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(self_input: S, other_input: O) -> Option where S: Into, O: Into, { 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::() { Ok(num) => return ComparisonNumber::UnsignedInteger(num), Err(_) => (), }; match original.parse::() { Ok(num) => return ComparisonNumber::SignedInteger(num), Err(_) => (), }; match original.parse::() { Ok(num) => return ComparisonNumber::Decimal(num), Err(_) => (), }; ComparisonNumber::Failure } }