#[test]
fn float_accepts_xsd_11_lexical_forms() {
for input in [
"0", "-0", "+0", "01", "1.", ".5", "-.5", "+.5", "1.25", "1e2", "1.E+2", ".5e-2", "INF",
"+INF", "-INF", "NaN", "1e9999", "1e-9999",
] {
let value = xsd::parse_float(input).unwrap();
assert_eq!(value.r#type(), xsd::FLOAT);
assert_eq!(xsd::parse(input, xsd::FLOAT).unwrap(), value);
}
assert_eq!(xsd::parse_float(".5e2").unwrap(), xsd::Value::from(50_f32));
}
#[test]
fn float_rejects_non_xsd_lexical_forms() {
for input in [
"inf",
"infinity",
"Infinity",
"INFINITY",
"nan",
"NAN",
"+NaN",
"-NaN",
"+inf",
"-infinity",
"",
"+",
"-",
".",
"1e",
"1e+",
"1e2e3",
"1.2.3",
"1_000",
"0x1p0",
" 1",
"1 ",
"1\n",
"1",
"1,5",
] {
assert!(
matches!(
xsd::parse_float(input),
Err(xsd::ParseFloatError::InvalidLexical)
),
"{input:?}"
);
assert!(
matches!(
xsd::parse(input, xsd::FLOAT),
Err(xsd::ParseError::InvalidFloat {
datatype: xsd::PrimitiveType::Float,
..
})
),
"{input:?}"
);
}
}
#[test]
fn floating_point_error_chains_distinguish_lexical_and_backend_failures() {
use core::error::Error;
let error = xsd::parse("nan", xsd::FLOAT).unwrap_err();
let source = error.source().unwrap();
assert_eq!(
source.downcast_ref::<xsd::ParseFloatError>(),
Some(&xsd::ParseFloatError::InvalidLexical)
);
assert!(source.source().is_none());
let native = "not-a-number".parse::<f32>().unwrap_err();
let wrapped = xsd::ParseFloatError::from(native.clone());
assert_eq!(
wrapped
.source()
.unwrap()
.downcast_ref::<core::num::ParseFloatError>(),
Some(&native)
);
assert_eq!(wrapped.to_string(), native.to_string());
}