Formalize concept of a Number (#55)

Number is implemented using rust_decimal::Decimal which uses a 96 bit mantissa.
TODO:
  a) Support u64, i64 variants
  b) Determine desired semantics for floating-point
  c) Determine desired big integer length
  d) Explore other big int/big float crates

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2023-12-01 08:45:59 -08:00
committed by GitHub
parent bb0ca29753
commit ed3492fd7b
21 changed files with 945 additions and 420 deletions
+21 -35
View File
@@ -13,12 +13,12 @@ fn non_string_key() -> Result<()> {
obj.as_object_mut()?.insert(Value::Null, Value::Null);
obj.as_object_mut()?.insert(Value::Bool(false), Value::Null);
obj.as_object_mut()?
.insert(Value::from_float(std::f64::consts::PI), Value::Null);
.insert(Value::from(std::f64::consts::PI), Value::Null);
obj.as_object_mut()?.insert(
Value::from_array(vec![
Value::Bool(true),
Value::Null,
Value::from_float(std::f64::consts::PI),
Value::from(std::f64::consts::PI),
]),
Value::Null,
);
@@ -27,8 +27,7 @@ fn non_string_key() -> Result<()> {
set.as_set_mut()?.insert(Value::Bool(true));
set.as_set_mut()?.insert(Value::Bool(false));
set.as_set_mut()?.insert(Value::Bool(true));
set.as_set_mut()?
.insert(Value::from_float(std::f64::consts::PI));
set.as_set_mut()?.insert(Value::from(std::f64::consts::PI));
obj.as_object_mut()?.insert(set, Value::Null);
obj.as_object_mut()?.insert(Value::Undefined, Value::Null);
@@ -57,30 +56,20 @@ fn non_string_key() -> Result<()> {
#[test]
fn serialize_number() -> Result<()> {
// Check that integer values are serialized without fractional part
assert_eq!(serde_json::to_string_pretty(&Value::from_float(1.0))?, "1");
assert_eq!(
serde_json::to_string_pretty(&Value::from_float(-1.0))?,
"-1"
);
assert_eq!(serde_json::to_string_pretty(&Value::from(1.0))?, "1");
assert_eq!(serde_json::to_string_pretty(&Value::from(-1.0))?, "-1");
// Ensure that fractional parts are also serialized.
assert_eq!(
serde_json::to_string_pretty(&Value::from_float(1.1))?,
"1.1"
);
assert_eq!(
serde_json::to_string_pretty(&Value::from_float(-1.1))?,
"-1.1"
);
assert_eq!(serde_json::to_string_pretty(&Value::from(1.1))?, "1.1");
assert_eq!(serde_json::to_string_pretty(&Value::from(-1.1))?, "-1.1");
Ok(())
}
#[test]
fn display_number() {
use ordered_float::OrderedFloat;
let n = Number(OrderedFloat(123456f64));
assert_eq!(format!("{}", &n), "123456");
let n = Number::from(123456f64);
assert_eq!(format!("{}", n.format_decimal()), "123456");
}
#[test]
@@ -101,18 +90,18 @@ fn constructors() -> Result<()> {
#[test]
fn value_as_index() -> Result<()> {
let idx = Value::from_float(2.0);
let idx = Value::from(2.0);
let mut item = Value::new_array();
item.as_array_mut()?.push(Value::from_float(3.0));
item.as_array_mut()?.push(Value::from_float(4.0));
item.as_array_mut()?.push(Value::from_float(5.0));
item.as_array_mut()?.push(Value::from(3.0));
item.as_array_mut()?.push(Value::from(4.0));
item.as_array_mut()?.push(Value::from(5.0));
// Check case of item present.
assert_eq!(&Value::from_json_str("[1, 2, [3, 4, 5]]")?[&idx], &item);
// Check case of item not present.
let idx = Value::from_float(5.0);
let idx = Value::from(5.0);
assert_eq!(
&Value::from_json_str("[1, 2, [3, 4, 5]]")?[&idx],
&Value::Undefined
@@ -131,17 +120,14 @@ fn value_as_index() -> Result<()> {
#[test]
fn string_as_index() -> Result<()> {
let obj = Value::from_json_str(r#"{ "a" : 5, "b" : 6 }"#)?;
assert_eq!(&obj["a"], &Value::from_float(5.0));
assert_eq!(&obj[&"b".to_owned()], &Value::from_float(6.0));
assert_eq!(&obj["a"], &Value::from(5.0));
assert_eq!(&obj[&"b".to_owned()], &Value::from(6.0));
Ok(())
}
#[test]
fn usize_as_index() -> Result<()> {
assert_eq!(
&Value::from_json_str("[1, 2, 3]")?[0],
&Value::from_float(1.0)
);
assert_eq!(&Value::from_json_str("[1, 2, 3]")?[0], &Value::from(1.0));
assert_eq!(&Value::from_json_str("[1, 2, 3]")?[5], &Value::Undefined);
Ok(())
}
@@ -151,8 +137,8 @@ fn api() -> Result<()> {
assert!(&Value::from_json_str("{}")?.as_object()?.is_empty());
let mut v = Value::new_object();
v.as_object_mut()?
.insert(Value::String("a".into()), Value::from_float(3.145));
assert_eq!(v["a"], Value::from_float(3.145));
.insert(Value::String("a".into()), Value::from(3.145));
assert_eq!(v["a"], Value::from(3.145));
assert_eq!(v.as_object()?.len(), 1);
// Null
@@ -174,7 +160,7 @@ fn api() -> Result<()> {
assert!(Value::new_object().as_number().is_err());
assert!(Value::new_object().as_number_mut().is_err());
assert!(Value::from_float(5.6).as_bool().is_err());
assert!(Value::from_float(5.6).as_bool_mut().is_err());
assert!(Value::from(5.6).as_bool().is_err());
assert!(Value::from(5.6).as_bool_mut().is_err());
Ok(())
}