sandl/
value.rs

1use std::collections::HashMap;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum Value {
5    Null,
6    Bool(bool),
7    Number(Number),
8    String(String),
9    Array(Vec<Value>),
10    Object(HashMap<String, Value>),
11}
12
13#[derive(Debug, Clone, PartialEq)]
14pub enum Number {
15    UnsignedInt(u64),
16    Int(i64),
17    Size(usize),
18    Float(f64),
19}
20
21impl Value {
22    pub fn null() -> Self {
23        Value::Null
24    }
25
26    pub fn is_null(&self) -> bool {
27        matches!(self, Value::Null)
28    }
29
30    pub fn as_bool(&self) -> Option<bool> {
31        match self {
32            Value::Bool(b) => Some(*b),
33            _ => None,
34        }
35    }
36
37    pub fn as_size(&self) -> Option<usize> {
38        match self {
39            Value::Number(Number::Size(i)) => Some(*i),
40            Value::Number(Number::Int(i)) => Some(*i as usize),
41            Value::Number(Number::UnsignedInt(i)) => Some(*i as usize),
42            Value::Number(Number::Float(f)) => Some(*f as usize),
43            _ => None,
44        }
45    }
46
47    pub fn as_u64(&self) -> Option<u64> {
48        match self {
49            Value::Number(Number::Size(i)) => Some(*i as u64),
50            Value::Number(Number::Int(i)) => Some(*i as u64),
51            Value::Number(Number::UnsignedInt(i)) => Some(*i),
52            Value::Number(Number::Float(f)) => Some(*f as u64),
53            _ => None,
54        }
55    }
56
57    pub fn as_i64(&self) -> Option<i64> {
58        match self {
59            Value::Number(Number::Int(i)) => Some(*i),
60            Value::Number(Number::Float(f)) => Some(*f as i64),
61            _ => None,
62        }
63    }
64
65    pub fn as_f64(&self) -> Option<f64> {
66        match self {
67            Value::Number(Number::Float(f)) => Some(*f),
68            Value::Number(Number::Int(i)) => Some(*i as f64),
69            _ => None,
70        }
71    }
72
73    pub fn as_str(&self) -> Option<&str> {
74        match self {
75            Value::String(s) => Some(s),
76            _ => None,
77        }
78    }
79
80    pub fn as_array(&self) -> Option<&Vec<Value>> {
81        match self {
82            Value::Array(arr) => Some(arr),
83            _ => None,
84        }
85    }
86
87    pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
88        match self {
89            Value::Array(arr) => Some(arr),
90            _ => None,
91        }
92    }
93
94    pub fn as_object(&self) -> Option<&HashMap<String, Value>> {
95        match self {
96            Value::Object(obj) => Some(obj),
97            _ => None,
98        }
99    }
100
101    pub fn as_object_mut(&mut self) -> Option<&mut HashMap<String, Value>> {
102        match self {
103            Value::Object(obj) => Some(obj),
104            _ => None,
105        }
106    }
107
108    pub fn get(&self, key: &str) -> Option<&Value> {
109        self.as_object()?.get(key)
110    }
111
112    pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
113        self.as_object_mut()?.get_mut(key)
114    }
115
116    pub fn get_index(&self, index: usize) -> Option<&Value> {
117        self.as_array()?.get(index)
118    }
119}
120
121impl From<()> for Value {
122    fn from(_: ()) -> Self {
123        Value::Null
124    }
125}
126
127impl From<bool> for Value {
128    fn from(b: bool) -> Self {
129        Value::Bool(b)
130    }
131}
132
133impl From<usize> for Value {
134    fn from(i: usize) -> Self {
135        Value::Number(Number::Size(i))
136    }
137}
138
139impl From<u64> for Value {
140    fn from(i: u64) -> Self {
141        Value::Number(Number::UnsignedInt(i))
142    }
143}
144
145impl From<i64> for Value {
146    fn from(i: i64) -> Self {
147        Value::Number(Number::Int(i))
148    }
149}
150
151impl From<i32> for Value {
152    fn from(i: i32) -> Self {
153        Value::Number(Number::Int(i as i64))
154    }
155}
156
157impl From<f64> for Value {
158    fn from(f: f64) -> Self {
159        Value::Number(Number::Float(f))
160    }
161}
162
163impl From<f32> for Value {
164    fn from(f: f32) -> Self {
165        Value::Number(Number::Float(f as f64))
166    }
167}
168
169impl From<String> for Value {
170    fn from(s: String) -> Self {
171        Value::String(s)
172    }
173}
174
175impl From<&str> for Value {
176    fn from(s: &str) -> Self {
177        Value::String(s.to_string())
178    }
179}
180
181impl<T: Into<Value>> From<Vec<T>> for Value {
182    fn from(v: Vec<T>) -> Self {
183        Value::Array(v.into_iter().map(Into::into).collect())
184    }
185}
186
187impl<T: Into<Value>> From<HashMap<String, T>> for Value {
188    fn from(m: HashMap<String, T>) -> Self {
189        Value::Object(m.into_iter().map(|(k, v)| (k, v.into())).collect())
190    }
191}
192
193// serde-json compat
194#[cfg(feature = "serde_json")]
195impl From<serde_json::Value> for Value {
196    fn from(v: serde_json::Value) -> Self {
197        match v {
198            serde_json::Value::Null => Value::Null,
199            serde_json::Value::Bool(b) => Value::Bool(b),
200            serde_json::Value::Number(n) => {
201                if let Some(i) = n.as_i64() {
202                    Value::Number(Number::Int(i))
203                } else if let Some(f) = n.as_f64() {
204                    Value::Number(Number::Float(f))
205                } else {
206                    Value::Null
207                }
208            }
209            serde_json::Value::String(s) => Value::String(s),
210            serde_json::Value::Array(arr) => {
211                Value::Array(arr.into_iter().map(Value::from).collect())
212            }
213            serde_json::Value::Object(obj) => {
214                Value::Object(obj.into_iter().map(|(k, v)| (k, Value::from(v))).collect())
215            }
216        }
217    }
218}
219
220#[cfg(feature = "serde_json")]
221impl From<Value> for serde_json::Value {
222    fn from(v: Value) -> Self {
223        match v {
224            Value::Null => serde_json::Value::Null,
225            Value::Bool(b) => serde_json::Value::Bool(b),
226            Value::Number(Number::UnsignedInt(i)) => serde_json::Value::Number(i.into()),
227            Value::Number(Number::Size(i)) => serde_json::Value::Number(i.into()),
228            Value::Number(Number::Int(i)) => serde_json::Value::Number(i.into()),
229            Value::Number(Number::Float(f)) => serde_json::Number::from_f64(f)
230                .map(serde_json::Value::Number)
231                .unwrap_or(serde_json::Value::Null),
232            Value::String(s) => serde_json::Value::String(s),
233            Value::Array(arr) => {
234                serde_json::Value::Array(arr.into_iter().map(serde_json::Value::from).collect())
235            }
236            Value::Object(obj) => serde_json::Value::Object(
237                obj.into_iter()
238                    .map(|(k, v)| (k, serde_json::Value::from(v)))
239                    .collect(),
240            ),
241        }
242    }
243}