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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@
- Implement `xsd:duration` codec and data type
- Implement `xsd:datetime` codec and data type
- Implement `xsd:anyUri` codec
- Implement `xsd:decimal` codec
- Implement `xsd:decimal` codec
- Implement `xsd:double` codec
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ This library aims to support the following XSD 1.1 built-in datatypes that are c
| `xsd:language` | ✅ | ✅ | `Locale` | `package:intl` |
| `xsd:NCName` | ✅ | ✅ | `String` | `dart:core` |
| `xsd:decimal` | ✅ | ✅ | `Decimal` | `package:decimal` |
| `xsd:double` | ✅ | ❌ | `double` | `dart:core` |
| `xsd:double` | ✅ | ✅ | `double` | `dart:core` |
| `xsd:float` | ✅ | ❌ | `double` | `dart:core` |
| `xsd:integer` | ✅ | ❌ | `BigInt` | `dart:core` |
| `xsd:nonPositiveInteger` | ✅ | ✅ | `BigInt` | `dart:core` |
Expand Down
1 change: 1 addition & 0 deletions lib/src/codecs/codecs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ export 'duration/xsd_duration_codec.dart';
export 'datetime/xsd_datetime_codec.dart';
export 'any_uri/any_uri_codec.dart';
export 'decimal/decimal_codec.dart';
export 'double/double_codec.dart';
42 changes: 42 additions & 0 deletions lib/src/codecs/double/double_codec.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'dart:convert';

import 'package:xsd/src/helpers/whitespace.dart';

/// A [Codec] that converts between XSD `double` strings and [double] values.
class XsdDoubleCodec extends Codec<double, String> {
const XsdDoubleCodec();

@override
Converter<double, String> get encoder => const XsdDoubleEncoder();

@override
Converter<String, double> get decoder => const XsdDoubleDecoder();
}

class XsdDoubleEncoder extends Converter<double, String> {
const XsdDoubleEncoder();

@override
String convert(double input) {
if (input.isNaN) return 'NaN';
if (input == double.infinity) return 'INF';
if (input == double.negativeInfinity) return '-INF';
// Dart's toString() might produce scientific notation 1.2e+3, XSD accepts 1.2E3 or 1.2e3.
// XSD canonical form uses 'E'.
return input.toString().toUpperCase();
}
}

class XsdDoubleDecoder extends Converter<String, double> {
const XsdDoubleDecoder();

@override
double convert(String input) {
final trimmed = processWhiteSpace(input, Whitespace.collapse);
if (trimmed == 'INF') return double.infinity;
if (trimmed == '-INF') return double.negativeInfinity;
if (trimmed == 'NaN') return double.nan;

return double.parse(trimmed);
}
}
37 changes: 37 additions & 0 deletions test/codecs/double_codec_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:test/test.dart';
import 'package:xsd/xsd.dart';

void main() {
group('XsdDoubleCodec', () {
const codec = XsdDoubleCodec();

test('should encode valid double', () {
expect(codec.encode(123.45), '123.45');
expect(codec.encode(-123.45), '-123.45');
expect(codec.encode(double.infinity), 'INF');
expect(codec.encode(double.negativeInfinity), '-INF');
expect(codec.encode(double.nan), 'NaN');
Comment thread
mark-dropbear marked this conversation as resolved.
expect(codec.encode(double.nan), 'NaN');
});

test('should decode valid double', () {
expect(codec.decode('123.45'), 123.45);
expect(codec.decode('-123.45'), -123.45);
expect(codec.decode('INF'), double.infinity);
expect(codec.decode('-INF'), double.negativeInfinity);
expect(codec.decode('NaN').isNaN, isTrue);
expect(codec.decode('1.2E3'), 1200.0);
expect(codec.decode('1.2e3'), 1200.0);
});
Comment thread
mark-dropbear marked this conversation as resolved.

test('should handle whitespace collapsing', () {
expect(codec.decode(' 123.45 '), 123.45);
expect(codec.decode('\n-123.45\t'), -123.45);
});

test('should throw FormatException for invalid input', () {
expect(() => codec.decode('invalid'), throwsFormatException);
expect(() => codec.decode('1.2.3'), throwsFormatException);
});
});
}