assemblyline_models/types/
json_validation.rs

1use std::str::FromStr;
2
3use serde_json::Value;
4
5
6pub fn validate_string(value: Value) -> Result<Value, Value> {
7    match value {
8        Value::String(value) => Ok(Value::String(value)),
9        Value::Number(number) => Ok(Value::String(number.to_string())),
10        value => Err(value)
11    }
12}
13
14pub fn validate_uppercase(value: Value) -> Result<Value, Value> {
15    match value {
16        Value::String(value) => Ok(Value::String(value.to_uppercase())),
17        Value::Number(number) => Ok(Value::String(number.to_string())),
18        value => Err(value)
19    }
20}
21
22pub fn validate_lowercase(value: Value) -> Result<Value, Value> {
23    match value {
24        Value::String(value) => Ok(Value::String(value.to_lowercase())),
25        Value::Number(number) => Ok(Value::String(number.to_string())),
26        value => Err(value)
27    }
28}
29
30pub fn validate_string_with<Filter: Fn(&str) -> bool>(value: Value, filter: Filter) -> Result<Value, Value> {
31    let transformed = match &value {
32        Value::String(value) => value,
33        Value::Number(number) => &number.to_string(),
34        _ => return Err(value)
35    };
36
37    if filter(transformed) {
38        Ok(Value::String(transformed.to_owned()))
39    } else {
40        Err(value)
41    }
42}
43
44pub fn transform_string_with<Filter: Fn(&str) -> Option<String>>(value: Value, filter: Filter) -> Result<Value, Value> {
45    let transformed = match &value {
46        Value::String(value) => value,
47        Value::Number(number) => &number.to_string(),
48        _ => return Err(value)
49    };
50
51    if let Some(transformed) = filter(transformed) {
52        Ok(Value::String(transformed))
53    } else {
54        Err(value)
55    }
56}
57
58pub fn validate_uppercase_with<Filter: Fn(&str) -> bool>(value: Value, filter: Filter) -> Result<Value, Value> {
59    let transformed = match &value {
60        Value::String(value) => value.to_uppercase(),
61        Value::Number(number) => number.to_string(),
62        _ => return Err(value)
63    };
64
65    if filter(&transformed) {
66        Ok(Value::String(transformed))
67    } else {
68        Err(value)
69    }
70}
71
72
73pub fn validate_lowercase_with<Filter: Fn(&str) -> bool>(value: Value, filter: Filter) -> Result<Value, Value> {
74    let transformed = match &value {
75        Value::String(value) => value.to_lowercase(),
76        Value::Number(number) => number.to_string(),
77        _ => return Err(value)
78    };
79
80    if filter(&transformed) {
81        Ok(Value::String(transformed))
82    } else {
83        Err(value)
84    }
85}
86
87
88pub fn validate_number<TYPE: FromStr + Into<serde_json::Number>>(value: Value) -> Result<Value, Value> {
89    match value {
90        Value::String(value) => {
91            let value: TYPE = match value.parse() {
92                Ok(value) => value,
93                Err(_) => return Err(Value::String(value))
94            };
95            Ok(Value::Number(value.into()))
96        },
97        Value::Bool(true) => Ok(Value::Number(1.into())),
98        Value::Bool(false) => Ok(Value::Number(0.into())),
99        Value::Number(number) => {
100            // TODO this is less efficient than it could be if we didn't go round trip to string
101            let value: TYPE = match number.to_string().parse() {
102                Ok(value) => value,
103                Err(_) => return Err(Value::String(number.to_string()))
104            };
105            Ok(Value::Number(value.into()))
106        },
107        value => Err(value)
108    }
109}
110
111// HashMap<String, Vec<String>>
112pub fn validate_rule_mapping(root: Value) -> Result<Value, Value> {
113    match root { 
114        Value::Object(mut obj) => {
115            for (_, value) in &mut obj {
116                if let Value::Array(items) = value {
117                    for item in items {
118                        if !item.is_string() {
119                            *item = Value::String(item.to_string())
120                        }
121                    }
122                } else {
123                    return Err(Value::Object(obj))
124                }
125            }
126            Ok(Value::Object(obj))
127        },
128        value => Err(value)
129    }
130}