54 lines
1.6 KiB
Rust
54 lines
1.6 KiB
Rust
use serde_json::Value;
|
|
|
|
/// serde_json treats 0 and 0.0 not equal. so we cannot simply use v1==v2
|
|
pub fn equals(v1: &Value, v2: &Value) -> bool {
|
|
match (v1, v2) {
|
|
(Value::Null, Value::Null) => true,
|
|
(Value::Bool(b1), Value::Bool(b2)) => b1 == b2,
|
|
(Value::Number(n1), Value::Number(n2)) => {
|
|
if let (Some(n1), Some(n2)) = (n1.as_u64(), n2.as_u64()) {
|
|
return n1 == n2;
|
|
}
|
|
if let (Some(n1), Some(n2)) = (n1.as_i64(), n2.as_i64()) {
|
|
return n1 == n2;
|
|
}
|
|
if let (Some(n1), Some(n2)) = (n1.as_f64(), n2.as_f64()) {
|
|
return (n1 - n2).abs() < f64::EPSILON;
|
|
}
|
|
false
|
|
}
|
|
(Value::String(s1), Value::String(s2)) => s1 == s2,
|
|
(Value::Array(arr1), Value::Array(arr2)) => {
|
|
if arr1.len() != arr2.len() {
|
|
return false;
|
|
}
|
|
arr1.iter().zip(arr2).all(|(e1, e2)| equals(e1, e2))
|
|
}
|
|
(Value::Object(obj1), Value::Object(obj2)) => {
|
|
if obj1.len() != obj2.len() {
|
|
return false;
|
|
}
|
|
for (k1, v1) in obj1 {
|
|
if let Some(v2) = obj2.get(k1) {
|
|
if !equals(v1, v2) {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
true
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
pub fn is_integer(v: &Value) -> bool {
|
|
match v {
|
|
Value::Number(n) => {
|
|
n.is_i64() || n.is_u64() || n.as_f64().filter(|n| n.fract() == 0.0).is_some()
|
|
}
|
|
_ => false,
|
|
}
|
|
}
|