refactor: improve `parseFixed` logic and add comprehensive unit tests for edge cases (#2661)

Konstantin Ullrich committed Nov 19, 2025 at 13:11 UTC c613e59cf45f005412f79dd7b404fc43e209e04f
2 files changed +42 -6
cw_core/lib/parse_fixed.dart
+4 -6
@@ -1,14 +1,13 @@
1 -BigInt parseFixed(String value, int? decimals) {
2 - decimals ??= 0;
1 +BigInt parseFixed(String value, int decimals) {
2 final multiplier = getMultiplier(decimals);
3
5 -// Is it negative?
6 - final negative = (value.substring(0, 1) == "-");
4 + final negative = value.startsWith("-");
5 if (negative) value = value.substring(1);
6
7 if (value == ".") throw Exception("missing value, value, $value");
8
11 -// Split it into a whole and fractional part
9 + if (value.startsWith(".")) value = "0$value";
10 +
11 final comps = value.split(".");
12 if (comps.length > 2) {
13 throw Exception("too many decimal points, value, $value");
@@ -17,7 +16,6 @@ BigInt parseFixed(String value, int? decimals) {
16 var whole = comps.isNotEmpty ? comps[0] : "0";
17 var fraction = (comps.length == 2 ? comps[1] : "0").padRight(decimals, "0");
18
20 - // Check the fraction doesn't exceed our decimals size
19 if (fraction.length > multiplier.length - 1) {
20 throw Exception(
21 "fractional component exceeds decimals, underflow, parseFixed");
cw_core/test/parse_fixed_test.dart new
+38
@@ -0,0 +1,38 @@
1 +import 'package:cw_core/parse_fixed.dart';
2 +import 'package:flutter_test/flutter_test.dart';
3 +
4 +void main() {
5 + group('parseFixed', () {
6 + group('parseFixed, positive', () {
7 + test('should parse 1.000001 as 1000001',
8 + () => expect(parseFixed("1.000001", 6), BigInt.from(1000001)));
9 +
10 + test('should parse 1 as 1000000', () => expect(parseFixed("1", 6), BigInt.from(1000000)));
11 +
12 + test('should parse 1. as 1000000', () => expect(parseFixed("1.", 6), BigInt.from(1000000)));
13 +
14 + test('should parse 1.1 as 1100000', () => expect(parseFixed("1.1", 6), BigInt.from(1100000)));
15 +
16 + test('should parse 01.1 as 1100000',
17 + () => expect(parseFixed("01.1", 6), BigInt.from(1100000)));
18 +
19 + test('should parse 1100000 as 11000000',
20 + () => expect(parseFixed("1100000", 1), BigInt.from(11000000)));
21 + });
22 +
23 + group('parseFixed, negative', () {
24 + test('should parse -1.000001 as -1000001',
25 + () => expect(parseFixed("-1.000001", 6), BigInt.from(-1000001)));
26 +
27 + test('should parse -1 as 1000000', () => expect(parseFixed("-1", 6), BigInt.from(-1000000)));
28 + });
29 +
30 + group('parseFixed, no leading 0', () {
31 + test('should parse .000001 as 1', () => expect(parseFixed(".000001", 6), BigInt.from(1)));
32 +
33 + test('should parse .00002 as 20', () => expect(parseFixed(".00002", 6), BigInt.from(20)));
34 +
35 + test('should parse -.00002 as -20', () => expect(parseFixed("-.00002", 6), BigInt.from(-20)));
36 + });
37 + });
38 +}