From 410017492247e8e2d95520af116f76bde80ebacc Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 27 Dec 2025 14:05:41 +0000 Subject: [PATCH 1/2] Update the float codec to respect 32 bit precision limitations --- lib/src/codecs/float/float_codec.dart | 18 +++++++----------- test/codecs/float_codec_test.dart | 8 ++++++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/src/codecs/float/float_codec.dart b/lib/src/codecs/float/float_codec.dart index 21ffd35..609d086 100644 --- a/lib/src/codecs/float/float_codec.dart +++ b/lib/src/codecs/float/float_codec.dart @@ -59,35 +59,31 @@ class XsdFloatDecoder extends Converter { if (trimmed == 'INF') return double.infinity; if (trimmed == '-INF') return double.negativeInfinity; if (trimmed == 'NaN') return double.nan; - final value = double.tryParse(trimmed); - if (value == null) { throw FormatException('Invalid XSD float value: "$input"'); } - - // Dart's double is 64-bit. We need to validate that the value - // fits within the 32-bit float value space as defined by XSD. if (value.isFinite) { - // Use Float32List to check for overflow. + // Use Float32List to force rounding to 32-bit precision final f32 = Float32List(1); f32[0] = value; - - // If the conversion results in infinity, but the original was not, it's an overflow. + // Check for overflow (if 32-bit rounded value became infinite) if (f32[0].isInfinite) { throw FormatException( 'The literal "$input" is outside the value range of float (overflow).', ); } - - // If the conversion results in 0, but the original was not, it's an underflow. + // Check for underflow (if 32-bit rounded value became zero but original wasn't) + // Note: We compare f32[0] because that's the value we are about to return. if (value != 0.0 && f32[0] == 0.0) { throw FormatException( 'The literal "$input" is outside the value range of float (underflow).', ); } - } + // FIX: Return the 32-bit rounded value. + return f32[0]; + } return value; } } diff --git a/test/codecs/float_codec_test.dart b/test/codecs/float_codec_test.dart index d74fa7b..17204e1 100644 --- a/test/codecs/float_codec_test.dart +++ b/test/codecs/float_codec_test.dart @@ -1,3 +1,5 @@ +import 'dart:typed_data'; + import 'package:test/test.dart'; import 'package:xsd/xsd.dart'; @@ -48,8 +50,10 @@ void main() { group('decoder', () { test('should decode valid float strings', () { - expect(codec.decode('123.45'), 123.45); - expect(codec.decode(' -123.45 '), -123.45); + final f32_123_45 = Float32List(1)..[0] = 123.45; + expect(codec.decode('123.45'), f32_123_45[0]); + final f32Neg12345 = Float32List(1)..[0] = -123.45; + expect(codec.decode(' -123.45 '), f32Neg12345[0]); expect(codec.decode('INF'), double.infinity); expect(codec.decode(' -INF '), double.negativeInfinity); expect(codec.decode('NaN').isNaN, isTrue); From 32754c2ac0c95bfef211c936a38134d2e5ad55e3 Mon Sep 17 00:00:00 2001 From: mark-dropbear <76698672+mark-dropbear@users.noreply.github.com> Date: Sat, 27 Dec 2025 14:33:27 +0000 Subject: [PATCH 2/2] Update test/codecs/float_codec_test.dart As per code review to improve readability Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- test/codecs/float_codec_test.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/codecs/float_codec_test.dart b/test/codecs/float_codec_test.dart index 17204e1..7ae8ae4 100644 --- a/test/codecs/float_codec_test.dart +++ b/test/codecs/float_codec_test.dart @@ -50,10 +50,10 @@ void main() { group('decoder', () { test('should decode valid float strings', () { - final f32_123_45 = Float32List(1)..[0] = 123.45; - expect(codec.decode('123.45'), f32_123_45[0]); - final f32Neg12345 = Float32List(1)..[0] = -123.45; - expect(codec.decode(' -123.45 '), f32Neg12345[0]); + double toFloat32(double value) => (Float32List(1)..[0] = value)[0]; + + expect(codec.decode('123.45'), toFloat32(123.45)); + expect(codec.decode(' -123.45 '), toFloat32(-123.45)); expect(codec.decode('INF'), double.infinity); expect(codec.decode(' -INF '), double.negativeInfinity); expect(codec.decode('NaN').isNaN, isTrue);