zen_expression/variable/types/
conv.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use crate::variable::types::VariableType;
use serde_json::Value;
use std::borrow::Cow;
use std::ops::Deref;
use std::rc::Rc;

impl<'a> From<Cow<'a, Value>> for VariableType {
    fn from(value: Cow<'a, Value>) -> Self {
        match value.deref() {
            Value::Null => VariableType::Null,
            Value::Bool(_) => VariableType::Bool,
            Value::Number(_) => VariableType::Number,
            Value::String(_) => VariableType::String,
            Value::Array(_) => {
                let Value::Array(arr) = value.into_owned() else {
                    panic!("unexpected type of value, expected array");
                };

                VariableType::from(arr)
            }
            Value::Object(_) => {
                let Value::Object(obj) = value.into_owned() else {
                    panic!("unexpected type of value, expected object");
                };

                VariableType::Object(
                    obj.into_iter()
                        .map(|(k, v)| (k, Rc::new(v.into())))
                        .collect(),
                )
            }
        }
    }
}

impl From<Value> for VariableType {
    fn from(value: Value) -> Self {
        VariableType::from(Cow::Owned(value)).into()
    }
}

impl From<&Value> for VariableType {
    fn from(value: &Value) -> Self {
        VariableType::from(Cow::Borrowed(value)).into()
    }
}

impl From<Vec<Value>> for VariableType {
    fn from(arr: Vec<Value>) -> Self {
        if arr.len() == 0 {
            return VariableType::Array(Rc::new(VariableType::Any));
        }

        let result_type = arr
            .into_iter()
            .fold(None, |acc: Option<VariableType>, b| match acc {
                Some(a) => Some(a.merge(&VariableType::from(b))),
                None => Some(VariableType::from(b)),
            });

        VariableType::Array(Rc::new(result_type.unwrap_or(VariableType::Any)))
    }
}

impl From<&Vec<Value>> for VariableType {
    fn from(arr: &Vec<Value>) -> Self {
        if arr.len() == 0 {
            return VariableType::Array(Rc::new(VariableType::Any));
        }

        let result_type = arr
            .iter()
            .fold(None, |acc: Option<VariableType>, b| match acc {
                Some(a) => Some(a.merge(&VariableType::from(b))),
                None => Some(VariableType::from(b)),
            });

        VariableType::Array(Rc::new(result_type.unwrap_or(VariableType::Any)))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;

    #[test]
    fn test_value_to_value_kind() {
        assert_eq!(VariableType::from(json!(null)), VariableType::Null);
        assert_eq!(VariableType::from(json!(true)), VariableType::Bool);
        assert_eq!(VariableType::from(json!(42)), VariableType::Number);
        assert_eq!(VariableType::from(json!("hello")), VariableType::String);
    }
}