Skip to main content

qql_core/ast/
value.rs

1#[cfg(feature = "json")]
2use crate::error::QqlError;
3use alloc::string::String;
4use alloc::vec::Vec;
5
6#[derive(Clone, PartialEq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub enum Value {
9    Str(String),
10    Int(i64),
11    Float(f64),
12    Bool(bool),
13    Null,
14    Dict(Vec<(String, Value)>),
15    List(Vec<Value>),
16}
17
18impl core::fmt::Debug for Value {
19    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20        match self {
21            Self::Str(value) => f.debug_tuple("Str").field(value).finish(),
22            Self::Int(value) => f.debug_tuple("Int").field(value).finish(),
23            Self::Float(value) => f.debug_tuple("Float").field(value).finish(),
24            Self::Bool(value) => f.debug_tuple("Bool").field(value).finish(),
25            Self::Null => f.write_str("Null"),
26            Self::Dict(value) => f.debug_tuple("Dict").field(value).finish(),
27            Self::List(value) => f.debug_tuple("List").field(value).finish(),
28        }
29    }
30}
31
32impl Value {
33    pub fn dict_get(&self, key: &str) -> Option<&Value> {
34        match self {
35            Self::Dict(items) => items
36                .iter()
37                .find(|(candidate, _)| candidate.eq_ignore_ascii_case(key))
38                .map(|(_, value)| value),
39            _ => None,
40        }
41    }
42
43    pub fn dict_set(&mut self, key: String, value: Value) {
44        if let Self::Dict(items) = self {
45            if let Some((_, current)) = items
46                .iter_mut()
47                .find(|(candidate, _)| candidate.eq_ignore_ascii_case(&key))
48            {
49                *current = value;
50            } else {
51                items.push((key, value));
52            }
53        }
54    }
55
56    pub fn as_str(&self) -> Option<&str> {
57        match self {
58            Self::Str(value) => Some(value),
59            _ => None,
60        }
61    }
62
63    #[cfg(feature = "json")]
64    pub fn from_json(value: serde_json::Value) -> Result<Self, QqlError> {
65        match value {
66            serde_json::Value::String(value) => Ok(Self::Str(value)),
67            serde_json::Value::Number(value) => value
68                .as_i64()
69                .map(Self::Int)
70                .or_else(|| value.as_f64().map(Self::Float))
71                .ok_or_else(|| {
72                    QqlError::validation(
73                        "QQL-JSON-NUMBER",
74                        "JSON number cannot be represented by QQL",
75                        None,
76                    )
77                }),
78            serde_json::Value::Bool(value) => Ok(Self::Bool(value)),
79            serde_json::Value::Null => Ok(Self::Null),
80            serde_json::Value::Array(items) => items
81                .into_iter()
82                .map(Self::from_json)
83                .collect::<Result<Vec<_>, _>>()
84                .map(Self::List),
85            serde_json::Value::Object(items) => items
86                .into_iter()
87                .map(|(key, value)| Self::from_json(value).map(|value| (key, value)))
88                .collect::<Result<Vec<_>, _>>()
89                .map(Self::Dict),
90        }
91    }
92
93    #[cfg(feature = "json")]
94    pub fn to_json(&self) -> Result<serde_json::Value, QqlError> {
95        match self {
96            Self::Str(value) => Ok(serde_json::Value::String(value.clone())),
97            Self::Int(value) => Ok(serde_json::Value::Number((*value).into())),
98            Self::Float(value) => serde_json::Number::from_f64(*value)
99                .map(serde_json::Value::Number)
100                .ok_or_else(|| {
101                    QqlError::validation(
102                        "QQL-JSON-NONFINITE",
103                        "non-finite floats cannot be converted to JSON",
104                        None,
105                    )
106                }),
107            Self::Bool(value) => Ok(serde_json::Value::Bool(*value)),
108            Self::Null => Ok(serde_json::Value::Null),
109            Self::Dict(items) => {
110                let mut object = serde_json::Map::new();
111                for (key, value) in items {
112                    object.insert(key.clone(), value.to_json()?);
113                }
114                Ok(serde_json::Value::Object(object))
115            }
116            Self::List(items) => items
117                .iter()
118                .map(Self::to_json)
119                .collect::<Result<Vec<_>, _>>()
120                .map(serde_json::Value::Array),
121        }
122    }
123}