jmap_tools/json/
value.rs

1use crate::json::index::Index;
2use crate::json::key::Key;
3use crate::json::num::{N, Number};
4pub use crate::json::object_vec::ObjectAsVec;
5use core::fmt;
6use core::hash::Hash;
7use std::borrow::Cow;
8use std::fmt::{Debug, Display};
9use std::str::FromStr;
10
11/// Represents any valid JMAP value.
12#[derive(Clone, Eq, PartialEq, Hash, Default)]
13pub enum Value<'ctx, P: Property, E: Element> {
14    #[default]
15    Null,
16    Bool(bool),
17    Number(Number),
18    Element(E),
19    Str(Cow<'ctx, str>),
20    Array(Vec<Value<'ctx, P, E>>),
21    Object(ObjectAsVec<'ctx, P, E>),
22}
23
24pub trait Property: Debug + Clone + PartialEq + Eq + PartialOrd + Ord + Hash {
25    fn try_parse(key: Option<&Key<'_, Self>>, value: &str) -> Option<Self>;
26    fn to_cow(&self) -> Cow<'static, str>;
27}
28
29pub trait Element: Clone + PartialEq + Eq + Hash + Debug + Sized {
30    type Property: Property;
31
32    fn try_parse<P>(key: &Key<'_, Self::Property>, value: &str) -> Option<Self>;
33    fn to_cow(&self) -> Cow<'static, str>;
34}
35
36impl<'ctx, P: Property, E: Element<Property = P>> Value<'ctx, P, E> {
37    pub fn new_object() -> Self {
38        Value::Object(ObjectAsVec::from(Vec::new()))
39    }
40
41    pub fn new_boolean_set(set: impl IntoIterator<Item = (Key<'ctx, P>, bool)>) -> Self {
42        let mut obj = Vec::new();
43        for (key, value) in set {
44            obj.push((key, value.into()));
45        }
46        Value::Object(obj.into())
47    }
48
49    pub fn parse_json(json: &'ctx str) -> Result<Self, String> {
50        serde_json::from_str(json).map_err(|e| e.to_string())
51    }
52
53    /// Returns a reference to the value corresponding to the key.
54    #[inline]
55    pub fn get<I: Index<'ctx, P, E>>(&'ctx self, index: I) -> &'ctx Value<'ctx, P, E> {
56        index.index_into(self).unwrap_or(&Value::Null)
57    }
58
59    pub fn is_object_and_contains_key(&self, key: &Key<'_, P>) -> bool {
60        match self {
61            Value::Object(obj) => obj.contains_key(key),
62            _ => false,
63        }
64    }
65
66    pub fn is_object_and_contains_any_key(&self, keys: &[Key<'_, P>]) -> bool {
67        match self {
68            Value::Object(obj) => obj.contains_any_key(keys),
69            _ => false,
70        }
71    }
72
73    /// Returns true if `Value` is Value::Null.
74    pub fn is_null(&self) -> bool {
75        matches!(self, Value::Null)
76    }
77
78    /// Returns true if `Value` is Value::Array.
79    pub fn is_array(&self) -> bool {
80        matches!(self, Value::Array(_))
81    }
82
83    /// Returns true if `Value` is Value::Object.
84    pub fn is_object(&self) -> bool {
85        matches!(self, Value::Object(_))
86    }
87
88    /// Returns true if `Value` is Value::Bool.
89    pub fn is_bool(&self) -> bool {
90        matches!(self, Value::Bool(_))
91    }
92
93    /// Returns true if `Value` is Value::Number.
94    pub fn is_number(&self) -> bool {
95        matches!(self, Value::Number(_))
96    }
97
98    /// Returns true if `Value` is Value::Str.
99    pub fn is_string(&self) -> bool {
100        matches!(self, Value::Str(_))
101    }
102
103    /// Returns true if the Value is an integer between i64::MIN and i64::MAX.
104    /// For any Value on which is_i64 returns true, as_i64 is guaranteed to return the integer
105    /// value.
106    pub fn is_i64(&self) -> bool {
107        match self {
108            Value::Number(n) => n.is_i64(),
109            _ => false,
110        }
111    }
112
113    /// Returns true if the Value is an integer between zero and u64::MAX.
114    /// For any Value on which is_u64 returns true, as_u64 is guaranteed to return the integer
115    /// value.
116    pub fn is_u64(&self) -> bool {
117        match self {
118            Value::Number(n) => n.is_u64(),
119            _ => false,
120        }
121    }
122
123    /// Returns true if the Value is a f64 number.
124    pub fn is_f64(&self) -> bool {
125        match self {
126            Value::Number(n) => n.is_f64(),
127            _ => false,
128        }
129    }
130
131    /// If the Value is an Array, returns an iterator over the elements in the array.
132    pub fn iter_array(&self) -> Option<impl Iterator<Item = &Value<'_, P, E>>> {
133        match self {
134            Value::Array(arr) => Some(arr.iter()),
135            _ => None,
136        }
137    }
138
139    /// If the Value is an Object, returns an iterator over the elements in the object.
140    pub fn iter_object(&self) -> Option<impl Iterator<Item = (&Key<'_, P>, &Value<'_, P, E>)>> {
141        match self {
142            Value::Object(arr) => Some(arr.iter()),
143            _ => None,
144        }
145    }
146
147    /// If the Value is an Array, returns the associated Array. Returns None otherwise.
148    pub fn as_array(&self) -> Option<&[Value<'ctx, P, E>]> {
149        match self {
150            Value::Array(arr) => Some(arr),
151            _ => None,
152        }
153    }
154
155    pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value<'ctx, P, E>>> {
156        match self {
157            Value::Array(arr) => Some(arr),
158            _ => None,
159        }
160    }
161
162    pub fn into_array(self) -> Option<Vec<Value<'ctx, P, E>>> {
163        match self {
164            Value::Array(arr) => Some(arr),
165            _ => None,
166        }
167    }
168
169    /// If the Value is an Object, returns the associated Object. Returns None otherwise.
170    pub fn as_object(&self) -> Option<&ObjectAsVec<'ctx, P, E>> {
171        match self {
172            Value::Object(obj) => Some(obj),
173            _ => None,
174        }
175    }
176
177    pub fn as_object_mut(&mut self) -> Option<&mut ObjectAsVec<'ctx, P, E>> {
178        match self {
179            Value::Object(obj) => Some(obj),
180            _ => None,
181        }
182    }
183
184    pub fn into_object(self) -> Option<ObjectAsVec<'ctx, P, E>> {
185        match self {
186            Value::Object(obj) => Some(obj),
187            _ => None,
188        }
189    }
190
191    pub fn into_owned(self) -> Value<'static, P, E> {
192        match self {
193            Value::Null => Value::Null,
194            Value::Bool(b) => Value::Bool(b),
195            Value::Number(n) => Value::Number(n),
196            Value::Element(e) => Value::Element(e),
197            Value::Str(s) => Value::Str(Cow::Owned(s.into_owned())),
198            Value::Array(arr) => {
199                let owned_arr: Vec<Value<'static, P, E>> =
200                    arr.into_iter().map(|v| v.into_owned()).collect();
201                Value::Array(owned_arr)
202            }
203            Value::Object(obj) => Value::Object(
204                obj.into_vec()
205                    .into_iter()
206                    .map(|(k, v)| (k.into_owned(), v.into_owned()))
207                    .collect(),
208            ),
209        }
210    }
211
212    pub fn into_expanded_object(self) -> impl Iterator<Item = (Key<'ctx, P>, Value<'ctx, P, E>)> {
213        self.into_object()
214            .map(|obj| obj.into_vec())
215            .unwrap_or_default()
216            .into_iter()
217    }
218
219    pub fn into_expanded_boolean_set(self) -> impl Iterator<Item = Key<'ctx, P>> {
220        self.into_object()
221            .map(|obj| obj.into_vec())
222            .unwrap_or_default()
223            .into_iter()
224            .filter_map(|(key, value)| value.as_bool().filter(|&b| b).map(|_| key))
225    }
226
227    pub fn into_element(self) -> Option<E> {
228        match self {
229            Value::Element(element) => Some(element),
230            _ => None,
231        }
232    }
233
234    /// If the Value is a Boolean, returns the associated bool. Returns None otherwise.
235    pub fn as_bool(&self) -> Option<bool> {
236        match self {
237            Value::Bool(b) => Some(*b),
238            _ => None,
239        }
240    }
241
242    /// If the Value is a String, returns the associated str. Returns None otherwise.
243    pub fn as_str(&self) -> Option<Cow<'_, str>> {
244        match self {
245            Value::Str(text) => Some(text.as_ref().into()),
246            Value::Element(element) => Some(element.to_cow()),
247            _ => None,
248        }
249    }
250
251    pub fn into_string(self) -> Option<Cow<'ctx, str>> {
252        match self {
253            Value::Str(text) => Some(text),
254            Value::Element(element) => Some(element.to_cow()),
255            _ => None,
256        }
257    }
258
259    pub fn into_owned_string(self) -> Option<String> {
260        match self {
261            Value::Str(text) => Some(text.into_owned()),
262            Value::Element(element) => Some(element.to_cow().into_owned()),
263            _ => None,
264        }
265    }
266
267    /// If the Value is an integer, represent it as i64 if possible. Returns None otherwise.
268    pub fn as_i64(&self) -> Option<i64> {
269        match self {
270            Value::Number(n) => n.as_i64(),
271            _ => None,
272        }
273    }
274
275    /// If the Value is an integer, represent it as u64 if possible. Returns None otherwise.
276    pub fn as_u64(&self) -> Option<u64> {
277        match self {
278            Value::Number(n) => n.as_u64(),
279            _ => None,
280        }
281    }
282
283    /// If the Value is a number, represent it as f64 if possible. Returns None otherwise.
284    pub fn as_f64(&self) -> Option<f64> {
285        match self {
286            Value::Number(n) => n.as_f64(),
287            _ => None,
288        }
289    }
290}
291
292impl<P: Property, E: Element> From<bool> for Value<'_, P, E> {
293    fn from(val: bool) -> Self {
294        Value::Bool(val)
295    }
296}
297
298impl<'a, P: Property, E: Element> From<&'a str> for Value<'a, P, E> {
299    fn from(val: &'a str) -> Self {
300        Value::Str(Cow::Borrowed(val))
301    }
302}
303
304impl<P: Property, E: Element> From<String> for Value<'_, P, E> {
305    fn from(val: String) -> Self {
306        Value::Str(Cow::Owned(val))
307    }
308}
309
310impl<'x, P: Property, E: Element> From<Cow<'x, str>> for Value<'x, P, E> {
311    fn from(val: Cow<'x, str>) -> Self {
312        Value::Str(val)
313    }
314}
315
316impl<'a, P: Property, E: Element, T: Into<Value<'a, P, E>>> From<Vec<T>> for Value<'a, P, E> {
317    fn from(val: Vec<T>) -> Self {
318        Value::Array(val.into_iter().map(Into::into).collect())
319    }
320}
321
322impl<'a, P: Property, E: Element, T: Clone + Into<Value<'a, P, E>>> From<&[T]> for Value<'a, P, E> {
323    fn from(val: &[T]) -> Self {
324        Value::Array(val.iter().map(Clone::clone).map(Into::into).collect())
325    }
326}
327
328impl<P: Property, E: Element> Debug for Value<'_, P, E> {
329    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
330        match self {
331            Value::Null => formatter.write_str("Null"),
332            Value::Bool(boolean) => write!(formatter, "Bool({})", boolean),
333            Value::Number(number) => match number.n {
334                N::PosInt(n) => write!(formatter, "Number({:?})", n),
335                N::NegInt(n) => write!(formatter, "Number({:?})", n),
336                N::Float(n) => write!(formatter, "Number({:?})", n),
337            },
338            Value::Str(string) => write!(formatter, "Str({:?})", string),
339            Value::Array(vec) => {
340                formatter.write_str("Array ")?;
341                Debug::fmt(vec, formatter)
342            }
343            Value::Object(map) => {
344                formatter.write_str("Object ")?;
345                Debug::fmt(map, formatter)
346            }
347            Value::Element(element) => write!(formatter, "Element({})", element.to_cow()),
348        }
349    }
350}
351
352// We just convert to serde_json::Value to Display
353impl<P: Property, E: Element> Display for Value<'_, P, E> {
354    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355        write!(f, "{}", serde_json::Value::from(self.clone()))
356    }
357}
358
359impl<P: Property, E: Element> From<u64> for Value<'_, P, E> {
360    fn from(val: u64) -> Self {
361        Value::Number(val.into())
362    }
363}
364
365impl<P: Property, E: Element> From<i64> for Value<'_, P, E> {
366    fn from(val: i64) -> Self {
367        Value::Number(val.into())
368    }
369}
370
371impl<P: Property, E: Element> From<f64> for Value<'_, P, E> {
372    fn from(val: f64) -> Self {
373        Value::Number(val.into())
374    }
375}
376
377impl<P: Property, E: Element> From<Value<'_, P, E>> for serde_json::Value {
378    fn from(val: Value<'_, P, E>) -> Self {
379        match val {
380            Value::Null => serde_json::Value::Null,
381            Value::Bool(val) => serde_json::Value::Bool(val),
382            Value::Number(val) => serde_json::Value::Number(val.into()),
383            Value::Str(val) => serde_json::Value::String(val.to_string()),
384            Value::Array(vals) => {
385                serde_json::Value::Array(vals.into_iter().map(|val| val.into()).collect())
386            }
387            Value::Object(vals) => serde_json::Value::Object(vals.into()),
388            Value::Element(element) => serde_json::Value::String(element.to_cow().to_string()),
389        }
390    }
391}
392
393impl<P: Property, E: Element> From<&Value<'_, P, E>> for serde_json::Value {
394    fn from(val: &Value<'_, P, E>) -> Self {
395        match val {
396            Value::Null => serde_json::Value::Null,
397            Value::Bool(val) => serde_json::Value::Bool(*val),
398            Value::Number(val) => serde_json::Value::Number((*val).into()),
399            Value::Str(val) => serde_json::Value::String(val.to_string()),
400            Value::Array(vals) => {
401                serde_json::Value::Array(vals.iter().map(|val| val.into()).collect())
402            }
403            Value::Object(vals) => serde_json::Value::Object(vals.into()),
404            Value::Element(element) => serde_json::Value::String(element.to_cow().to_string()),
405        }
406    }
407}
408
409impl<'ctx, P: Property, E: Element> From<&'ctx serde_json::Value> for Value<'ctx, P, E> {
410    fn from(value: &'ctx serde_json::Value) -> Self {
411        match value {
412            serde_json::Value::Null => Value::Null,
413            serde_json::Value::Bool(b) => Value::Bool(*b),
414            serde_json::Value::Number(n) => {
415                if let Some(n) = n.as_i64() {
416                    Value::Number(n.into())
417                } else if let Some(n) = n.as_u64() {
418                    Value::Number(n.into())
419                } else if let Some(n) = n.as_f64() {
420                    Value::Number(n.into())
421                } else {
422                    unreachable!()
423                }
424            }
425            serde_json::Value::String(val) => Value::Str(Cow::Borrowed(val)),
426            serde_json::Value::Array(arr) => {
427                let out: Vec<Value<'ctx, P, E>> = arr.iter().map(|v| v.into()).collect();
428                Value::Array(out)
429            }
430            serde_json::Value::Object(obj) => {
431                let mut ans = ObjectAsVec(Vec::with_capacity(obj.len()));
432                for (k, v) in obj {
433                    ans.insert(Key::Borrowed(k.as_str()), v.into());
434                }
435                Value::Object(ans)
436            }
437        }
438    }
439}
440
441#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
442pub struct Null;
443
444impl Display for Null {
445    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446        write!(f, "null")
447    }
448}
449
450impl AsRef<str> for Null {
451    fn as_ref(&self) -> &str {
452        "null"
453    }
454}
455
456impl FromStr for Null {
457    type Err = ();
458
459    fn from_str(_: &str) -> Result<Self, Self::Err> {
460        Err(())
461    }
462}
463
464impl Property for Null {
465    fn try_parse(_: Option<&Key<'_, Self>>, _: &str) -> Option<Self> {
466        None
467    }
468
469    fn to_cow(&self) -> Cow<'static, str> {
470        "".into()
471    }
472}
473
474impl Element for Null {
475    type Property = Null;
476
477    fn try_parse<P>(_: &Key<'_, Self::Property>, _: &str) -> Option<Self> {
478        None
479    }
480
481    fn to_cow(&self) -> Cow<'static, str> {
482        "".into()
483    }
484}
485
486#[cfg(test)]
487mod tests {
488    use std::io;
489
490    use super::*;
491
492    #[test]
493    fn from_serde() {
494        let value = &serde_json::json!({
495            "a": 1,
496            "b": "2",
497            "c": [3, 4],
498            "d": {"e": "alo"}
499        });
500
501        let value: Value<'_, Null, Null> = value.into();
502        assert_eq!(value.get("a"), &Value::Number(1i64.into()));
503        assert_eq!(value.get("b"), &Value::Str("2".into()));
504        assert_eq!(value.get("c").get(0), &Value::Number(3i64.into()));
505        assert_eq!(value.get("c").get(1), &Value::Number(4i64.into()));
506        assert_eq!(value.get("d").get("e"), &Value::Str("alo".into()));
507    }
508
509    #[test]
510    fn number_test() -> io::Result<()> {
511        let data = r#"{"val1": 123.5, "val2": 123, "val3": -123}"#;
512        let value: Value<'_, Null, Null> = serde_json::from_str(data)?;
513        assert!(value.get("val1").is_f64());
514        assert!(!value.get("val1").is_u64());
515        assert!(!value.get("val1").is_i64());
516
517        assert!(!value.get("val2").is_f64());
518        assert!(value.get("val2").is_u64());
519        assert!(value.get("val2").is_i64());
520
521        assert!(!value.get("val3").is_f64());
522        assert!(!value.get("val3").is_u64());
523        assert!(value.get("val3").is_i64());
524
525        assert!(value.get("val1").as_f64().is_some());
526        assert!(value.get("val2").as_f64().is_some());
527        assert!(value.get("val3").as_f64().is_some());
528
529        assert!(value.get("val1").as_u64().is_none());
530        assert!(value.get("val2").as_u64().is_some());
531        assert!(value.get("val3").as_u64().is_none());
532
533        assert!(value.get("val1").as_i64().is_none());
534        assert!(value.get("val2").as_i64().is_some());
535        assert!(value.get("val3").as_i64().is_some());
536
537        Ok(())
538    }
539}