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
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
|
|
}
|
|
}
|