diff --git a/CHANGELOG.md b/CHANGELOG.md index 4987633..9e6db82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,3 +32,4 @@ - Implement `xsd:double` codec - Implement `xsd:float` codec - Implement `xsd:unsignedInt` codec +- Implement `xsd:integer` codec diff --git a/README.md b/README.md index 01c9f73..e353563 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ This library aims to support the following XSD 1.1 built-in datatypes that are c | `xsd:decimal` | ✅ | ✅ | `Decimal` | `package:decimal` | | `xsd:double` | ✅ | ✅ | `double` | `dart:core` | | `xsd:float` | ✅ | ✅ | `double` | `dart:core` | -| `xsd:integer` | ✅ | ❌ | `BigInt` | `dart:core` | +| `xsd:integer` | ✅ | ✅ | `BigInt` | `dart:core` | | `xsd:nonPositiveInteger` | ✅ | ✅ | `BigInt` | `dart:core` | | `xsd:negativeInteger` | ✅ | ❌ | `BigInt` | `dart:core` | | `xsd:long` | ✅ | ✅ | `BigInt` | `dart:core` | @@ -77,7 +77,7 @@ This library aims to support the following XSD 1.1 built-in datatypes that are c ## Limitations * **Facets on Built-in Types**: This library focuses on implementing the XSD built-in datatypes as they are defined in the "XML Schema Part 2: Datatypes" specification. This includes their inherent properties, lexical spaces, value spaces, and any *fixed* facets that define them (e.g., the range of `xsd:byte` or the `whiteSpace` behavior of `xsd:token`). - * The library currently **does not** provide a mechanism to dynamically apply arbitrary constraining facets (like `minLength`, `maxLength`, `pattern`, `enumeration`, `totalDigits`, `fractionDigits` beyond what defines a base type) to create new, user-defined derived simple types *at runtime through the codec*. For instance, while `xsd:string` is supported, you cannot pass `maxLength="5"` to the `XsdStringCodec` to validate against this specific restriction dynamically. Such validation would typically be handled by a higher-level XSD schema processor that uses this library for the base datatype conversions. +* The library currently **does not** provide a mechanism to dynamically apply arbitrary constraining facets (like `minLength`, `maxLength`, `pattern`, `enumeration`, `totalDigits`, `fractionDigits` beyond what defines a base type) to create new, user-defined derived simple types *at runtime through the codec*. For instance, while `xsd:string` is supported, you cannot pass `maxLength="5"` to the `XsdStringCodec` to validate against this specific restriction dynamically. Such validation would typically be handled by a higher-level XSD schema processor that uses this library for the base datatype conversions. ## Usage diff --git a/lib/src/codecs/codecs.dart b/lib/src/codecs/codecs.dart index 6193d6d..4aac7f6 100644 --- a/lib/src/codecs/codecs.dart +++ b/lib/src/codecs/codecs.dart @@ -28,3 +28,5 @@ export 'any_uri/any_uri_codec.dart'; export 'decimal/decimal_codec.dart'; export 'double/double_codec.dart'; export 'float/float_codec.dart'; +export 'integer/integer_codec.dart'; +export 'unsigned_int/unsigned_int_codec.dart'; diff --git a/lib/src/codecs/integer/integer_codec.dart b/lib/src/codecs/integer/integer_codec.dart new file mode 100644 index 0000000..f43051e --- /dev/null +++ b/lib/src/codecs/integer/integer_codec.dart @@ -0,0 +1,15 @@ +import 'dart:convert'; + +import 'package:xsd/src/codecs/integer/integer_decoder.dart'; +import 'package:xsd/src/codecs/integer/integer_encoder.dart'; + +/// A [Codec] that converts between XSD `integer` strings and [BigInt] objects. +class XsdIntegerCodec extends Codec { + const XsdIntegerCodec(); + + @override + Converter get encoder => const XsdIntegerEncoder(); + + @override + Converter get decoder => const XsdIntegerDecoder(); +} diff --git a/lib/src/codecs/integer/integer_decoder.dart b/lib/src/codecs/integer/integer_decoder.dart new file mode 100644 index 0000000..80f20d9 --- /dev/null +++ b/lib/src/codecs/integer/integer_decoder.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; + +import '../../helpers/whitespace.dart'; + +class XsdIntegerDecoder extends Converter { + const XsdIntegerDecoder(); + + @override + BigInt convert(String input) { + final trimmed = processWhiteSpace(input, Whitespace.collapse); + + if (trimmed.isEmpty) { + throw const FormatException('The input string cannot be empty.'); + } + + return BigInt.parse(trimmed); + } +} diff --git a/lib/src/codecs/integer/integer_encoder.dart b/lib/src/codecs/integer/integer_encoder.dart new file mode 100644 index 0000000..6714186 --- /dev/null +++ b/lib/src/codecs/integer/integer_encoder.dart @@ -0,0 +1,8 @@ +import 'dart:convert'; + +class XsdIntegerEncoder extends Converter { + const XsdIntegerEncoder(); + + @override + String convert(BigInt input) => input.toString(); +} diff --git a/test/codecs/integer_codec_test.dart b/test/codecs/integer_codec_test.dart new file mode 100644 index 0000000..bf37572 --- /dev/null +++ b/test/codecs/integer_codec_test.dart @@ -0,0 +1,26 @@ +import 'package:test/test.dart'; +import 'package:xsd/xsd.dart'; + +void main() { + group('XsdIntegerCodec', () { + const codec = XsdIntegerCodec(); + + test('should encode valid integer', () { + expect(codec.encode(BigInt.from(123)), '123'); + expect(codec.encode(BigInt.from(-123)), '-123'); + expect(codec.encode(BigInt.zero), '0'); + }); + + test('should decode valid integer', () { + expect(codec.decode('123'), BigInt.from(123)); + expect(codec.decode('-123'), BigInt.from(-123)); + expect(codec.decode('0'), BigInt.zero); + expect(codec.decode(' +123 '), BigInt.from(123)); + }); + + test('should throw on invalid integer', () { + expect(() => codec.decode('12.3'), throwsFormatException); + expect(() => codec.decode('abc'), throwsFormatException); + }); + }); +}