Fix number comparison logic.
This commit is contained in:
parent
4d28120732
commit
03ff75b2de
113
src/bin.rs
113
src/bin.rs
@ -366,74 +366,27 @@ impl CompareContextElement for serde_json::Value {
|
|||||||
.partial_compare(other);
|
.partial_compare(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle other serde_json::Value
|
let maybe_json_other = other.to_any().downcast_ref::<Self>();
|
||||||
match other.to_any().downcast_ref::<Self>() {
|
let maybe_literal_other = other.to_any().downcast_ref::<OwnedLiteral>();
|
||||||
None => (),
|
|
||||||
Some(other_json_value) => {
|
// If they're both strings, compare them directly
|
||||||
return match (self, other_json_value) {
|
match (self, maybe_json_other, maybe_literal_other) {
|
||||||
(
|
// If they're both strings, compare them directly
|
||||||
serde_json::Value::Bool(self_boolean),
|
(
|
||||||
serde_json::Value::Bool(other_boolean),
|
serde_json::Value::String(self_string),
|
||||||
) => self_boolean.partial_cmp(other_boolean),
|
Some(serde_json::Value::String(other_string)),
|
||||||
(
|
_,
|
||||||
serde_json::Value::Number(self_number),
|
) => return self_string.partial_cmp(&other_string),
|
||||||
serde_json::Value::Number(other_number),
|
(
|
||||||
) => return compare_json_numbers(self_number, other_number),
|
serde_json::Value::String(self_string),
|
||||||
(
|
_,
|
||||||
serde_json::Value::String(self_string),
|
Some(OwnedLiteral::LString(other_string)),
|
||||||
serde_json::Value::Number(other_number),
|
) => return self_string.partial_cmp(&other_string),
|
||||||
) => return compare_json_numbers(self_string, other_number),
|
// Otherwise, convert to numbers are compare them that way
|
||||||
(
|
(_, Some(json_other), _) => return compare_json_numbers(self, json_other),
|
||||||
serde_json::Value::Number(self_number),
|
(_, _, Some(literal_other)) => return compare_json_numbers(self, literal_other),
|
||||||
serde_json::Value::String(other_string),
|
_ => panic!("Unimplemented comparison type."),
|
||||||
) => return compare_json_numbers(self_number, other_string),
|
|
||||||
(
|
|
||||||
serde_json::Value::String(self_string),
|
|
||||||
serde_json::Value::String(other_string),
|
|
||||||
) => self_string.partial_cmp(other_string),
|
|
||||||
(
|
|
||||||
serde_json::Value::Array(_self_array),
|
|
||||||
serde_json::Value::Array(_other_array),
|
|
||||||
) => {
|
|
||||||
// TODO: is this reachable given the early convert to string before this block?
|
|
||||||
return self
|
|
||||||
.render(&Vec::new())
|
|
||||||
.unwrap_or("".to_owned())
|
|
||||||
.partial_cmp(
|
|
||||||
&other_json_value
|
|
||||||
.render(&Vec::new())
|
|
||||||
.unwrap_or("".to_owned()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Handle literals
|
|
||||||
match (self, other.to_any().downcast_ref::<OwnedLiteral>()) {
|
|
||||||
(_, None) => (),
|
|
||||||
(serde_json::Value::String(self_text), Some(OwnedLiteral::LString(other_text))) => {
|
|
||||||
return self_text.partial_cmp(other_text);
|
|
||||||
}
|
|
||||||
(_, Some(OwnedLiteral::LString(text))) => {
|
|
||||||
return self.to_string().partial_cmp(text);
|
|
||||||
}
|
|
||||||
(_, Some(OwnedLiteral::LPositiveInteger(other_num))) => {
|
|
||||||
let other_json_num: serde_json::Number = std::convert::From::from(*other_num);
|
|
||||||
return self.partial_compare(
|
|
||||||
&serde_json::Value::Number(other_json_num) as &dyn ContextElement
|
|
||||||
);
|
|
||||||
}
|
|
||||||
(_, Some(OwnedLiteral::LFloat(other_num))) => {
|
|
||||||
let other_json_num = serde_json::Number::from_f64(*other_num);
|
|
||||||
match other_json_num {
|
|
||||||
None => return None,
|
|
||||||
Some(ojn) => return self
|
|
||||||
.partial_compare(&serde_json::Value::Number(ojn) as &dyn ContextElement),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,6 +398,32 @@ enum JsonNumber {
|
|||||||
Failure,
|
Failure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&serde_json::Value> for JsonNumber {
|
||||||
|
/// Convert from a JSON value to a number for comparison based on
|
||||||
|
/// the logic described at
|
||||||
|
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Greater_than
|
||||||
|
fn from(original: &serde_json::Value) -> Self {
|
||||||
|
match original {
|
||||||
|
serde_json::Value::Null => JsonNumber::UnsignedInteger(0),
|
||||||
|
serde_json::Value::Bool(boolean) => {
|
||||||
|
if *boolean {
|
||||||
|
JsonNumber::UnsignedInteger(1)
|
||||||
|
} else {
|
||||||
|
JsonNumber::UnsignedInteger(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serde_json::Value::Number(num) => num.into(),
|
||||||
|
serde_json::Value::String(text) => text.into(),
|
||||||
|
serde_json::Value::Array(_) => {
|
||||||
|
panic!("Only primitives should be cast to numbers for comparisons")
|
||||||
|
}
|
||||||
|
serde_json::Value::Object(_) => {
|
||||||
|
panic!("Only primitives should be cast to numbers for comparisons")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&String> for JsonNumber {
|
impl From<&String> for JsonNumber {
|
||||||
fn from(original: &String) -> Self {
|
fn from(original: &String) -> Self {
|
||||||
match original.parse::<u64>() {
|
match original.parse::<u64>() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user