Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@
- Implement `xsd:double` codec
- Implement `xsd:float` codec
- Implement `xsd:unsignedInt` codec
- Implement `xsd:integer` codec
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` |
Expand Down Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions lib/src/codecs/codecs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
15 changes: 15 additions & 0 deletions lib/src/codecs/integer/integer_codec.dart
Original file line number Diff line number Diff line change
@@ -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<BigInt, String> {
const XsdIntegerCodec();

@override
Converter<BigInt, String> get encoder => const XsdIntegerEncoder();

@override
Converter<String, BigInt> get decoder => const XsdIntegerDecoder();
}
18 changes: 18 additions & 0 deletions lib/src/codecs/integer/integer_decoder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'dart:convert';

import '../../helpers/whitespace.dart';

class XsdIntegerDecoder extends Converter<String, BigInt> {
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);
}
}
8 changes: 8 additions & 0 deletions lib/src/codecs/integer/integer_encoder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'dart:convert';

class XsdIntegerEncoder extends Converter<BigInt, String> {
const XsdIntegerEncoder();

@override
String convert(BigInt input) => input.toString();
}
26 changes: 26 additions & 0 deletions test/codecs/integer_codec_test.dart
Original file line number Diff line number Diff line change
@@ -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);
Comment on lines +22 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve test coverage, it would be good to add test cases for empty and whitespace-only strings, as these are important edge cases for the decoder.

      expect(() => codec.decode('12.3'), throwsFormatException);
      expect(() => codec.decode('abc'), throwsFormatException);
      expect(() => codec.decode(''), throwsFormatException);
      expect(() => codec.decode('   '), throwsFormatException);

});
});
}