From df0ae0564875e033111cf5334d91c392d0d23c4b Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sat, 13 Jun 2020 18:34:13 -0400 Subject: [PATCH] Start of implementation for serde_json but I'm going to change my approach. The permutations are pretty intense, so I think I'm going to do the same design I did for comparison where I have a JsonNumber (but I'll call this one MathNumber and rename JsonNumber to ComparisonNumber), convert the types to that, and then do the math. --- src/bin.rs | 59 +++++++++++++++++++++++++++++- src/renderer/mod.rs | 1 + src/renderer/parameters_context.rs | 2 +- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 21579b6..fdb7905 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -5,6 +5,7 @@ use parser::Filter; use parser::OwnedLiteral; use parser::Template; use renderer::compile_template; +use renderer::math_ints; use renderer::CompileError; use renderer::ContextElement; use renderer::DustRenderer; @@ -390,7 +391,63 @@ impl CompareContextElement for serde_json::Value { } fn math_add<'a>(&self, other: &dyn ContextElement) -> Option> { - todo!() + match ( + self, + other.to_any().downcast_ref::(), + other.to_any().downcast_ref::(), + ) { + // 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 + ( + serde_json::Value::Number(self_num), + Some(serde_json::Value::Number(other_num)), + _, + ) => { + match ( + self_num.as_u64(), + other_num.as_u64(), + self_num.as_i64(), + other_num.as_i64(), + self_num.as_f64(), + other_num.as_f64(), + ) { + // If both numbers are integers, we can pass them into math_ints + (Some(self_num), Some(other_num), _, _, _, _) => { + math_ints(self_num, other_num, std::ops::Add::add) + .map(IceResult::from_owned) + } + (_, _, Some(self_num), Some(other_num), _, _) => { + math_ints(self_num, other_num, std::ops::Add::add) + .map(IceResult::from_owned) + } + (Some(self_num), _, _, Some(other_num), _, _) => { + math_ints(self_num, other_num, std::ops::Add::add) + .map(IceResult::from_owned) + } + (_, Some(other_num), Some(self_num), _, _, _) => { + math_ints(self_num, other_num, std::ops::Add::add) + .map(IceResult::from_owned) + } + // Otherwise they'll be floats and we can just do the math directly + (_, _, _, _, Some(self_num), Some(other_num)) => Some(IceResult::from_owned( + OwnedLiteral::LFloat(self_num + other_num), + )), + _ => panic!("Unhandled operation, some integer must not have cast to a float."), + } + } + // Handle literals + _ => todo!(), + } } } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 434dedd..f773381 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -21,6 +21,7 @@ pub use context_element::Walkable; pub use errors::CompileError; pub use errors::RenderError; pub use errors::WalkError; +pub use parameters_context::math_ints; pub use renderer::compile_template; pub use renderer::DustRenderer; pub use select_context::SelectContext; diff --git a/src/renderer/parameters_context.rs b/src/renderer/parameters_context.rs index 5a6f80b..85a422d 100644 --- a/src/renderer/parameters_context.rs +++ b/src/renderer/parameters_context.rs @@ -388,7 +388,7 @@ impl CompareContextElement for OwnedLiteral { /// For math operations that take in integers and return integers /// (add, subtract, multiply) -fn math_ints(left: L, right: R, operation: F) -> Option +pub fn math_ints(left: L, right: R, operation: F) -> Option where L: Into, R: Into,