Skip to content

Commit d85f90e

Browse files
authored
Merge pull request #375 from tgauth/add-max-function
add max function
2 parents 38cb5f0 + 917fdc0 commit d85f90e

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

dsc_lib/src/functions/max.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
use crate::DscError;
5+
use crate::configure::context::Context;
6+
use crate::functions::{AcceptedArgKind, Function};
7+
use serde_json::Value;
8+
use tracing::debug;
9+
10+
#[derive(Debug, Default)]
11+
pub struct Max {}
12+
13+
impl Function for Max {
14+
fn min_args(&self) -> usize {
15+
1
16+
}
17+
18+
fn max_args(&self) -> usize {
19+
usize::MAX
20+
}
21+
22+
fn accepted_arg_types(&self) -> Vec<AcceptedArgKind> {
23+
vec![AcceptedArgKind::Number, AcceptedArgKind::Array]
24+
}
25+
26+
fn invoke(&self, args: &[Value], _context: &Context) -> Result<Value, DscError> {
27+
debug!("max function");
28+
if args.len() == 1 {
29+
if let Some(array) = args[0].as_array() {
30+
find_max(array)
31+
}
32+
else {
33+
Err(DscError::Parser("Array cannot be empty".to_string()))
34+
}
35+
}
36+
else {
37+
find_max(args)
38+
}
39+
}
40+
}
41+
42+
fn find_max(args: &[Value]) -> Result<Value, DscError> {
43+
let array = args.iter().map(|v| v.as_i64().ok_or(DscError::Parser("Input must only contain integers".to_string()))).collect::<Result<Vec<i64>, DscError>>()?;
44+
let value = array.iter().max().ok_or(DscError::Parser("Unable to find max value".to_string()))?;
45+
Ok(Value::Number((*value).into()))
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
use crate::configure::context::Context;
51+
use crate::parser::Statement;
52+
53+
#[test]
54+
fn list() {
55+
let mut parser = Statement::new().unwrap();
56+
let result = parser.parse_and_execute("[max(3,2,5,4)]", &Context::new()).unwrap();
57+
assert_eq!(result, 5);
58+
}
59+
60+
#[test]
61+
fn list_with_spaces() {
62+
let mut parser = Statement::new().unwrap();
63+
let result = parser.parse_and_execute("[max(3, 2, 5, 4)]", &Context::new()).unwrap();
64+
assert_eq!(result, 5);
65+
}
66+
67+
#[test]
68+
fn array() {
69+
let mut parser = Statement::new().unwrap();
70+
let result = parser.parse_and_execute("[max(createArray(0, 3, 2, 7, 4)]", &Context::new()).unwrap();
71+
assert_eq!(result, 7);
72+
}
73+
74+
#[test]
75+
fn array_single_value() {
76+
let mut parser = Statement::new().unwrap();
77+
let result = parser.parse_and_execute("[max(createArray(0)]", &Context::new()).unwrap();
78+
assert_eq!(result, 0);
79+
}
80+
81+
#[test]
82+
fn arrays() {
83+
let mut parser = Statement::new().unwrap();
84+
let result = parser.parse_and_execute("[max(createArray(0, 3), createArray(2, 5))]", &Context::new());
85+
assert!(result.is_err());
86+
}
87+
88+
#[test]
89+
fn string_and_numbers() {
90+
let mut parser = Statement::new().unwrap();
91+
let result = parser.parse_and_execute("[max('a', 1)]", &Context::new());
92+
assert!(result.is_err());
93+
}
94+
95+
#[test]
96+
fn nested() {
97+
let mut parser = Statement::new().unwrap();
98+
let result = parser.parse_and_execute("[max(-10, max(-2, -9), -5)]", &Context::new()).unwrap();
99+
assert_eq!(result, -2);
100+
}
101+
102+
#[test]
103+
fn int_and_array() {
104+
let mut parser = Statement::new().unwrap();
105+
let result = parser.parse_and_execute("[max(1, createArray(0,2))]", &Context::new());
106+
assert!(result.is_err());
107+
}
108+
109+
#[test]
110+
fn array_and_int() {
111+
let mut parser = Statement::new().unwrap();
112+
let result = parser.parse_and_execute("[max(createArray(0,2), 1)]", &Context::new());
113+
assert!(result.is_err());
114+
}
115+
}

dsc_lib/src/functions/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub mod concat;
1313
pub mod create_array;
1414
pub mod div;
1515
pub mod envvar;
16+
pub mod max;
1617
pub mod min;
1718
pub mod mod_function;
1819
pub mod mul;
@@ -67,6 +68,7 @@ impl FunctionDispatcher {
6768
functions.insert("createArray".to_string(), Box::new(create_array::CreateArray{}));
6869
functions.insert("div".to_string(), Box::new(div::Div{}));
6970
functions.insert("envvar".to_string(), Box::new(envvar::Envvar{}));
71+
functions.insert("max".to_string(), Box::new(max::Max{}));
7072
functions.insert("min".to_string(), Box::new(min::Min{}));
7173
functions.insert("mod".to_string(), Box::new(mod_function::Mod{}));
7274
functions.insert("mul".to_string(), Box::new(mul::Mul{}));

0 commit comments

Comments
 (0)