///|
/// The broad lexical shape of a JSON number, before IEEE-754 normalization.
pub enum NumberKind {
Zero
Integer
Fraction
Exponent
}
///|
pub(all) struct NumberInfo {
original : String
canonical : String
kind : NumberKind
negative_zero : Bool
}
///|
pub fn NumberKind::to_string(self : NumberKind) -> String {
match self {
Zero => "zero"
Integer => "integer"
Fraction => "fraction"
Exponent => "exponent"
}
}
///|
/// Parse and normalize one JSON number token while retaining useful audit
/// metadata about the original spelling.
pub fn inspect_number(token : String) -> Result[NumberInfo, CanonicalError] {
let canonical = canonical_number(token)
let normalized = match canonical {
Ok(value) => value
Err(error) => return Err(error)
}
let kind = if token.contains("e") || token.contains("E") {
Exponent
} else if token.contains(".") {
Fraction
} else if normalized == "0" {
Zero
} else {
Integer
}
Ok({
original: token,
canonical: normalized,
kind,
negative_zero: token == "-0" ||
token == "-0.0" ||
token == "-0e0" ||
token == "-0E0",
})
}
///|
pub fn canonical_number_token(token : String) -> Result[String, CanonicalError] {
match inspect_number(token) {
Ok(info) => Ok(info.canonical)
Err(error) => Err(error)
}
}
///|
pub fn NumberInfo::summary(self : NumberInfo) -> String {
"original=" +
self.original +
",canonical=" +
self.canonical +
",kind=" +
self.kind.to_string() +
",negative_zero=" +
(if self.negative_zero { "true" } else { "false" })
}
///|
pub fn NumberInfo::to_json(self : NumberInfo) -> String {
"{\"original\":" +
canonical_string(self.original) +
",\"canonical\":" +
canonical_string(self.canonical) +
",\"kind\":" +
canonical_string(self.kind.to_string()) +
",\"negative_zero\":" +
(if self.negative_zero { "true" } else { "false" }) +
"}"
}