crates/zu-common/src/decimal.rs says MAX_DIGITS is 38, which is the widest decimal this engine holds and the widest DECIMAL(p, s) that may be declared. Decimal::parse does not compare what it built against it.
The limit that actually applies inside parse is the i128, which holds up to about 1.70e38. A 39 digit number below that fits:
let d = Decimal::parse(&"1".repeat(39), 0).unwrap();
assert_eq!(d.digits(), 39); // wider than MAX_DIGITS, and parsed anyway
So the value is one the engine will not store, handed back by the function whose job is to say whether the text is a decimal this engine holds. Every client that parses text has to add the check itself, and one that forgets gets a value that fails later and somewhere else.
Two things would fix it, and they are worth having together:
parse refuses a result whose digits() exceeds MAX_DIGITS, the same way it already refuses an overflow.
- A constructor that reads the scale out of the text rather than taking it as an argument.
parse takes a scale, so a caller who has only text has to count the digits after the point, apply any exponent to that count, and hand the answer back to the function that is about to read the same text. zu-go, zu-node and zu-python each reimplemented that arithmetic, three times, three ways.
Found while adding decimal support to the three clients.
crates/zu-common/src/decimal.rssaysMAX_DIGITSis 38, which is the widest decimal this engine holds and the widestDECIMAL(p, s)that may be declared.Decimal::parsedoes not compare what it built against it.The limit that actually applies inside
parseis thei128, which holds up to about 1.70e38. A 39 digit number below that fits:So the value is one the engine will not store, handed back by the function whose job is to say whether the text is a decimal this engine holds. Every client that parses text has to add the check itself, and one that forgets gets a value that fails later and somewhere else.
Two things would fix it, and they are worth having together:
parserefuses a result whosedigits()exceedsMAX_DIGITS, the same way it already refuses an overflow.parsetakes a scale, so a caller who has only text has to count the digits after the point, apply any exponent to that count, and hand the answer back to the function that is about to read the same text. zu-go, zu-node and zu-python each reimplemented that arithmetic, three times, three ways.Found while adding decimal support to the three clients.