gnostr_xq/
value.rs

1use std::{
2    borrow::Borrow,
3    cmp::Ordering,
4    collections::HashMap,
5    fmt::{Debug, Display, Formatter},
6    hash::{Hash, Hasher},
7    iter::FromIterator,
8    ops::Deref,
9    rc::Rc,
10    slice::SliceIndex,
11};
12
13use derive_more::{DebugCustom, Display, Index, IndexMut, IntoIterator, IsVariant, Unwrap};
14use itertools::Itertools;
15use num::Float;
16use serde::{
17    de::{Error, MapAccess, SeqAccess, Visitor},
18    ser::{SerializeMap, SerializeSeq},
19    serde_if_integer128, Deserialize, Deserializer, Serialize, Serializer,
20};
21
22use crate::Number;
23
24type Vector = Vec<Value>;
25type Map = HashMap<RcString, Value>;
26pub type RcString = Rc<String>;
27
28#[derive(
29    Clone, Eq, PartialEq, Hash, Default, DebugCustom, Display, IntoIterator, Index, IndexMut,
30)]
31#[debug(fmt = "{_0:?}")]
32#[display(fmt = "{_0:?}")]
33pub struct Array(#[into_iterator(owned, ref, ref_mut)] Vector);
34
35#[derive(Clone, Eq, PartialEq, Default, DebugCustom, Display, IntoIterator, Index, IndexMut)]
36#[debug(fmt = "{_0:?}")]
37#[display(fmt = "{_0:?}")]
38pub struct Object(#[into_iterator(owned, ref, ref_mut)] Map);
39
40#[allow(clippy::derived_hash_with_manual_eq)] // HashMap::eq is implemented properly.
41impl Hash for Object {
42    fn hash<H: Hasher>(&self, state: &mut H) {
43        for (key, value) in self.0.iter().sorted_unstable_by_key(|e| e.0) {
44            key.hash(state);
45            value.hash(state);
46        }
47    }
48}
49
50impl Array {
51    pub fn new() -> Self {
52        Default::default()
53    }
54
55    pub fn with_capacity(capacity: usize) -> Self {
56        Self(Vector::with_capacity(capacity))
57    }
58
59    pub fn from_vec(v: Vector) -> Self {
60        Self(v)
61    }
62
63    pub fn is_empty(&self) -> bool {
64        self.0.is_empty()
65    }
66
67    pub fn len(&self) -> usize {
68        self.0.len()
69    }
70
71    pub fn push<V>(&mut self, value: V)
72    where
73        V: Into<Value>,
74    {
75        self.0.push(value.into())
76    }
77
78    pub fn extend<I: IntoIterator<Item = Value>>(&mut self, iter: I) {
79        self.0.extend(iter);
80    }
81
82    pub fn get<I: SliceIndex<[Value]>>(&self, index: I) -> Option<&I::Output> {
83        self.0.get(index)
84    }
85
86    pub fn remove(&mut self, index: usize) -> Value {
87        self.0.remove(index)
88    }
89
90    pub fn split_off(&mut self, index: usize) -> Self {
91        Self(self.0.split_off(index))
92    }
93}
94
95impl Object {
96    pub fn new() -> Self {
97        Default::default()
98    }
99
100    pub fn with_capacity(capacity: usize) -> Self {
101        Self(Map::with_capacity(capacity))
102    }
103
104    pub fn is_empty(&self) -> bool {
105        self.0.is_empty()
106    }
107
108    pub fn len(&self) -> usize {
109        self.0.len()
110    }
111
112    pub fn iter(&self) -> impl Iterator<Item = (&RcString, &Value)> {
113        self.0.iter()
114    }
115
116    pub fn insert<K, V>(&mut self, key: K, value: V) -> Option<Value>
117    where
118        K: Into<RcString>,
119        V: Into<Value>,
120    {
121        self.0.insert(key.into(), value.into())
122    }
123
124    pub fn extend<T: IntoIterator<Item = (RcString, Value)>>(&mut self, iter: T) {
125        self.0.extend(iter)
126    }
127
128    pub fn keys(&self) -> impl Iterator<Item = &RcString> {
129        self.0.keys()
130    }
131
132    pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&Value>
133    where
134        RcString: Borrow<Q>,
135        Q: Hash + Eq,
136    {
137        self.0.get(key)
138    }
139
140    pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut Value>
141    where
142        RcString: Borrow<Q>,
143        Q: Hash + Eq,
144    {
145        self.0.get_mut(key)
146    }
147
148    pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<Value>
149    where
150        RcString: Borrow<Q>,
151        Q: Hash + Eq,
152    {
153        self.0.remove(key)
154    }
155
156    pub fn entry(&mut self, key: RcString) -> std::collections::hash_map::Entry<RcString, Value> {
157        self.0.entry(key)
158    }
159}
160
161impl FromIterator<Value> for Array {
162    fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
163        Array(Vector::from_iter(iter))
164    }
165}
166
167impl FromIterator<(RcString, Value)> for Object {
168    fn from_iter<T: IntoIterator<Item = (RcString, Value)>>(iter: T) -> Self {
169        Object(Map::from_iter(iter))
170    }
171}
172
173impl Deref for Array {
174    type Target = [Value];
175
176    fn deref(&self) -> &Self::Target {
177        &self.0
178    }
179}
180
181#[derive(
182    Clone, Eq, PartialEq, Hash, derive_more::From, derive_more::TryInto, IsVariant, Unwrap,
183)]
184pub enum Value {
185    Null,
186    Boolean(bool),
187    Number(Number),
188    String(RcString),
189    Array(Rc<Array>),
190    Object(Rc<Object>),
191}
192
193impl From<String> for Value {
194    fn from(s: String) -> Self {
195        Self::String(RcString::new(s))
196    }
197}
198
199impl From<Array> for Value {
200    fn from(arr: Array) -> Self {
201        Self::Array(Rc::new(arr))
202    }
203}
204
205impl From<Object> for Value {
206    fn from(obj: Object) -> Self {
207        Self::Object(Rc::new(obj))
208    }
209}
210
211impl Debug for Value {
212    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
213        match self {
214            Value::Null => f.write_str("null"),
215            Value::Boolean(v) => f.write_fmt(format_args!("{v:?}")),
216            Value::Number(v) => f.write_fmt(format_args!("{v:?}")),
217            Value::String(v) => f.write_fmt(format_args!("{v:?}")),
218            Value::Array(v) => f.write_fmt(format_args!("{:?}", v.as_ref())),
219            Value::Object(v) => f.write_fmt(format_args!("{:?}", v.as_ref())),
220        }
221    }
222}
223impl Display for Value {
224    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
225        match self {
226            Value::Null => f.write_str("null"),
227            Value::Boolean(v) => f.write_fmt(format_args!("{v:?}")),
228            Value::Number(v) => f.write_fmt(format_args!("{v:?}")),
229            Value::String(v) => f.write_fmt(format_args!("{v:?}")),
230            Value::Array(arr) => {
231                f.write_str("[")?;
232                let mut first = true;
233                for v in arr.as_ref() {
234                    if first {
235                        first = false;
236                    } else {
237                        f.write_str(", ")?;
238                    }
239                    Display::fmt(&v, f)?;
240                }
241                f.write_str("]")
242            }
243            Value::Object(obj) => {
244                f.write_str("{")?;
245                let mut first = true;
246                for (k, v) in obj.as_ref() {
247                    if first {
248                        first = false;
249                    } else {
250                        f.write_str(", ")?;
251                    }
252                    f.write_fmt(format_args!("{k}: {v}"))?;
253                }
254                f.write_str("}")
255            }
256        }
257    }
258}
259
260impl Value {
261    pub fn number<T: Into<Number>>(n: T) -> Self {
262        // TODO: Replace the caller with into
263        n.into().into()
264    }
265    pub fn string(s: String) -> Self {
266        // TODO: Replace the caller with into
267        s.into()
268    }
269}
270
271impl Serialize for Value {
272    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
273    where
274        S: Serializer,
275    {
276        match self {
277            Value::Null => serializer.serialize_none(),
278            Value::Boolean(v) => serializer.serialize_bool(*v),
279            Value::Number(v) => {
280                if v.is_finite() {
281                    v.serialize(serializer)
282                } else if v.is_nan() {
283                    serializer.serialize_none()
284                } else if v.is_sign_negative() {
285                    serializer.serialize_f64(f64::MIN)
286                } else {
287                    serializer.serialize_f64(f64::MAX)
288                }
289            }
290            Value::String(s) => serializer.serialize_str(s),
291            Value::Array(arr) => {
292                let mut seq = serializer.serialize_seq(Some(arr.len()))?;
293                for e in arr.as_ref() {
294                    seq.serialize_element::<Value>(e)?;
295                }
296                seq.end()
297            }
298            Value::Object(obj) => {
299                let mut map = serializer.serialize_map(Some(obj.len()))?;
300                for (k, v) in obj.as_ref() {
301                    map.serialize_entry::<String, Value>(k, v)?;
302                }
303                map.end()
304            }
305        }
306    }
307}
308
309impl<'de> Deserialize<'de> for Value {
310    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
311    where
312        D: Deserializer<'de>,
313    {
314        struct V;
315        impl<'de> Visitor<'de> for V {
316            type Value = Value;
317
318            fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
319                write!(
320                    formatter,
321                    "null, boolean, number, string, array, or map keyed with string"
322                )
323            }
324
325            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
326            where
327                E: serde::de::Error,
328            {
329                Ok(v.into())
330            }
331
332            fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
333            where
334                E: serde::de::Error,
335            {
336                Ok(Value::number(v))
337            }
338
339            fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
340            where
341                E: serde::de::Error,
342            {
343                Ok(Value::number(v))
344            }
345
346            serde_if_integer128! {
347                fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
348                where
349                    E: serde::de::Error,
350                {
351                    Ok(Value::number(v))
352                }
353
354                fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
355                where
356                    E: serde::de::Error,
357                {
358                    Ok(Value::number(v))
359                }
360            }
361
362            fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
363            where
364                E: serde::de::Error,
365            {
366                Ok(Value::number(v))
367            }
368
369            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
370            where
371                E: serde::de::Error,
372            {
373                Ok(v.to_string().into())
374            }
375
376            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
377            where
378                E: serde::de::Error,
379            {
380                Ok(v.into())
381            }
382
383            fn visit_none<E>(self) -> Result<Self::Value, E>
384            where
385                E: serde::de::Error,
386            {
387                Ok(Value::Null)
388            }
389
390            fn visit_unit<E>(self) -> Result<Self::Value, E>
391            where
392                E: Error,
393            {
394                Ok(Value::Null)
395            }
396
397            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
398            where
399                A: SeqAccess<'de>,
400            {
401                let mut arr = if let Some(n) = seq.size_hint() {
402                    Array::with_capacity(n)
403                } else {
404                    Array::new()
405                };
406                while let Some(elem) = seq.next_element::<Value>()? {
407                    arr.push(elem);
408                }
409                Ok(arr.into())
410            }
411
412            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
413            where
414                A: MapAccess<'de>,
415            {
416                let mut obj = if let Some(n) = map.size_hint() {
417                    Object::with_capacity(n)
418                } else {
419                    Object::new()
420                };
421                while let Some((key, value)) = map.next_entry::<String, Value>()? {
422                    obj.insert(key, value);
423                }
424                Ok(obj.into())
425            }
426        }
427        deserializer.deserialize_any(V)
428    }
429}
430
431impl PartialOrd for Value {
432    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
433        Some(Self::cmp(self, other))
434    }
435}
436
437impl Ord for Value {
438    fn cmp(&self, other: &Self) -> Ordering {
439        use Ordering::*;
440        use Value::*;
441        fn type_ord(value: &Value) -> u8 {
442            match value {
443                Null => 0,
444                Boolean(_) => 1,
445                Number(_) => 2,
446                String(_) => 3,
447                Array(_) => 4,
448                Object(_) => 5,
449            }
450        }
451        if let res @ (Less | Greater) = type_ord(self).cmp(&type_ord(other)) {
452            return res;
453        }
454        return match (&self, &other) {
455            (Null, Null) => Equal,
456            (Boolean(lhs), Boolean(rhs)) => Ord::cmp(lhs, rhs),
457            (Number(lhs), Number(rhs)) => Ord::cmp(&lhs, &rhs),
458            (String(lhs), String(rhs)) => Ord::cmp(&lhs, &rhs),
459            (Array(lhs), Array(rhs)) => return Iterator::cmp(lhs.iter(), rhs.iter()),
460            (Object(lhs), Object(rhs)) => {
461                let lhs_keys = lhs.keys().sorted_unstable().collect_vec();
462                let rhs_keys = rhs.keys().sorted_unstable().collect_vec();
463                if let res @ (Less | Greater) = Iterator::cmp(lhs_keys.iter(), rhs_keys.iter()) {
464                    return res;
465                }
466                for key in lhs_keys {
467                    if let res @ (Less | Greater) = Ord::cmp(&lhs.get(key), &rhs.get(key)) {
468                        return res;
469                    }
470                }
471                Equal
472            }
473            (Null | Boolean(_) | Number(_) | String(_) | Array(_) | Object(_), _) => {
474                unreachable!()
475            }
476        };
477    }
478}