From c91654cefc05f6c75512b342e1ed8c38024d77f0 Mon Sep 17 00:00:00 2001 From: mark Date: Thu, 27 Nov 2025 14:46:02 +0000 Subject: [PATCH 1/3] Implement xsd:integer codec --- CHANGELOG.md | 1 + README.md | 2 +- lib/src/codecs/codecs.dart | 2 ++ lib/src/codecs/integer/integer_codec.dart | 15 ++++++++++++ lib/src/codecs/integer/integer_decoder.dart | 18 ++++++++++++++ lib/src/codecs/integer/integer_encoder.dart | 8 +++++++ test/codecs/integer_codec_test.dart | 26 +++++++++++++++++++++ 7 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 lib/src/codecs/integer/integer_codec.dart create mode 100644 lib/src/codecs/integer/integer_decoder.dart create mode 100644 lib/src/codecs/integer/integer_encoder.dart create mode 100644 test/codecs/integer_codec_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 4987633..f6f729c 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 \ No newline at end of file diff --git a/README.md b/README.md index 01c9f73..b96cd9e 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` | 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); + }); + }); +} From c27ce722f253bc1eb509fc474727eb38e4f32c49 Mon Sep 17 00:00:00 2001 From: mark-dropbear <76698672+mark-dropbear@users.noreply.github.com> Date: Thu, 27 Nov 2025 14:49:32 +0000 Subject: [PATCH 2/3] Update CHANGELOG.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6f729c..9e6db82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,4 +32,4 @@ - Implement `xsd:double` codec - Implement `xsd:float` codec - Implement `xsd:unsignedInt` codec -- Implement `xsd:integer` codec \ No newline at end of file +- Implement `xsd:integer` codec From 30328af18759b7b4b7f0c72571665100f513143b Mon Sep 17 00:00:00 2001 From: mark Date: Thu, 27 Nov 2025 14:51:57 +0000 Subject: [PATCH 3/3] Fix spacing on README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b96cd9e..e353563 100644 --- a/README.md +++ b/README.md @@ -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