From be3e55c079fe43f8f35ebe5add00fd05ef912f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?PedroGon=C3=A7aloCorreia?= Date: Sat, 13 Oct 2018 23:26:20 +0100 Subject: [PATCH] feat(liquid_filters): add filters "at_least" and "at_most" Add two filters specified in the Liquid tutorial: - at_least - at_most --- src/filters/math.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++ src/filters/mod.rs | 2 +- src/parser.rs | 2 ++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/filters/math.rs b/src/filters/math.rs index a1e4b498f..4c54333b7 100644 --- a/src/filters/math.rs +++ b/src/filters/math.rs @@ -17,6 +17,52 @@ pub fn abs(input: &Value, args: &[Value]) -> FilterResult { } } +/// Limits a number to a minimum value. +pub fn at_least(input: &Value, args: &[Value]) -> FilterResult { + check_args_len(args, 1, 0)?; + let input = input + .as_scalar() + .ok_or_else(|| invalid_input("Number expected"))?; + + let max_value = args[0] + .as_scalar() + .ok_or_else(|| invalid_argument(0, "Number expected"))?; + + let result = input + .to_integer() + .and_then(|i| max_value.to_integer().map(|max| Value::scalar(i.max(max)))) + .or_else(|| { + input + .to_float() + .and_then(|i| max_value.to_float().map(|max| Value::scalar(i.max(max)))) + }).ok_or_else(|| invalid_argument(0, "Number expected"))?; + + Ok(result) +} + +/// Limits a number to a maximum value. +pub fn at_most(input: &Value, args: &[Value]) -> FilterResult { + check_args_len(args, 1, 0)?; + let input = input + .as_scalar() + .ok_or_else(|| invalid_input("Number expected"))?; + + let max_value = args[0] + .as_scalar() + .ok_or_else(|| invalid_argument(0, "Number expected"))?; + + let result = input + .to_integer() + .and_then(|i| max_value.to_integer().map(|max| Value::scalar(i.min(max)))) + .or_else(|| { + input + .to_float() + .and_then(|i| max_value.to_float().map(|max| Value::scalar(i.min(max)))) + }).ok_or_else(|| invalid_argument(0, "Number expected"))?; + + Ok(result) +} + pub fn plus(input: &Value, args: &[Value]) -> FilterResult { check_args_len(args, 1, 0)?; @@ -199,6 +245,44 @@ mod tests { assert_eq!(unit!(abs, tos!("-19.86"), &[]), Value::scalar(19.86f64)); } #[test] + fn unit_at_least() { + assert_eq!( + unit!(at_least, Value::scalar(4f64), &[Value::scalar(5f64)]), + Value::scalar(5f64) + ); + assert_eq!( + unit!(at_least, Value::scalar(4f64), &[Value::scalar(3f64)]), + Value::scalar(4f64) + ); + assert_eq!( + unit!(at_least, Value::scalar(21.5), &[Value::scalar(2.25)]), + Value::scalar(21.5) + ); + assert_eq!( + unit!(at_least, Value::scalar(21.5), &[Value::scalar(42.25)]), + Value::scalar(42.25) + ); + } + #[test] + fn unit_at_most() { + assert_eq!( + unit!(at_most, Value::scalar(4f64), &[Value::scalar(5f64)]), + Value::scalar(4f64) + ); + assert_eq!( + unit!(at_most, Value::scalar(4f64), &[Value::scalar(3f64)]), + Value::scalar(3f64) + ); + assert_eq!( + unit!(at_most, Value::scalar(21.5), &[Value::scalar(2.25)]), + Value::scalar(2.25) + ); + assert_eq!( + unit!(at_most, Value::scalar(21.5), &[Value::scalar(42.25)]), + Value::scalar(21.5) + ); + } + #[test] fn unit_plus() { assert_eq!( unit!(plus, Value::scalar(2f64), &[Value::scalar(1f64)]), diff --git a/src/filters/mod.rs b/src/filters/mod.rs index f28f957ad..e60728a70 100644 --- a/src/filters/mod.rs +++ b/src/filters/mod.rs @@ -7,7 +7,7 @@ pub use self::date::date; #[cfg(feature = "extra-filters")] pub use self::date::date_in_tz; pub use self::html::{escape, escape_once, newline_to_br, strip_html}; -pub use self::math::{abs, divided_by, minus, modulo, plus, times}; +pub use self::math::{abs, at_least, at_most, divided_by, minus, modulo, plus, times}; pub use self::url::{url_decode, url_encode}; use std::borrow::Cow; diff --git a/src/parser.rs b/src/parser.rs index 71d1a0215..5b8f24c68 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -58,6 +58,8 @@ impl ParserBuilder { pub fn liquid_filters(self) -> Self { self.filter("abs", filters::abs as interpreter::FnFilterValue) .filter("append", filters::append as interpreter::FnFilterValue) + .filter("at_least", filters::at_least as interpreter::FnFilterValue) + .filter("at_most", filters::at_most as interpreter::FnFilterValue) .filter( "capitalize", filters::capitalize as interpreter::FnFilterValue,