json/blueprint/number
Exact JSON numbers and their checked conversions to Int and Float.
A Number keeps the decimal value of a JSON number token exactly, with no
rounding, so 1.10 equals 1.1 and 1e2 equals 100. parse reads a
token within Limits on token bytes, significant digits and exponent
size; default_limits() is 1,024 bytes, 800 digits and exponent 1,200,
which admits the exact decimal expansion of every finite binary64 value.
to_int and to_float_exact return a native value only when it is
exactly equal; to_float rounds to the nearest binary64. from_int,
from_float (the shortest decimal that reads back as the same float) and
from_float_exact (the float’s exact binary expansion) convert back. On
JavaScript, integers outside the safe range (±9,007,199,254,740,991) are
refused instead of rounded.
value.Number holds this type, and codec.number() decodes it.
import gleam/order
import json/blueprint/number
pub fn example() {
let assert Ok(price) = number.parse("19.90", number.default_limits())
let assert Ok(same) = number.parse("1.99e1", number.default_limits())
let assert order.Eq = number.compare(price, same)
let assert Ok(19.9) = number.to_float(price)
number.to_string(price)
}
Types
Why from_float or from_float_exact refused a Float: on JavaScript,
an infinity or NaN.
pub type FloatConstructionError {
NonFiniteFloat
}
Constructors
-
NonFiniteFloat
Why to_float or to_float_exact refused a number.
pub type FloatProjectionError {
FloatOverflow
FloatUnderflow
FloatInexact
InvalidFloatCandidate
}
Constructors
-
FloatOverflow -
FloatUnderflow -
FloatInexact -
InvalidFloatCandidate
Why from_int refused an Int. Only JavaScript produces these: a
non-finite or fractional number, or one outside the safe integer range.
pub type IntegerConstructionError {
NonFiniteInteger
NonIntegerValue
UnsafeNativeInteger
}
Constructors
-
NonFiniteInteger -
NonIntegerValue -
UnsafeNativeInteger
Why to_int refused a number.
pub type IntegerProjectionError {
FractionalInteger
IntegerDigitLimitExceeded
UnsupportedNativeInteger
}
Constructors
-
FractionalInteger -
IntegerDigitLimitExceeded -
UnsupportedNativeInteger
Bounds for parse: token bytes, significant digits and the magnitude of
the decimal exponent.
pub opaque type Limits
An exact JSON number.
The representation is canonical, so two Number values are equal exactly
when they denote the same mathematical value.
pub opaque type Number
Why parse refused a token. InvalidSyntax is not a JSON number; the other
variants exceed a bound of Limits or the target’s exact exponent representation.
pub type NumberError {
InvalidSyntax
TokenTooLong
TooManySignificandDigits
ExponentOutOfRange
}
Constructors
-
InvalidSyntax -
TokenTooLong -
TooManySignificandDigits -
ExponentOutOfRange
Values
pub fn compare(left: Number, right: Number) -> order.Order
Compare two numbers by mathematical value.
pub fn default_limits() -> Limits
1,024 token bytes, 800 significant digits and exponent magnitude 1,200. These admit the exact decimal expansion of every finite binary64 value, including the smallest subnormal.
pub fn from_float(
value: Float,
) -> Result(Number, FloatConstructionError)
The shortest decimal that reads back as the same float, such as 0.1 for
0.1. This is the number a JSON reader sees in the float’s usual printed
form.
pub fn from_float_exact(
value: Float,
) -> Result(Number, FloatConstructionError)
The exact decimal value of the float’s binary representation, such as
0.1000000000000000055511151231257827021181583404541015625 for 0.1.
pub fn from_int(
value: Int,
) -> Result(Number, IntegerConstructionError)
The exact number of an Int. Fails only on JavaScript, for a value that is
not a safe integer.
pub fn limits(
max_token_bytes max_token_bytes: Int,
max_significant_digits max_significant_digits: Int,
max_exponent max_exponent: Int,
) -> Limits
Build number limits. A token longer than max_token_bytes, with more than
max_significant_digits digits as written, or whose normalized decimal
exponent exceeds max_exponent in magnitude is refused. A token bound
or digit bound below 1 refuses every token; a negative exponent bound
refuses every number except zero.
pub fn parse(
token: String,
limits: Limits,
) -> Result(Number, NumberError)
Parse a JSON number token, such as -12.5e3, exactly. Leading or trailing
whitespace, a leading +, leading zeros and a bare . are invalid, as in
JSON. JavaScript refuses written exponents, normalized exponents, or decimal
comparison magnitudes outside its safe integer range with ExponentOutOfRange,
even when the supplied limits are larger. Erlang retains arbitrary integers.
pub fn to_float(
number: Number,
) -> Result(Float, FloatProjectionError)
The nearest binary64 float. Fails with FloatOverflow when the magnitude
is beyond the largest finite float; a magnitude below the smallest
subnormal rounds to zero.
pub fn to_float_exact(
number: Number,
) -> Result(Float, FloatProjectionError)
The float exactly equal to the number. Fails when the nearest float
differs (FloatInexact), or the number is beyond the float range.
pub fn to_int(
number: Number,
max_digits: Int,
) -> Result(Int, IntegerProjectionError)
The number as an Int when it is an integer of at most max_digits
decimal digits. max_digits bounds the work and memory of the conversion;
on JavaScript the integer must also be within the safe range.