Skip to main content

rok_utils/types/
mod.rs

1#[cfg(feature = "json")]
2use serde_json::Value;
3
4#[cfg(feature = "json")]
5pub fn is_string(val: &Value) -> bool {
6    val.is_string()
7}
8
9#[cfg(feature = "json")]
10pub fn is_number(val: &Value) -> bool {
11    val.is_number()
12}
13
14#[cfg(feature = "json")]
15pub fn is_bool(val: &Value) -> bool {
16    val.is_boolean()
17}
18
19#[cfg(feature = "json")]
20pub fn is_array(val: &Value) -> bool {
21    val.is_array()
22}
23
24#[cfg(feature = "json")]
25pub fn is_object(val: &Value) -> bool {
26    val.is_object()
27}
28
29#[cfg(feature = "json")]
30pub fn is_null(val: &Value) -> bool {
31    val.is_null()
32}
33
34#[cfg(feature = "json")]
35pub fn is_defined(val: &Value) -> bool {
36    !val.is_null()
37}
38
39#[cfg(feature = "json")]
40pub fn deep_equal(a: &Value, b: &Value) -> bool {
41    match (a, b) {
42        (Value::Null, Value::Null) => true,
43        (Value::Bool(a), Value::Bool(b)) => a == b,
44        (Value::Number(a), Value::Number(b)) => a == b,
45        (Value::String(a), Value::String(b)) => a == b,
46        (Value::Array(a), Value::Array(b)) => {
47            a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| deep_equal(x, y))
48        }
49        (Value::Object(a), Value::Object(b)) => {
50            a.len() == b.len()
51                && a.iter()
52                    .all(|(k, v)| b.get(k).map(|bv| deep_equal(v, bv)).unwrap_or(false))
53        }
54        _ => false,
55    }
56}
57
58#[cfg(feature = "json")]
59pub fn get_path<'a>(val: &'a Value, path: &str) -> Option<&'a Value> {
60    let mut current: Option<&'a Value> = Some(val);
61    for key in path.split('.') {
62        current = current.and_then(|v| {
63            if let Some(obj) = v.as_object() {
64                obj.get(key)
65            } else if let Some(arr) = v.as_array() {
66                key.parse::<usize>().ok().and_then(|i| arr.get(i))
67            } else {
68                None
69            }
70        });
71    }
72    current
73}
74
75#[cfg(feature = "json")]
76pub fn set_path(val: Value, path: &str, new: Value) -> Value {
77    let keys: Vec<&str> = path.split('.').collect();
78    if keys.is_empty() {
79        return new;
80    }
81
82    let mut result = val;
83    if let Some(_last) = keys.last() {
84        for key in &keys[..keys.len() - 1] {
85            if result.get(*key).is_none() {
86                if let Ok(idx) = key.parse::<usize>() {
87                    while result.as_array().map(|a| a.len()).unwrap_or(0) <= idx {
88                        result = Value::Array(vec![result, Value::Null]);
89                    }
90                } else {
91                    result = Value::Object(serde_json::Map::new());
92                }
93            }
94        }
95    }
96
97    if let Value::Object(ref mut obj) = result {
98        if let Some(last_key) = keys.last() {
99            obj.insert(last_key.to_string(), new);
100        }
101    }
102    result
103}
104
105#[cfg(feature = "json")]
106#[cfg(test)]
107mod tests {
108    use super::*;
109    use serde_json::json;
110
111    #[test]
112    fn test_is_string() {
113        assert!(is_string(&json!("hello")));
114        assert!(!is_string(&json!(42)));
115    }
116
117    #[test]
118    fn test_is_number() {
119        assert!(is_number(&json!(42)));
120        assert!(!is_number(&json!("hello")));
121    }
122
123    #[test]
124    fn test_is_bool() {
125        assert!(is_bool(&json!(true)));
126        assert!(!is_bool(&json!(42)));
127    }
128
129    #[test]
130    fn test_is_array() {
131        assert!(is_array(&json!([1, 2, 3])));
132        assert!(!is_array(&json!(42)));
133    }
134
135    #[test]
136    fn test_is_object() {
137        assert!(is_object(&json!({"a": 1})));
138        assert!(!is_object(&json!([1, 2])));
139    }
140
141    #[test]
142    fn test_is_null() {
143        assert!(is_null(&json!(null)));
144        assert!(!is_null(&json!(42)));
145    }
146
147    #[test]
148    fn test_deep_equal() {
149        assert!(deep_equal(&json!({"a": 1}), &json!({"a": 1})));
150        assert!(!deep_equal(&json!({"a": 1}), &json!({"a": 2})));
151    }
152
153    #[test]
154    fn test_get_path() {
155        let val = json!({"user": {"address": {"city": "NYC"}}});
156        assert_eq!(get_path(&val, "user.address.city"), Some(&json!("NYC")));
157    }
158
159    #[test]
160    fn test_set_path() {
161        let val = json!({"a": 1});
162        let result = set_path(val, "b", json!(2));
163        assert_eq!(result.get("b"), Some(&json!(2)));
164    }
165}