@ -5,17 +5,21 @@ use parser::Filter;
use parser ::OwnedLiteral ;
use parser ::Template ;
use renderer ::compile_template ;
use renderer ::Castable ;
use renderer ::CompileError ;
use renderer ::ContextElement ;
use renderer ::DustRenderer ;
use renderer ::IceResult ;
use renderer ::IntoContextElement ;
use renderer ::Loopable ;
use renderer ::MathNumber ;
use renderer ::RenderError ;
use renderer ::Renderable ;
use renderer ::Truthiness ;
use renderer ::WalkError ;
use renderer ::Walkable ;
use std ::cmp ::Ordering ;
use std ::convert ::TryInto ;
use std ::env ;
use std ::fs ;
use std ::io ::{ self , Read } ;
@ -274,7 +278,6 @@ impl Renderable for serde_json::Value {
serde_json ::Value ::Number ( num ) = > Ok ( num . to_string ( ) ) ,
serde_json ::Value ::String ( string ) = > Ok ( string . to_string ( ) ) ,
serde_json ::Value ::Array ( arr ) = > {
// TODO: Handle the filters instead of passing a Vec::new()
let rendered : Result < Vec < String > , RenderError > =
arr . iter ( ) . map ( | val | val . render ( & Vec ::new ( ) ) ) . collect ( ) ;
let rendered_slice : & [ String ] = & rendered ? ;
@ -310,8 +313,30 @@ impl Loopable for serde_json::Value {
}
}
impl Castable for serde_json ::Value {
fn cast_to_type < ' a > ( & ' a self , target : & str ) -> Option < IceResult < ' a > > {
match ( self , target ) {
( serde_json ::Value ::String ( text ) , "number" ) = > text
. parse ::< u64 > ( )
. map ( | num | IceResult ::from_owned ( OwnedLiteral ::LPositiveInteger ( num ) ) )
. or_else ( | _ | {
text . parse ::< i64 > ( )
. map ( | num | IceResult ::from_owned ( OwnedLiteral ::LNegativeInteger ( num ) ) )
} )
. or_else ( | _ | {
text . parse ::< f64 > ( )
. map ( | num | IceResult ::from_owned ( OwnedLiteral ::LFloat ( num ) ) )
} )
. ok ( ) ,
( serde_json ::Value ::Number ( _ ) , "number" ) = > Some ( IceResult ::from_borrowed ( self ) ) ,
( _ , _ ) = > panic! ( "Unimplemented cast" ) ,
}
}
}
impl CompareContextElement for serde_json ::Value {
fn equals ( & self , other : & dyn ContextElement ) -> bool {
// println!("Json equality check {:?} == {:?}", self, other);
// Handle other serde_json::Value
match other . to_any ( ) . downcast_ref ::< Self > ( ) {
None = > ( ) ,
@ -332,8 +357,19 @@ impl CompareContextElement for serde_json::Value {
return self . as_str ( ) . map_or ( false , | s | s = = other_string )
}
Some ( OwnedLiteral ::LPositiveInteger ( other_num ) ) = > {
return self . as_u64 ( ) . map_or ( false , | n | n = = * other_num )
let other_json_num : serde_json ::Number = std ::convert ::From ::from ( * other_num ) ;
return self
. equals ( & serde_json ::Value ::Number ( other_json_num ) as & dyn ContextElement ) ;
}
Some ( OwnedLiteral ::LNegativeInteger ( other_num ) ) = > {
let other_json_num : serde_json ::Number = std ::convert ::From ::from ( * other_num ) ;
return self
. equals ( & serde_json ::Value ::Number ( other_json_num ) as & dyn ContextElement ) ;
}
Some ( OwnedLiteral ::LFloat ( other_num ) ) = > match self . as_f64 ( ) {
None = > return false ,
Some ( self_float ) = > return self_float = = * other_num ,
} ,
}
false
}
@ -355,138 +391,261 @@ impl CompareContextElement for serde_json::Value {
. partial_compare ( other ) ;
}
// Handle other serde_json::Value
match other . to_any ( ) . downcast_ref ::< Self > ( ) {
None = > ( ) ,
Some ( other_json_value ) = > {
return match ( self , other_json_value ) {
(
serde_json ::Value ::Bool ( self_boolean ) ,
serde_json ::Value ::Bool ( other_boolean ) ,
) = > self_boolean . partial_cmp ( other_boolean ) ,
(
serde_json ::Value ::Number ( self_number ) ,
serde_json ::Value ::Number ( other_number ) ,
) = > return compare_json_numbers ( self_number , other_number ) ,
(
serde_json ::Value ::String ( self_string ) ,
serde_json ::Value ::Number ( other_number ) ,
) = > return compare_json_numbers ( self_string , other_number ) ,
(
serde_json ::Value ::Number ( self_number ) ,
serde_json ::Value ::String ( other_string ) ,
) = > 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 ,
} ;
}
let maybe_json_other = other . to_any ( ) . downcast_ref ::< Self > ( ) ;
let maybe_literal_other = other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) ;
// If they're both strings, compare them directly
match ( self , maybe_json_other , maybe_literal_other ) {
// If they're both strings, compare them directly
(
serde_json ::Value ::String ( self_string ) ,
Some ( serde_json ::Value ::String ( other_string ) ) ,
_ ,
) = > return self_string . partial_cmp ( & other_string ) ,
(
serde_json ::Value ::String ( self_string ) ,
_ ,
Some ( OwnedLiteral ::LString ( other_string ) ) ,
) = > return self_string . partial_cmp ( & other_string ) ,
// Otherwise, convert to numbers are compare them that way
( _ , Some ( json_other ) , _ ) = > return compare_json_numbers ( self , json_other ) ,
( _ , _ , Some ( literal_other ) ) = > return compare_json_numbers ( self , literal_other ) ,
_ = > panic! ( "Unimplemented comparison type." ) ,
}
// Handle literals
match other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) {
None = > ( ) ,
Some ( other_literal ) = > match ( self , other_literal ) {
( serde_json ::Value ::String ( self_string ) , OwnedLiteral ::LString ( other_string ) ) = > {
return self_string . partial_cmp ( other_string )
}
(
serde_json ::Value ::String ( self_string ) ,
OwnedLiteral ::LPositiveInteger ( _other_num ) ,
) = > return compare_json_numbers ( self_string , other_literal ) ,
( serde_json ::Value ::Number ( self_num ) , OwnedLiteral ::LString ( other_string ) ) = > {
return compare_json_numbers ( self_num , other_string )
}
(
serde_json ::Value ::Number ( self_num ) ,
OwnedLiteral ::LPositiveInteger ( _other_num ) ,
) = > return compare_json_numbers ( self_num , other_literal ) ,
( serde_json ::Value ::Array ( _ ) , _ ) = > {
// TODO
todo! ( )
}
( serde_json ::Value ::Object ( _ ) , _ ) = > {
// TODO
todo! ( )
}
( serde_json ::Value ::Bool ( _ ) , _ ) = > {
// TODO
todo! ( )
}
( serde_json ::Value ::Null , _ ) = > {
// TODO
todo! ( )
}
} ,
}
fn math_add < ' a > ( & self , other : & dyn ContextElement ) -> Option < IceResult < ' a > > {
let other_json = other . to_any ( ) . downcast_ref ::< Self > ( ) ;
let other_literal = other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) ;
match ( self , other_json , other_literal ) {
// If its neither of those types, then it is unimplemented
( _ , None , None ) = > panic! ( "Math operation on unimplemented type" ) ,
// Since this is specifically for the math helper, non-primitives are not supported
( serde_json ::Value ::Array ( _ ) , _ , _ )
| ( serde_json ::Value ::Object ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::Array ( _ ) ) , _ )
| ( _ , Some ( serde_json ::Value ::Object ( _ ) ) , _ ) = > None ,
// Strings also are ignored because this is specifically a math function
( serde_json ::Value ::String ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::String ( _ ) ) , _ )
| ( _ , _ , Some ( OwnedLiteral ::LString ( _ ) ) ) = > None ,
// Handle other serde_json::Value
( _ , Some ( other_json_value ) , _ ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
+ std ::convert ::Into ::< MathNumber > ::into ( other_json_value ) )
. map ( IceResult ::from_owned ) ,
// Handle literals
( _ , _ , Some ( other_literal ) ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
+ std ::convert ::Into ::< MathNumber > ::into ( other_literal ) )
. map ( IceResult ::from_owned ) ,
}
}
fn math_subtract < ' a > ( & self , other : & dyn ContextElement ) -> Option < IceResult < ' a > > {
let other_json = other . to_any ( ) . downcast_ref ::< Self > ( ) ;
let other_literal = other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) ;
match ( self , other_json , other_literal ) {
// If its neither of those types, then it is unimplemented
( _ , None , None ) = > panic! ( "Math operation on unimplemented type" ) ,
// Since this is specifically for the math helper, non-primitives are not supported
( serde_json ::Value ::Array ( _ ) , _ , _ )
| ( serde_json ::Value ::Object ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::Array ( _ ) ) , _ )
| ( _ , Some ( serde_json ::Value ::Object ( _ ) ) , _ ) = > None ,
// Strings also are ignored because this is specifically a math function
( serde_json ::Value ::String ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::String ( _ ) ) , _ )
| ( _ , _ , Some ( OwnedLiteral ::LString ( _ ) ) ) = > None ,
// Handle other serde_json::Value
( _ , Some ( other_json_value ) , _ ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
- std ::convert ::Into ::< MathNumber > ::into ( other_json_value ) )
. map ( IceResult ::from_owned ) ,
// Handle literals
( _ , _ , Some ( other_literal ) ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
- std ::convert ::Into ::< MathNumber > ::into ( other_literal ) )
. map ( IceResult ::from_owned ) ,
}
}
fn math_multiply < ' a > ( & self , other : & dyn ContextElement ) -> Option < IceResult < ' a > > {
let other_json = other . to_any ( ) . downcast_ref ::< Self > ( ) ;
let other_literal = other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) ;
match ( self , other_json , other_literal ) {
// If its neither of those types, then it is unimplemented
( _ , None , None ) = > panic! ( "Math operation on unimplemented type" ) ,
// Since this is specifically for the math helper, non-primitives are not supported
( serde_json ::Value ::Array ( _ ) , _ , _ )
| ( serde_json ::Value ::Object ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::Array ( _ ) ) , _ )
| ( _ , Some ( serde_json ::Value ::Object ( _ ) ) , _ ) = > None ,
// Strings also are ignored because this is specifically a math function
( serde_json ::Value ::String ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::String ( _ ) ) , _ )
| ( _ , _ , Some ( OwnedLiteral ::LString ( _ ) ) ) = > None ,
// Handle other serde_json::Value
( _ , Some ( other_json_value ) , _ ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
* std ::convert ::Into ::< MathNumber > ::into ( other_json_value ) )
. map ( IceResult ::from_owned ) ,
// Handle literals
( _ , _ , Some ( other_literal ) ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
* std ::convert ::Into ::< MathNumber > ::into ( other_literal ) )
. map ( IceResult ::from_owned ) ,
}
}
fn math_divide < ' a > ( & self , other : & dyn ContextElement ) -> Option < IceResult < ' a > > {
let other_json = other . to_any ( ) . downcast_ref ::< Self > ( ) ;
let other_literal = other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) ;
match ( self , other_json , other_literal ) {
// If its neither of those types, then it is unimplemented
( _ , None , None ) = > panic! ( "Math operation on unimplemented type" ) ,
// Since this is specifically for the math helper, non-primitives are not supported
( serde_json ::Value ::Array ( _ ) , _ , _ )
| ( serde_json ::Value ::Object ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::Array ( _ ) ) , _ )
| ( _ , Some ( serde_json ::Value ::Object ( _ ) ) , _ ) = > None ,
// Strings also are ignored because this is specifically a math function
( serde_json ::Value ::String ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::String ( _ ) ) , _ )
| ( _ , _ , Some ( OwnedLiteral ::LString ( _ ) ) ) = > None ,
// Handle other serde_json::Value
( _ , Some ( other_json_value ) , _ ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
/ std ::convert ::Into ::< MathNumber > ::into ( other_json_value ) )
. map ( IceResult ::from_owned ) ,
// Handle literals
( _ , _ , Some ( other_literal ) ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
/ std ::convert ::Into ::< MathNumber > ::into ( other_literal ) )
. map ( IceResult ::from_owned ) ,
}
None
}
fn math_modulus < ' a > ( & self , other : & dyn ContextElement ) -> Option < IceResult < ' a > > {
let other_json = other . to_any ( ) . downcast_ref ::< Self > ( ) ;
let other_literal = other . to_any ( ) . downcast_ref ::< OwnedLiteral > ( ) ;
match ( self , other_json , other_literal ) {
// If its neither of those types, then it is unimplemented
( _ , None , None ) = > panic! ( "Math operation on unimplemented type" ) ,
// Since this is specifically for the math helper, non-primitives are not supported
( serde_json ::Value ::Array ( _ ) , _ , _ )
| ( serde_json ::Value ::Object ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::Array ( _ ) ) , _ )
| ( _ , Some ( serde_json ::Value ::Object ( _ ) ) , _ ) = > None ,
// Strings also are ignored because this is specifically a math function
( serde_json ::Value ::String ( _ ) , _ , _ )
| ( _ , Some ( serde_json ::Value ::String ( _ ) ) , _ )
| ( _ , _ , Some ( OwnedLiteral ::LString ( _ ) ) ) = > None ,
// Handle other serde_json::Value
( _ , Some ( other_json_value ) , _ ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
% std ::convert ::Into ::< MathNumber > ::into ( other_json_value ) )
. map ( IceResult ::from_owned ) ,
// Handle literals
( _ , _ , Some ( other_literal ) ) = > ( std ::convert ::Into ::< MathNumber > ::into ( self )
% std ::convert ::Into ::< MathNumber > ::into ( other_literal ) )
. map ( IceResult ::from_owned ) ,
}
}
fn math_abs < ' a > ( & self ) -> Option < IceResult < ' a > > {
std ::convert ::Into ::< MathNumber > ::into ( self )
. math_abs ( )
. map ( IceResult ::from_owned )
}
fn math_floor < ' a > ( & self ) -> Option < IceResult < ' a > > {
std ::convert ::Into ::< MathNumber > ::into ( self )
. math_floor ( )
. map ( IceResult ::from_owned )
}
fn math_ceil < ' a > ( & self ) -> Option < IceResult < ' a > > {
std ::convert ::Into ::< MathNumber > ::into ( self )
. math_ceil ( )
. map ( IceResult ::from_owned )
}
}
#[ derive(Debug) ]
enum JsonNumber {
enum Compari sonNumber {
UnsignedInteger ( u64 ) ,
SignedInteger ( i64 ) ,
Decimal ( f64 ) ,
Failure ,
}
impl From < & String > for JsonNumber {
impl From < & serde_json ::Value > for ComparisonNumber {
/// 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 = > ComparisonNumber ::UnsignedInteger ( 0 ) ,
serde_json ::Value ::Bool ( boolean ) = > {
if * boolean {
ComparisonNumber ::UnsignedInteger ( 1 )
} else {
ComparisonNumber ::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 ComparisonNumber {
fn from ( original : & String ) -> Self {
match original . parse ::< u64 > ( ) {
Ok ( num ) = > return JsonNumber ::UnsignedInteger ( num ) ,
Ok ( num ) = > return Compari sonNumber::UnsignedInteger ( num ) ,
Err ( _ ) = > ( ) ,
} ;
match original . parse ::< i64 > ( ) {
Ok ( num ) = > return JsonNumber ::SignedInteger ( num ) ,
Ok ( num ) = > return Compari sonNumber::SignedInteger ( num ) ,
Err ( _ ) = > ( ) ,
} ;
match original . parse ::< f64 > ( ) {
Ok ( num ) = > return JsonNumber ::Decimal ( num ) ,
Ok ( num ) = > return Compari sonNumber::Decimal ( num ) ,
Err ( _ ) = > ( ) ,
} ;
JsonNumber ::Failure
Compari sonNumber::Failure
}
}
impl From < & serde_json ::Number > for JsonNumber {
impl From < & serde_json ::Number > for Compari sonNumber {
fn from ( original : & serde_json ::Number ) -> Self {
match original . as_u64 ( ) {
Some ( num ) = > return JsonNumber ::UnsignedInteger ( num ) ,
Some ( num ) = > return Compari sonNumber::UnsignedInteger ( num ) ,
None = > ( ) ,
} ;
match original . as_i64 ( ) {
Some ( num ) = > return JsonNumber ::SignedInteger ( num ) ,
Some ( num ) = > return Compari sonNumber::SignedInteger ( num ) ,
None = > ( ) ,
} ;
match original . as_f64 ( ) {
Some ( num ) = > return JsonNumber ::Decimal ( num ) ,
Some ( num ) = > return Compari sonNumber::Decimal ( num ) ,
None = > ( ) ,
} ;
JsonNumber ::Failure
Compari sonNumber::Failure
}
}
impl From < & OwnedLiteral > for JsonNumber {
impl From < & OwnedLiteral > for Compari sonNumber {
fn from ( original : & OwnedLiteral ) -> Self {
match original {
OwnedLiteral ::LPositiveInteger ( num ) = > JsonNumber ::UnsignedInteger ( * num ) ,
OwnedLiteral ::LPositiveInteger ( num ) = > ComparisonNumber ::UnsignedInteger ( * num ) ,
OwnedLiteral ::LNegativeInteger ( num ) = > ComparisonNumber ::SignedInteger ( * num ) ,
OwnedLiteral ::LString ( text ) = > text . into ( ) ,
OwnedLiteral ::LFloat ( num ) = > {
if num . is_nan ( ) {
ComparisonNumber ::Failure
} else {
ComparisonNumber ::Decimal ( * num )
}
}
}
}
}
@ -498,39 +657,104 @@ impl From<&OwnedLiteral> for JsonNumber {
/// strings
fn compare_json_numbers < S , O > ( self_input : S , other_input : O ) -> Option < Ordering >
where
S : Into < J sonNumber> ,
O : Into < J sonNumber> ,
S : Into < Compari sonNumber> ,
O : Into < Compari sonNumber> ,
{
let self_number : JsonNumber = self_input . into ( ) ;
let other_number : JsonNumber = other_input . into ( ) ;
// TODO: Figure out how javascript compares floats and ints
let self_number : ComparisonNumber = self_input . into ( ) ;
let other_number : ComparisonNumber = other_input . into ( ) ;
match ( self_number , other_number ) {
( JsonNumber ::Failure , _ ) = > return None ,
( _ , JsonNumber ::Failure ) = > return None ,
( JsonNumber ::UnsignedInteger ( self_num ) , JsonNumber ::UnsignedInteger ( other_num ) ) = > {
return self_num . partial_cmp ( & other_num )
( 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 ) ;
}
}
( JsonNumber ::UnsignedInteger ( _self_num ) , JsonNumber ::SignedInteger ( _other_num ) ) = > {
return Some ( Ordering ::Greater )
( ComparisonNumber::UnsignedInteger ( self_num ) , ComparisonNumber ::Decimal ( other_num) ) = > {
return ( self_num as f64 ) . partial_cmp ( & other_num )
}
( JsonNumber ::UnsignedInteger ( _self_num ) , JsonNumber ::Decimal ( _other_num ) ) = > return None ,
( JsonNumber ::SignedInteger ( _self_num ) , JsonNumber ::UnsignedInteger ( _other_num ) ) = > {
return Some ( Ordering ::Less )
(
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 ) ;
}
}
( JsonNumber ::SignedInteger ( self_num ) , JsonNumber ::SignedInteger ( other_num ) ) = > {
( ComparisonNumber::SignedInteger ( self_num ) , Compari sonNumber::SignedInteger ( other_num ) ) = > {
return self_num . partial_cmp ( & other_num )
}
( JsonNumber ::SignedInteger ( _self_num ) , JsonNumber ::Decimal ( _other_num ) ) = > return None ,
( ComparisonNumber ::SignedInteger ( self_num ) , ComparisonNumber ::Decimal ( other_num ) ) = > {
return ( self_num as f64 ) . partial_cmp ( & other_num )
}
( JsonNumber ::Decimal ( _self_num ) , JsonNumber ::UnsignedInteger ( _other_num ) ) = > return None ,
( JsonNumber ::Decimal ( _self_num ) , JsonNumber ::SignedInteger ( _other_num ) ) = > return None ,
( JsonNumber ::Decimal ( self_num ) , JsonNumber ::Decimal ( 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 < & serde_json ::Value > for MathNumber {
fn from ( original : & serde_json ::Value ) -> Self {
match original {
serde_json ::Value ::Null = > MathNumber ::Integer ( 0 ) ,
serde_json ::Value ::Bool ( boolean ) = > {
if * boolean {
MathNumber ::Integer ( 1 )
} else {
MathNumber ::Integer ( 0 )
}
}
serde_json ::Value ::Number ( num ) = > num . into ( ) ,
serde_json ::Value ::String ( _ ) = > {
panic! ( "Strings should not be cast to numbers for math" )
}
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 < & serde_json ::Number > for MathNumber {
fn from ( original : & serde_json ::Number ) -> Self {
match original . as_u64 ( ) {
Some ( num ) = > return MathNumber ::Integer ( num . try_into ( ) . unwrap ( ) ) ,
None = > ( ) ,
} ;
match original . as_i64 ( ) {
Some ( num ) = > return MathNumber ::Integer ( num . into ( ) ) ,
None = > ( ) ,
} ;
match original . as_f64 ( ) {
Some ( num ) = > return MathNumber ::Decimal ( num ) ,
None = > ( ) ,
} ;
MathNumber ::Failure
}
}
#[ cfg(test) ]
mod tests {
use super ::* ;