diff --git a/CHANGELOG.md b/CHANGELOG.md index ed407d4..55c1380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,15 @@ -## 0.1.0 -Initial release - -## 0.2.0-beta +## [1.0.0] +Stable, null-safe release +### Changed +- Requires Dart version >= 2.12 +## [0.2.0-beta] +### Changed - Refactored access to class values. Both ISO and user-assigned codes are accessible through `values` list. -- added `index` getter to match enum behaviour -- added `symbol` getter +### Added +- `index` getter to match enum behaviour +- `symbol` getter + +## [0.1.0] +Initial release \ No newline at end of file diff --git a/README.md b/README.md index ade5075..e72aa1d 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ if (code == CountryCode.US) { print(code.numeric); } ``` -[See more examples](https://github.com/denixport/dart.country/tree/master/example) - +[See more examples][examples] ## Bugs and feature requests Please file feature requests and bugs at the [issue tracker][tracker]. +[examples]: https://github.com/denixport/dart.country/tree/master/example [tracker]: https://github.com/denixport/dart.country/issues diff --git a/analysis_options.yaml b/analysis_options.yaml index 49ddaec..0372bca 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -6,12 +6,11 @@ analyzer: implicit-dynamic: false errors: dead_code: error - missing_required_param: warning - missing_return: warning - override_on_non_overriding_method: warning + missing_required_param: error + missing_return: error todo: info unused_element: error - unused_import: warning + unused_import: error unused_local_variable: error linter: diff --git a/example/example.dart b/example/example.dart index 0e5abd0..7a4b280 100644 --- a/example/example.dart +++ b/example/example.dart @@ -7,20 +7,20 @@ void main() { print(CountryCode.US.symbol); // -> 🇺🇸 // The list of ISO-assigned codes are in CountryCode.values - var list = CountryCode.values.map((c) => c.alpha2).join(", "); + var list = CountryCode.values.map((c) => c.alpha2).join(', '); print(list); // You can statically access countries by alpha-2, alpha-3, or numeric code // That's also helpful to get other ISO codes for known code - print(CountryCode.ofAlpha("US").alpha2); // -> US - print(CountryCode.ofAlpha("USA").alpha2); // -> US + print(CountryCode.ofAlpha('US').alpha2); // -> US + print(CountryCode.ofAlpha('USA').alpha2); // -> US print(CountryCode.ofNumeric(840).alpha2); // -> US // Always same values for the same country code is returned - print(identical(CountryCode.ofAlpha("US"), CountryCode.US)); // -> true + print(identical(CountryCode.ofAlpha('US'), CountryCode.US)); // -> true // You can also parse alpha-2, alpha-3, or numeric code - print(CountryCode.parse("US").alpha2); // -> US - print(CountryCode.parse("USA").alpha2); // -> US - print(CountryCode.parse("840").alpha2); // -> US + print(CountryCode.parse('US').alpha2); // -> US + print(CountryCode.parse('USA').alpha2); // -> US + print(CountryCode.parse('840').alpha2); // -> US } diff --git a/example/user_example.dart b/example/user_example.dart index 525ae4c..3bcacb0 100644 --- a/example/user_example.dart +++ b/example/user_example.dart @@ -4,28 +4,28 @@ void main() { CountryCode c1, c2, c3, c4, c5; // Create values with custom codes (From ISO defined code range) - c1 = CountryCode.user(alpha2: "AA"); + c1 = CountryCode.user(alpha2: 'AA'); print(c1.alpha2); // -> AA - print(c1.alpha3); // -> + print(c1.alpha3); // -> print(c1.numeric); // -> 0 - + // Country values for the same code are equal, but not the same object - c1 = CountryCode.user(alpha3: "XAA"); - c2 = CountryCode.user(alpha3: "XAA"); + c1 = CountryCode.user(alpha3: 'XAA'); + c2 = CountryCode.user(alpha3: 'XAA'); print(c1 == c2); // -> true print(identical(c1, c2)); // -> false - // You need to assign country code using static method assign(), + // You need to assign country code using static method assign(), // to be able to use parsing and static accessors for the code. - int index = CountryCode.assign(alpha3: "XAA", numeric: 901); + var index = CountryCode.assign(alpha3: 'XAA', numeric: 901); print(index); // -> 0 print(CountryCode.userValues); // -> [Country.XXA] c1 = CountryCode.userValues[index]; - c2 = CountryCode.ofAlpha("XAA"); + c2 = CountryCode.ofAlpha('XAA'); c3 = CountryCode.ofNumeric(901); - c4 = CountryCode.parse("XAA"); - c5 = CountryCode.parse("901"); + c4 = CountryCode.parse('XAA'); + c5 = CountryCode.parse('901'); print(identical(c1, c2)); // -> true print(identical(c2, c3)); // -> true @@ -36,7 +36,6 @@ void main() { CountryCode.unassignAll(); print(CountryCode.userValues.length); // -> 0 - // Now you can not parse or get value for the code 'XAA' - print(CountryCode.tryParse("XAA")); // - null - + // Now you can not parse or get value for the code 'XAA' + print(CountryCode.tryParse('XAA')); // - null } diff --git a/lib/src/country_code.dart b/lib/src/country_code.dart index 82df885..27c3ecd 100644 --- a/lib/src/country_code.dart +++ b/lib/src/country_code.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2019, Denis Portnov. All rights reserved. +// Copyright (c) 2019-2021, Denis Portnov. All rights reserved. // Released under MIT License that can be found in the LICENSE file. /// @@ -19,62 +19,55 @@ class CountryCode { const CountryCode._(this._code); /// Creates user-defined country code. - /// Note: Code is not registered in class `values`, use `assign` to + /// Note: Code is not registered in class `values`, use `assign` to /// register user country codes. - factory CountryCode.user({String alpha2, String alpha3, int numeric}) { + factory CountryCode.user({String? alpha2, String? alpha3, int? numeric}) { assert(!(alpha2 == null && alpha3 == null && numeric == null)); assert(alpha2 == null || alpha2.length >= 2); assert(alpha3 == null || alpha3.length >= 3); - int a2 = 0; - int a3 = 0; - - // checks + var a2 = 0; if (alpha2 != null) { a2 = _packAlpha2(alpha2.codeUnits); if (!_isInRange(a2, _userA2Ranges)) { - throw ArgumentError("Alpha-2 code is not in allowed range"); + throw ArgumentError('Alpha-2 code is not in allowed range'); } } - // alpha-2 + var a3 = 0; if (alpha3 != null) { a3 = _packAlpha3(alpha3.codeUnits); if (!_isInRange(a3, _userA3Ranges)) { - throw ArgumentError("Alpha-3 code is not in allowed range"); + throw ArgumentError('Alpha-3 code is not in allowed range'); } } - // numeric if (numeric != null && (numeric < 900 || numeric > 999)) { throw ArgumentError.value( - numeric, "numeric", "Should be between 900..999"); + numeric, 'numeric', 'Should be between 900..999'); } numeric ??= 0; - int code; - if ((1 << 32) != 0) { - code = a2 | a3 | numeric; - } else { - code = a2 + (a3 | numeric); + if ((1 << 32) == 0) { + return CountryCode._(a2 + (a3 | numeric)); } - return CountryCode._(code); + return CountryCode._(a2 | a3 | numeric); } /// Alpha-2 code as defined in (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2] /// Returns empty string for user-assigned values that doesn't have alpha-2 code String get alpha2 { _unpackAlpha2(_code); - return (_a2cu[0] != _baseChar) ? String.fromCharCodes(_a2cu) : ""; + return (_a2cu[0] != _baseChar) ? String.fromCharCodes(_a2cu) : ''; } /// Alpha-3 code as defined in (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3] /// Returns empty string for user-assigned values that doesn't have alpha-3 code String get alpha3 { _unpackAlpha3(_code); - return (_a3cu[0] != _baseChar) ? String.fromCharCodes(_a3cu) : ""; + return (_a3cu[0] != _baseChar) ? String.fromCharCodes(_a3cu) : ''; } /// Numeric code as defined in (ISO 3166-1)[https://en.wikipedia.org/wiki/ISO_3166-1_numeric] @@ -85,28 +78,28 @@ class CountryCode { /// Returns unicode symbol for country code String get symbol { - const int base = 0x1f1a5; + const base = 0x1f1a5; if (_code & 0x3ff != 0) { _unpackAlpha2(_code); return String.fromCharCodes([base + _a2cu[0], base + _a2cu[1]]); } - return ""; + return ''; } /// Returns `true` if the code is official ISO-assigned bool get isOfficial { - int n = _code & 0x3ff; + var n = _code & 0x3ff; return n > 0 && n < 900; } /// Returns `true` if the code is user-assigned. /// See (User-assigned code elements)[https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#User-assigned_code_elements] bool get isUserAssigned { - int n = _code & 0x3ff; + var n = _code & 0x3ff; return n == 0 || n >= 900; } - /// Returns position of the value in list of all country codes. + /// Returns position of the value in list of all country codes. int get index => values.indexOf(this); @override @@ -116,7 +109,7 @@ class CountryCode { bool operator ==(Object other) => other is CountryCode && _code == other._code; - /// Returns string representation of CountryCode object. + /// Returns string representation of `CountryCode`. /// Which is `CountryCode.` followed by either alpha-2, alpha-2, or numeric code /// depeding on which code is defined. /// For ISO-assigned country codes it alwais returns `CountryCode.` + alpha-2. @@ -135,16 +128,16 @@ class CountryCode { return String.fromCharCodes(cu + _a3cu); } - int n = _code & 0x3ff; + var n = _code & 0x3ff; if (n != 0) { - return String.fromCharCodes(cu + n.toString().padLeft(3, "0").codeUnits); + return String.fromCharCodes(cu + n.toString().padLeft(3, '0').codeUnits); } - assert(true, "Unreachable return"); - return "Country.UNKNOWN"; + assert(true, 'Unreachable return'); + return 'Country.UNKNOWN'; } - /// + /// List of all ISO-assigned country codes static List get values { if (_userValues.isNotEmpty) { return List.unmodifiable(_values + _userValues); @@ -174,7 +167,7 @@ class CountryCode { return _values[index]; } - throw ArgumentError("Alpha code \"$code\" is not assigned"); + throw ArgumentError('Alpha code \"$code\" is not assigned'); } /// Returns country code by numeric code @@ -194,12 +187,12 @@ class CountryCode { return _values[index]; } - throw ArgumentError("No country assigned for numeric code \"$code\""); + throw ArgumentError('No country assigned for numeric code \"$code\"'); } // returns index of numeric code in values list static int _indexOfNum(int code, List values) { - for (int i = 0; i < values.length; i++) { + for (var i = 0; i < values.length; i++) { if (values[i]._code & 0x3ff == code) { return i; } @@ -212,24 +205,24 @@ class CountryCode { /// or 2-3 digits of numeric code /// Throws `FormatException` if the code is not valid country code static CountryCode parse(String source) { - CountryCode c = _parse(source); + var c = _parse(source); if (c == null) { - throw FormatException("Invalid or non-assigned code", source); + throw FormatException('Invalid or non-assigned code', source); } return c; } /// Parses [source] as Alpha-2, alpha-3 or numeric country code. /// Same as [parse] but returns `null` in case of invalid country code - static CountryCode tryParse(String source) { + static CountryCode? tryParse(String source) { return _parse(source); } // - static CountryCode _parse(String code) { + static CountryCode? _parse(String code) { int index; - // try user-assigned alpha code + // first try user-assigned alpha code if (_userValues.isNotEmpty) { index = _parseAlpha(code, _userValues); if (index != -1) { @@ -265,7 +258,7 @@ class CountryCode { var cu = code.codeUnits; switch (cu.length) { case 2: - for (int i = 0; i < values.length; i++) { + for (var i = 0; i < values.length; i++) { _unpackAlpha2(values[i]._code); if (_a2cu[0] == cu[0] && _a2cu[1] == cu[1]) { return i; @@ -273,7 +266,7 @@ class CountryCode { } break; case 3: - for (int i = 0; i < values.length; i++) { + for (var i = 0; i < values.length; i++) { _unpackAlpha3(values[i]._code); if (_a3cu[0] == cu[0] && _a3cu[1] == cu[1] && _a3cu[2] == cu[2]) { return i; @@ -286,11 +279,11 @@ class CountryCode { // Parses numeric code, returns -1 for invalid or unassigned static int _parseNum(String code, List values) { - int n = int.tryParse(code); + var n = int.tryParse(code); if (n == null) { return -1; } - for (int i = 0; i < values.length; i++) { + for (var i = 0; i < values.length; i++) { if (values[i]._code & 0x3ff == n) { return i; } @@ -303,28 +296,28 @@ class CountryCode { /// Either one of 3 codes is required. /// After calling [assign] user-assigned codes are available through /// [parse], [tryParse], [ofAlpha], and [ofNumeric] static methods. - static int assign({String alpha2, String alpha3, int numeric}) { + static int assign({String? alpha2, String? alpha3, int? numeric}) { assert(!(alpha2 == null && alpha3 == null && numeric == null)); // check Alpha-2 if (alpha2 != null && (_parseAlpha(alpha2, _userValues) != -1 || _parseAlpha(alpha2, _values) != -1)) { - throw StateError("Alpha-2 code \"$alpha2\" is already assigned"); + throw StateError('Alpha-2 code \"$alpha2\" is already assigned'); } // check Alpha-3 if (alpha3 != null && (_parseAlpha(alpha3, _userValues) != -1 || _parseAlpha(alpha3, _values) != -1)) { - throw StateError("Alpha-3 code \"$alpha3\" is already assigned"); + throw StateError('Alpha-3 code \"$alpha3\" is already assigned'); } // check numeric if (numeric != null && (_indexOfNum(numeric, _userValues) != -1 || _indexOfNum(numeric, _values) != -1)) { - throw StateError("Numeric code \"$numeric\" is already assigned"); + throw StateError('Numeric code \"$numeric\" is already assigned'); } _userValues.add( @@ -374,7 +367,7 @@ class CountryCode { } static bool _isInRange(int code, List ranges) { - for (int i = 0; i < ranges.length - 1; i += 2) { + for (var i = 0; i < ranges.length - 1; i += 2) { if (code >= ranges[i] && code <= ranges[i + 1]) { return true; } diff --git a/pubspec.yaml b/pubspec.yaml index b71d62e..e57179c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,14 @@ name: country_code description: Provides list of ISO 3166-1 coutry codes in enum-like class, as well as parsing and user-assigned code elements -version: 0.2.0-beta +version: 1.0.0 author: Denis Portnov uploader: Denis Portnov homepage: https://github.com/denixport/dart.country environment: - sdk: '>=2.1.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dev_dependencies: - pedantic: ^1.0.0 - test: ^1.0.0 + pedantic: ^1.9.0 + test: '^1.16.0' + diff --git a/test/country_code_test.dart b/test/country_code_test.dart index bfa11a8..9559f24 100644 --- a/test/country_code_test.dart +++ b/test/country_code_test.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2019, Denis Portnov. All rights reserved. +// Copyright (c) 2019-2021, Denis Portnov. All rights reserved. // Released under MIT License that can be found in the LICENSE file. import 'package:country_code/country_code.dart'; @@ -8,9 +8,9 @@ import 'gold.dart'; void main() { group('ISO-assigned', () { test('Generated values are correct', () { - var lines = isoGold.split("\n"); - for (int i = 0; i < lines.length; i++) { - var fields = lines[i].split("\t"); + var lines = isoGold.split('\n'); + for (var i = 0; i < lines.length; i++) { + var fields = lines[i].split('\t'); var c = CountryCode.values[i]; expect(c.alpha2, fields[0]); @@ -23,9 +23,9 @@ void main() { }); test('Generated values are statically accesible', () { - var lines = isoGold.split("\n"); - for (int i = 0; i < lines.length; i++) { - var fields = lines[i].split("\t"); + var lines = isoGold.split('\n'); + for (var i = 0; i < lines.length; i++) { + var fields = lines[i].split('\t'); var n = int.parse(fields[2]); var c = CountryCode.values[i]; @@ -37,9 +37,8 @@ void main() { }); test('Can be printed', () { - expect(CountryCode.RU.toString(), "CountryCode.RU"); + expect(CountryCode.RU.toString(), 'CountryCode.RU'); }); - }); group('User-assigned', () { @@ -48,9 +47,9 @@ void main() { }); test('Can create user-assigned country code', () { - String a2 = "QP"; - String a3 = "QPX"; - int n = 910; + var a2 = 'QP'; + var a3 = 'QPX'; + var n = 910; var c = CountryCode.user(alpha2: a2, alpha3: a3, numeric: n); @@ -64,12 +63,12 @@ void main() { }); test('Can not create user-assigned country with out of range code', () { - const codesA2 = ["QL", "ZA"]; + const codesA2 = ['QL', 'ZA']; for (var code in codesA2) { expect(() => CountryCode.user(alpha2: code), throwsArgumentError); } - const codesA3 = ["QLA", "ZAA"]; + const codesA3 = ['QLA', 'ZAA']; for (var code in codesA3) { expect(() => CountryCode.user(alpha3: code), throwsArgumentError); } @@ -81,58 +80,58 @@ void main() { }); test('Can be assigned with Alpha-2 only', () { - String a2 = "QP"; + var a2 = 'QP'; - int index = CountryCode.assign(alpha2: a2); + var index = CountryCode.assign(alpha2: a2); var c = CountryCode.values[index]; expect(c.alpha2, a2); - expect(c.alpha3, ""); + expect(c.alpha3, ''); expect(c.numeric, 0); expect(c.isUserAssigned, isTrue); }); test('Can be assigned with Alpha-3 only', () { - String a3 = "XXZ"; + var a3 = 'XXZ'; - int index = CountryCode.assign(alpha3: a3); + var index = CountryCode.assign(alpha3: a3); var c = CountryCode.values[index]; - expect(c.alpha2, ""); + expect(c.alpha2, ''); expect(c.alpha3, a3); expect(c.numeric, 0); expect(c.isUserAssigned, isTrue); }); test('Can be assigned with numeric only', () { - int n = 999; + var n = 999; - int index = CountryCode.assign(numeric: n); + var index = CountryCode.assign(numeric: n); var c = CountryCode.values[index]; - expect(c.alpha2, ""); - expect(c.alpha3, ""); + expect(c.alpha2, ''); + expect(c.alpha3, ''); expect(c.numeric, n); expect(c.isUserAssigned, isTrue); }); test('Can not assign same user code more than once', () { - CountryCode.assign(alpha2: "XA", alpha3: "XAA", numeric: 900); - expect(() => CountryCode.assign(alpha2: "XA"), throwsStateError); + CountryCode.assign(alpha2: 'XA', alpha3: 'XAA', numeric: 900); + expect(() => CountryCode.assign(alpha2: 'XA'), throwsStateError); }); test('Can be checked for equality', () { - var c1 = CountryCode.user(alpha2: "ZZ"); - var c2 = CountryCode.user(alpha2: "ZZ"); + var c1 = CountryCode.user(alpha2: 'ZZ'); + var c2 = CountryCode.user(alpha2: 'ZZ'); expect(identical(c1, c2), isFalse); expect(c1, equals(c2)); }); test('Can be printed', () { - expect(CountryCode.user(alpha2: "ZZ").toString(), "CountryCode.ZZ"); - expect(CountryCode.user(alpha3: "ZZZ").toString(), "CountryCode.ZZZ"); - expect(CountryCode.user(numeric: 999).toString(), "CountryCode.999"); + expect(CountryCode.user(alpha2: 'ZZ').toString(), 'CountryCode.ZZ'); + expect(CountryCode.user(alpha3: 'ZZZ').toString(), 'CountryCode.ZZZ'); + expect(CountryCode.user(numeric: 999).toString(), 'CountryCode.999'); }); }); } diff --git a/test/gold.dart b/test/gold.dart index 6a083bf..3fe9260 100644 --- a/test/gold.dart +++ b/test/gold.dart @@ -1,5 +1,5 @@ -//Alpha-2 Alpha-2 Numeric -const isoGold = """ +//Alpha-2 Alpha-2 Numeric +const isoGold = ''' AD AND 20 AE ARE 784 AF AFG 4 @@ -248,4 +248,4 @@ YE YEM 887 YT MYT 175 ZA ZAF 710 ZM ZMB 894 -ZW ZWE 716"""; \ No newline at end of file +ZW ZWE 716''';