You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.1 KiB
Rust

use std::cmp::Ordering;
#[derive(Debug)]
pub enum ComparisonNumber {
UnsignedInteger(u64),
SignedInteger(i64),
Decimal(f64),
Failure,
}
/// Compare json numbers
///
/// While this function can be called with two strings, it would not
/// make sense because javascript does not use numeric comparisons for
/// strings
pub fn compare_json_numbers<S, O>(self_input: S, other_input: O) -> Option<Ordering>
where
S: Into<ComparisonNumber>,
O: Into<ComparisonNumber>,
{
let self_number: ComparisonNumber = self_input.into();
let other_number: ComparisonNumber = other_input.into();
match (self_number, other_number) {
(ComparisonNumber::Failure, _) => return None,
(_, ComparisonNumber::Failure) => return None,
(
ComparisonNumber::UnsignedInteger(self_num),
ComparisonNumber::UnsignedInteger(other_num),
) => return self_num.partial_cmp(&other_num),
(
ComparisonNumber::UnsignedInteger(self_num),
ComparisonNumber::SignedInteger(other_num),
) => {
if self_num < std::i64::MAX as u64 {
return (self_num as i64).partial_cmp(&other_num);
} else {
return Some(Ordering::Greater);
}
}
(ComparisonNumber::UnsignedInteger(self_num), ComparisonNumber::Decimal(other_num)) => {
return (self_num as f64).partial_cmp(&other_num)
}
(
ComparisonNumber::SignedInteger(self_num),
ComparisonNumber::UnsignedInteger(other_num),
) => {
if other_num < std::i64::MAX as u64 {
return self_num.partial_cmp(&(other_num as i64));
} else {
return Some(Ordering::Less);
}
}
(ComparisonNumber::SignedInteger(self_num), ComparisonNumber::SignedInteger(other_num)) => {
return self_num.partial_cmp(&other_num)
}
(ComparisonNumber::SignedInteger(self_num), ComparisonNumber::Decimal(other_num)) => {
return (self_num as f64).partial_cmp(&other_num)
}
(ComparisonNumber::Decimal(self_num), ComparisonNumber::UnsignedInteger(other_num)) => {
return self_num.partial_cmp(&(other_num as f64))
}
(ComparisonNumber::Decimal(self_num), ComparisonNumber::SignedInteger(other_num)) => {
return self_num.partial_cmp(&(other_num as f64))
}
(ComparisonNumber::Decimal(self_num), ComparisonNumber::Decimal(other_num)) => {
return self_num.partial_cmp(&other_num)
}
}
}
impl From<&String> for ComparisonNumber {
fn from(original: &String) -> Self {
match original.parse::<u64>() {
Ok(num) => return ComparisonNumber::UnsignedInteger(num),
Err(_) => (),
};
match original.parse::<i64>() {
Ok(num) => return ComparisonNumber::SignedInteger(num),
Err(_) => (),
};
match original.parse::<f64>() {
Ok(num) => return ComparisonNumber::Decimal(num),
Err(_) => (),
};
ComparisonNumber::Failure
}
}