Skip to content

Commit 28cfb87

Browse files
authored
Merge pull request #353 from tgauth/add-sub-function
implement sub function
2 parents f4ed69b + 86968f4 commit 28cfb87

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

dsc_lib/src/functions/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub mod envvar;
1515
pub mod mul;
1616
pub mod parameters;
1717
pub mod resource_id;
18+
pub mod sub;
1819

1920
/// The kind of argument that a function accepts.
2021
#[derive(Debug, PartialEq)]
@@ -64,6 +65,7 @@ impl FunctionDispatcher {
6465
functions.insert("mul".to_string(), Box::new(mul::Mul{}));
6566
functions.insert("parameters".to_string(), Box::new(parameters::Parameters{}));
6667
functions.insert("resourceId".to_string(), Box::new(resource_id::ResourceId{}));
68+
functions.insert("sub".to_string(), Box::new(sub::Sub{}));
6769
Self {
6870
functions,
6971
}

dsc_lib/src/functions/sub.rs

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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 Sub {}
12+
13+
impl Function for Sub {
14+
fn min_args(&self) -> usize {
15+
2
16+
}
17+
18+
fn max_args(&self) -> usize {
19+
2
20+
}
21+
22+
fn accepted_arg_types(&self) -> Vec<AcceptedArgKind> {
23+
vec![AcceptedArgKind::Number]
24+
}
25+
26+
fn invoke(&self, args: &[Value], _context: &Context) -> Result<Value, DscError> {
27+
debug!("sub function");
28+
if let (Some(arg1), Some(arg2)) = (args[0].as_i64(), args[1].as_i64()) {
29+
Ok(Value::Number((arg1 - arg2).into()))
30+
} else {
31+
Err(DscError::Parser("Invalid argument(s)".to_string()))
32+
}
33+
}
34+
}
35+
36+
#[cfg(test)]
37+
mod tests {
38+
use crate::configure::context::Context;
39+
use crate::parser::Statement;
40+
41+
#[test]
42+
fn numbers() {
43+
let mut parser = Statement::new().unwrap();
44+
let result = parser.parse_and_execute("[sub(7, 3)]", &Context::new()).unwrap();
45+
assert_eq!(result, 4);
46+
}
47+
48+
#[test]
49+
fn nested() {
50+
let mut parser = Statement::new().unwrap();
51+
let result = parser.parse_and_execute("[sub(9, sub(5, 3))]", &Context::new()).unwrap();
52+
assert_eq!(result, 7);
53+
}
54+
55+
#[test]
56+
fn invalid_one_parameter() {
57+
let mut parser = Statement::new().unwrap();
58+
let result = parser.parse_and_execute("[sub(5)]", &Context::new());
59+
assert!(result.is_err());
60+
}
61+
62+
#[test]
63+
fn overflow_result() {
64+
let mut parser = Statement::new().unwrap();
65+
// max value for i64 is 2^63 -1 (or 9,223,372,036,854,775,807)
66+
let result = parser.parse_and_execute("[sub(9223372036854775807, -2)]", &Context::new());
67+
assert!(result.is_err());
68+
}
69+
70+
#[test]
71+
fn overflow_input() {
72+
let mut parser = Statement::new().unwrap();
73+
let result = parser.parse_and_execute("[sub(9223372036854775808, 2)]", &Context::new());
74+
assert!(result.is_err());
75+
}
76+
}

0 commit comments

Comments
 (0)