Skip to content

Commit e3918ca

Browse files
authored
Merge pull request #376 from tgauth/add-int-function
add int function
2 parents ffd58ca + d73f73e commit e3918ca

File tree

4 files changed

+89
-0
lines changed

4 files changed

+89
-0
lines changed

dsc_lib/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ base64 = "0.21"
88
derive_builder ="0.20"
99
indicatif = { version = "0.17" }
1010
jsonschema = "0.17"
11+
num-traits = "0.2"
1112
regex = "1.7"
1213
reqwest = { version = "0.11", features = ["blocking"] }
1314
schemars = { version = "0.8.12", features = ["preserve_order"] }

dsc_lib/src/dscerror.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ pub enum DscError {
2323
#[error("Function '{0}' error: {1}")]
2424
Function(String, String),
2525

26+
#[error("Function '{0}' error: {1}")]
27+
FunctionArg(String, String),
28+
2629
#[error("HTTP: {0}")]
2730
Http(#[from] reqwest::Error),
2831

dsc_lib/src/functions/int.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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;
7+
use num_traits::cast::NumCast;
8+
use serde_json::Value;
9+
use super::Function;
10+
11+
#[derive(Debug, Default)]
12+
pub struct Int {}
13+
14+
impl Function for Int {
15+
fn accepted_arg_types(&self) -> Vec<AcceptedArgKind> {
16+
vec![AcceptedArgKind::String, AcceptedArgKind::Number]
17+
}
18+
19+
fn min_args(&self) -> usize {
20+
1
21+
}
22+
23+
fn max_args(&self) -> usize {
24+
1
25+
}
26+
27+
fn invoke(&self, args: &[Value], _context: &Context) -> Result<Value, DscError> {
28+
let arg = &args[0];
29+
let value: i64;
30+
if arg.is_string() {
31+
let input = arg.as_str().ok_or(DscError::FunctionArg("int".to_string(), "invalid input string".to_string()))?;
32+
let result = input.parse::<f64>().map_err(|_| DscError::FunctionArg("int".to_string(), "unable to parse string to int".to_string()))?;
33+
value = NumCast::from(result).ok_or(DscError::FunctionArg("int".to_string(), "unable to cast to int".to_string()))?;
34+
} else if arg.is_number() {
35+
value = arg.as_i64().ok_or(DscError::FunctionArg("int".to_string(), "unable to parse number to int".to_string()))?;
36+
} else {
37+
return Err(DscError::FunctionArg("int".to_string(), "Invalid argument type".to_string()));
38+
}
39+
Ok(Value::Number(value.into()))
40+
}
41+
}
42+
43+
#[cfg(test)]
44+
mod tests {
45+
use crate::configure::context::Context;
46+
use crate::parser::Statement;
47+
use crate::DscError;
48+
49+
#[test]
50+
fn string() {
51+
let mut parser = Statement::new().unwrap();
52+
let result = parser.parse_and_execute("[int('4')]", &Context::new()).unwrap();
53+
assert_eq!(result, 4);
54+
}
55+
56+
#[test]
57+
fn string_with_decimal() {
58+
let mut parser = Statement::new().unwrap();
59+
let result = parser.parse_and_execute("[int('4.0')]", &Context::new()).unwrap();
60+
assert_eq!(result, 4);
61+
}
62+
63+
#[test]
64+
fn number() {
65+
let mut parser = Statement::new().unwrap();
66+
let result = parser.parse_and_execute("[int(123)]", &Context::new()).unwrap();
67+
assert_eq!(result, 123);
68+
}
69+
70+
#[test]
71+
fn nested() {
72+
let mut parser = Statement::new().unwrap();
73+
let result = parser.parse_and_execute("[int(int('-1'))]", &Context::new()).unwrap();
74+
assert_eq!(result, -1);
75+
}
76+
77+
#[test]
78+
fn error() {
79+
let mut parser = Statement::new().unwrap();
80+
let err = parser.parse_and_execute("[int('foo')]", &Context::new()).unwrap_err();
81+
assert!(matches!(err, DscError::FunctionArg(_, _)));
82+
}
83+
}

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 int;
1617
pub mod max;
1718
pub mod min;
1819
pub mod mod_function;
@@ -68,6 +69,7 @@ impl FunctionDispatcher {
6869
functions.insert("createArray".to_string(), Box::new(create_array::CreateArray{}));
6970
functions.insert("div".to_string(), Box::new(div::Div{}));
7071
functions.insert("envvar".to_string(), Box::new(envvar::Envvar{}));
72+
functions.insert("int".to_string(), Box::new(int::Int{}));
7173
functions.insert("max".to_string(), Box::new(max::Max{}));
7274
functions.insert("min".to_string(), Box::new(min::Min{}));
7375
functions.insert("mod".to_string(), Box::new(mod_function::Mod{}));

0 commit comments

Comments
 (0)