From a330269efcaefd5dac68e80cb0c3993c4a303f32 Mon Sep 17 00:00:00 2001 From: mark Date: Thu, 27 Nov 2025 15:17:31 +0000 Subject: [PATCH 1/2] feat: Implement `xsd:negativeInteger` codec --- CHANGELOG.md | 1 + README.md | 2 +- lib/src/codecs/codecs.dart | 1 + .../negative_integer_codec.dart | 18 +++++++++++ .../negative_integer_decoder.dart | 32 +++++++++++++++++++ .../negative_integer_encoder.dart | 18 +++++++++++ test/codecs/negative_integer_codec_test.dart | 27 ++++++++++++++++ 7 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 lib/src/codecs/negative_integer/negative_integer_codec.dart create mode 100644 lib/src/codecs/negative_integer/negative_integer_decoder.dart create mode 100644 lib/src/codecs/negative_integer/negative_integer_encoder.dart create mode 100644 test/codecs/negative_integer_codec_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e6db82..19c114f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,3 +33,4 @@ - Implement `xsd:float` codec - Implement `xsd:unsignedInt` codec - Implement `xsd:integer` codec +- Implement `xsd:negativeInteger` codec diff --git a/README.md b/README.md index e353563..9c017b4 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ This library aims to support the following XSD 1.1 built-in datatypes that are c | `xsd:float` | ✅ | ✅ | `double` | `dart:core` | | `xsd:integer` | ✅ | ✅ | `BigInt` | `dart:core` | | `xsd:nonPositiveInteger` | ✅ | ✅ | `BigInt` | `dart:core` | -| `xsd:negativeInteger` | ✅ | ❌ | `BigInt` | `dart:core` | +| `xsd:negativeInteger` | ✅ | ✅ | `BigInt` | `dart:core` | | `xsd:long` | ✅ | ✅ | `BigInt` | `dart:core` | | `xsd:int` | ✅ | ✅ | `int` | `dart:core` | | `xsd:short` | ✅ | ✅ | `int` | `dart:core` | diff --git a/lib/src/codecs/codecs.dart b/lib/src/codecs/codecs.dart index 4aac7f6..65d893f 100644 --- a/lib/src/codecs/codecs.dart +++ b/lib/src/codecs/codecs.dart @@ -30,3 +30,4 @@ export 'double/double_codec.dart'; export 'float/float_codec.dart'; export 'integer/integer_codec.dart'; export 'unsigned_int/unsigned_int_codec.dart'; +export 'negative_integer/negative_integer_codec.dart'; diff --git a/lib/src/codecs/negative_integer/negative_integer_codec.dart b/lib/src/codecs/negative_integer/negative_integer_codec.dart new file mode 100644 index 0000000..55cd4e7 --- /dev/null +++ b/lib/src/codecs/negative_integer/negative_integer_codec.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; + +import 'package:xsd/src/codecs/negative_integer/negative_integer_decoder.dart'; +import 'package:xsd/src/codecs/negative_integer/negative_integer_encoder.dart'; + +/// A codec for xsd:negativeInteger. +/// +/// Converts between a string representation of a negative integer and a +/// [BigInt]. +class XsdNegativeIntegerCodec extends Codec { + const XsdNegativeIntegerCodec(); + + @override + Converter get decoder => const XsdNegativeIntegerDecoder(); + + @override + Converter get encoder => const XsdNegativeIntegerEncoder(); +} diff --git a/lib/src/codecs/negative_integer/negative_integer_decoder.dart b/lib/src/codecs/negative_integer/negative_integer_decoder.dart new file mode 100644 index 0000000..7b5186e --- /dev/null +++ b/lib/src/codecs/negative_integer/negative_integer_decoder.dart @@ -0,0 +1,32 @@ +import 'dart:convert'; + +import '../../helpers/whitespace.dart'; + +class XsdNegativeIntegerDecoder extends Converter { + const XsdNegativeIntegerDecoder(); + + static final BigInt _maxValue = BigInt.from(-1); + + @override + BigInt convert(String input) { + final str = processWhiteSpace(input, Whitespace.collapse); + + if (str.isEmpty) { + throw const FormatException('The input string cannot be empty.'); + } + + final value = BigInt.tryParse(str); + + if (value == null) { + throw FormatException('The input "$str" is not a valid integer.'); + } + + if (value > _maxValue) { + throw FormatException( + 'The value "$value" must be less than or equal to $_maxValue.', + ); + } + + return value; + } +} diff --git a/lib/src/codecs/negative_integer/negative_integer_encoder.dart b/lib/src/codecs/negative_integer/negative_integer_encoder.dart new file mode 100644 index 0000000..ba682d8 --- /dev/null +++ b/lib/src/codecs/negative_integer/negative_integer_encoder.dart @@ -0,0 +1,18 @@ +import 'dart:convert'; + +class XsdNegativeIntegerEncoder extends Converter { + const XsdNegativeIntegerEncoder(); + + static final BigInt _maxValue = BigInt.from(-1); + + @override + String convert(BigInt input) { + if (input > _maxValue) { + throw FormatException( + 'The value "$input" must be less than or equal to $_maxValue.', + ); + } + + return input.toString(); + } +} diff --git a/test/codecs/negative_integer_codec_test.dart b/test/codecs/negative_integer_codec_test.dart new file mode 100644 index 0000000..33ed727 --- /dev/null +++ b/test/codecs/negative_integer_codec_test.dart @@ -0,0 +1,27 @@ +import 'package:test/test.dart'; +import 'package:xsd/xsd.dart'; + +void main() { + group('XsdNegativeIntegerCodec', () { + const codec = XsdNegativeIntegerCodec(); + + test('should encode valid negative integer', () { + expect(codec.encode(BigInt.from(-1)), '-1'); + expect(codec.encode(BigInt.from(-123)), '-123'); + }); + + test('should decode valid negative integer', () { + expect(codec.decode('-1'), BigInt.from(-1)); + expect(codec.decode('-123'), BigInt.from(-123)); + expect(codec.decode(' -123 '), BigInt.from(-123)); + }); + + test('should throw on invalid negative integer', () { + expect(() => codec.decode('0'), throwsFormatException); + expect(() => codec.decode('1'), throwsFormatException); + expect(() => codec.decode('abc'), throwsFormatException); + expect(() => codec.encode(BigInt.zero), throwsFormatException); + expect(() => codec.encode(BigInt.one), throwsFormatException); + }); + }); +} From 9fd24bc65ad88926a15dce91fbfd3e37f5d99cd7 Mon Sep 17 00:00:00 2001 From: mark-dropbear <76698672+mark-dropbear@users.noreply.github.com> Date: Thu, 27 Nov 2025 15:19:18 +0000 Subject: [PATCH 2/2] Update test/codecs/negative_integer_codec_test.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- test/codecs/negative_integer_codec_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/codecs/negative_integer_codec_test.dart b/test/codecs/negative_integer_codec_test.dart index 33ed727..ba9abd9 100644 --- a/test/codecs/negative_integer_codec_test.dart +++ b/test/codecs/negative_integer_codec_test.dart @@ -20,6 +20,8 @@ void main() { expect(() => codec.decode('0'), throwsFormatException); expect(() => codec.decode('1'), throwsFormatException); expect(() => codec.decode('abc'), throwsFormatException); + expect(() => codec.decode(''), throwsFormatException); + expect(() => codec.decode(' '), throwsFormatException); expect(() => codec.encode(BigInt.zero), throwsFormatException); expect(() => codec.encode(BigInt.one), throwsFormatException); });