From 68036ddd13000a9fa69c77a93765e81b7a096ff9 Mon Sep 17 00:00:00 2001 From: Mike Taghavi Date: Sat, 25 Mar 2023 12:38:39 +0100 Subject: [PATCH] Add min, max function Update README Increase version --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 2 ++ src/func.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 16ad390..f1ff3c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,7 +96,7 @@ checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jetro" -version = "0.1.0" +version = "0.2.0" dependencies = [ "dynfmt", "pest", diff --git a/Cargo.toml b/Cargo.toml index 9ba5ff2..d69f2ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jetro" -version = "0.2.0" +version = "0.2.1" edition = "2021" authors = ["Milad (Mike) Taghavi "] license = "MIT" diff --git a/README.md b/README.md index 13b4763..fa78ffa 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ By convention, functions are denoted using `#` operator. Functions can be compos | #keys | Keys associated with an object | | #values | Values associated with an object | | #reverse | Reverse the list | +| #min | Min value of numbers | +| #max | Max value of numbers | | #all | Whether all boolean values are true | | #sum | Sum of numbers | | #formats('format with placeholder {} {}', 'key_a', 'key_b') [ -> \| ->* 'binding_value' ] | Insert formatted key:value into object or return it as single key:value | diff --git a/src/func.rs b/src/func.rs index 0cddd9d..564e4b2 100644 --- a/src/func.rs +++ b/src/func.rs @@ -373,6 +373,74 @@ impl Callable for Values { } } +struct Min; +impl Callable for Min { + fn call( + &mut self, + _func: &Func, + value: &Value, + _ctx: Option<&mut Context<'_>>, + ) -> Result { + match &value { + Value::Array(ref array) => { + let mut result = array + .iter() + .filter(|v| v.is_number()) + .map(|v| v.as_f64().unwrap()) + .collect::>(); + result.sort_by(|a, b| a.partial_cmp(b).unwrap()); + match result.get(0) { + Some(output) => { + return Ok(Value::Number( + serde_json::Number::from_f64(*output).unwrap(), + )); + } + _ => { + return Ok(Value::Array(Vec::::new())); + } + } + } + _ => { + return Err(Error::FuncEval("expected value to be array".to_owned())); + } + } + } +} + +struct Max; +impl Callable for Max { + fn call( + &mut self, + _func: &Func, + value: &Value, + _ctx: Option<&mut Context<'_>>, + ) -> Result { + match &value { + Value::Array(ref array) => { + let mut result = array + .iter() + .filter(|v| v.is_number()) + .map(|v| v.as_f64().unwrap()) + .collect::>(); + result.sort_by(|a, b| b.partial_cmp(a).unwrap()); + match result.get(0) { + Some(output) => { + return Ok(Value::Number( + serde_json::Number::from_f64(*output).unwrap(), + )); + } + _ => { + return Ok(Value::Array(Vec::::new())); + } + } + } + _ => { + return Err(Error::FuncEval("expected value to be array".to_owned())); + } + } + } +} + impl Default for FuncRegistry { fn default() -> Self { let mut output = FuncRegistry::new(); @@ -386,6 +454,8 @@ impl Default for FuncRegistry { output.register("map", Box::new(MapFn)); output.register("keys", Box::new(Keys)); output.register("values", Box::new(Values)); + output.register("min", Box::new(Min)); + output.register("max", Box::new(Max)); output } }