///|
// Validate the original numeric token with decimal digits, so IEEE-754
// rounding/underflow cannot turn a fraction into
// an apparently valid integer cost, timestamp or limit.
fn exact_integer(source : String, path : String) -> Int32 raise InputError {
if source.length() > 64 {
invalid(path, "numeric spelling exceeds 64 units")
}
let digits : Array[Int32] = []
let mut fraction = 0
let mut after_dot = false
let mut exponent = 0
let mut exp_negative = false
let mut in_exponent = false
let mut negative = false
for i in 0..= 48 && c <= 57 {
let digit = c.to_int() - 48
if in_exponent {
exponent = (exponent * 10 + digit).min(1001)
} else {
digits.push(digit)
if after_dot {
fraction += 1
}
}
} else {
invalid(path, "invalid numeric spelling")
}
}
if digits.all(d => d == 0) {
return 0
}
if negative {
invalid(path, "expected nonnegative integer")
}
let shift = (if exp_negative { -exponent } else { exponent }) - fraction
let mut keep = digits.length()
if shift < 0 {
if -shift >= digits.length() {
invalid(path, "expected exact integer")
}
keep += shift
for i in keep.. (2147483647 - digit) / 10 {
invalid(path, "integer exceeds 2147483647")
}
value = value * 10 + digit
}
if shift > 0 {
if shift > 10 {
invalid(path, "integer exceeds 2147483647")
}
for _ in 0.. 2147483647 / 10 {
invalid(path, "integer exceeds 2147483647")
}
value *= 10
}
}
value
}