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.
This commit is contained in:
Tom Alexander 2020-06-13 18:34:13 -04:00
parent db11677b22
commit df0ae05648
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 60 additions and 2 deletions

View File

@ -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<IceResult<'a>> {
todo!()
match (
self,
other.to_any().downcast_ref::<Self>(),
other.to_any().downcast_ref::<OwnedLiteral>(),
) {
// 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!(),
}
}
}

View File

@ -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;

View File

@ -388,7 +388,7 @@ impl CompareContextElement for OwnedLiteral {
/// For math operations that take in integers and return integers
/// (add, subtract, multiply)
fn math_ints<L, R, F>(left: L, right: R, operation: F) -> Option<OwnedLiteral>
pub fn math_ints<L, R, F>(left: L, right: R, operation: F) -> Option<OwnedLiteral>
where
L: Into<i128>,
R: Into<i128>,