From ae00dae48a9756f255b635f6076dfe3a157fbd07 Mon Sep 17 00:00:00 2001 From: Tess Gauthier Date: Tue, 5 Mar 2024 14:48:32 -0500 Subject: [PATCH 1/4] add mul function --- dsc_lib/src/functions/mod.rs | 2 ++ dsc_lib/src/functions/mul.rs | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 dsc_lib/src/functions/mul.rs diff --git a/dsc_lib/src/functions/mod.rs b/dsc_lib/src/functions/mod.rs index 400b8293..70b8e6f8 100644 --- a/dsc_lib/src/functions/mod.rs +++ b/dsc_lib/src/functions/mod.rs @@ -11,6 +11,7 @@ pub mod base64; pub mod concat; pub mod create_array; pub mod envvar; +pub mod mul; pub mod parameters; pub mod resource_id; @@ -58,6 +59,7 @@ impl FunctionDispatcher { functions.insert("concat".to_string(), Box::new(concat::Concat{})); functions.insert("createArray".to_string(), Box::new(create_array::CreateArray{})); functions.insert("envvar".to_string(), Box::new(envvar::Envvar{})); + functions.insert("mul".to_string(), Box::new(mul::Mul{})); functions.insert("parameters".to_string(), Box::new(parameters::Parameters{})); functions.insert("resourceId".to_string(), Box::new(resource_id::ResourceId{})); Self { diff --git a/dsc_lib/src/functions/mul.rs b/dsc_lib/src/functions/mul.rs new file mode 100644 index 00000000..fb2d33b9 --- /dev/null +++ b/dsc_lib/src/functions/mul.rs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use crate::DscError; +use crate::configure::context::Context; +use crate::functions::{AcceptedArgKind, Function}; +use serde_json::Value; +use tracing::trace; + +#[derive(Debug, Default)] +pub struct Mul {} + +impl Function for Mul { + fn min_args(&self) -> usize { + 2 + } + + fn max_args(&self) -> usize { + 2 + } + + fn accepted_arg_types(&self) -> Vec { + vec![AcceptedArgKind::Number] + } + + fn invoke(&self, args: &[Value], _context: &Context) -> Result { + trace!("mul function"); + let value = args[0].as_i64().unwrap_or_default() * args[1].as_i64().unwrap_or_default(); + Ok(Value::Number(value.into())) + } +} + +#[cfg(test)] +mod tests { + use crate::configure::context::Context; + use crate::parser::Statement; + + #[test] + fn numbers() { + let mut parser = Statement::new().unwrap(); + let result = parser.parse_and_execute("[mul(2, 3)]", &Context::new()).unwrap(); + assert_eq!(result, 6); + } + + #[test] + fn nested() { + let mut parser = Statement::new().unwrap(); + let result = parser.parse_and_execute("[mul(2, mul(3, 4))]", &Context::new()).unwrap(); + assert_eq!(result, 24); + } + + #[test] + fn invalid_one_parameter() { + let mut parser = Statement::new().unwrap(); + let result = parser.parse_and_execute("[mul(5)]", &Context::new()); + assert!(result.is_err()); + } +} From 14f87aba4463f763e67be2c5c44db85611d3ba58 Mon Sep 17 00:00:00 2001 From: Tess Gauthier Date: Tue, 5 Mar 2024 14:50:26 -0500 Subject: [PATCH 2/4] use debug instead of trace --- dsc_lib/src/functions/mul.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dsc_lib/src/functions/mul.rs b/dsc_lib/src/functions/mul.rs index fb2d33b9..c813bebe 100644 --- a/dsc_lib/src/functions/mul.rs +++ b/dsc_lib/src/functions/mul.rs @@ -5,7 +5,7 @@ use crate::DscError; use crate::configure::context::Context; use crate::functions::{AcceptedArgKind, Function}; use serde_json::Value; -use tracing::trace; +use tracing::debug; #[derive(Debug, Default)] pub struct Mul {} @@ -24,7 +24,7 @@ impl Function for Mul { } fn invoke(&self, args: &[Value], _context: &Context) -> Result { - trace!("mul function"); + debug!("mul function"); let value = args[0].as_i64().unwrap_or_default() * args[1].as_i64().unwrap_or_default(); Ok(Value::Number(value.into())) } From 2d87447c4cd7c783b27785e47ce2ad7485aec7cd Mon Sep 17 00:00:00 2001 From: Tess Gauthier Date: Wed, 6 Mar 2024 10:43:37 -0500 Subject: [PATCH 3/4] test for int overflow --- dsc_lib/src/functions/mul.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/dsc_lib/src/functions/mul.rs b/dsc_lib/src/functions/mul.rs index c813bebe..286de680 100644 --- a/dsc_lib/src/functions/mul.rs +++ b/dsc_lib/src/functions/mul.rs @@ -25,7 +25,7 @@ impl Function for Mul { fn invoke(&self, args: &[Value], _context: &Context) -> Result { debug!("mul function"); - let value = args[0].as_i64().unwrap_or_default() * args[1].as_i64().unwrap_or_default(); + let value = args[0].as_i64().unwrap() * args[1].as_i64().unwrap(); Ok(Value::Number(value.into())) } } @@ -55,4 +55,19 @@ mod tests { let result = parser.parse_and_execute("[mul(5)]", &Context::new()); assert!(result.is_err()); } + + #[test] + fn overflow_result() { + let mut parser = Statement::new().unwrap(); + // max value for i64 is 2^63 -1 (or 9,223,372,036,854,775,807) + let result = parser.parse_and_execute("[mul(9223372036854775807, 2)]", &Context::new()); + assert!(result.is_err()); + } + + #[test] + fn overflow_input() { + let mut parser = Statement::new().unwrap(); + let result = parser.parse_and_execute("[mul(9223372036854775808, 2)]", &Context::new()); + assert!(result.is_err()); + } } From 8c2e017b63e6e302441261d473726a9fbf1a5d9c Mon Sep 17 00:00:00 2001 From: Tess Gauthier Date: Wed, 6 Mar 2024 15:55:23 -0500 Subject: [PATCH 4/4] change unwrap call --- dsc_lib/src/functions/mul.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dsc_lib/src/functions/mul.rs b/dsc_lib/src/functions/mul.rs index 286de680..888a463d 100644 --- a/dsc_lib/src/functions/mul.rs +++ b/dsc_lib/src/functions/mul.rs @@ -25,8 +25,11 @@ impl Function for Mul { fn invoke(&self, args: &[Value], _context: &Context) -> Result { debug!("mul function"); - let value = args[0].as_i64().unwrap() * args[1].as_i64().unwrap(); - Ok(Value::Number(value.into())) + if let (Some(arg1), Some(arg2)) = (args[0].as_i64(), args[1].as_i64()) { + Ok(Value::Number((arg1 * arg2).into())) + } else { + Err(DscError::Parser("Invalid argument(s)".to_string())) + } } }