Skip to main content

deser_value/
index.rs

1use crate::map::{Map, MapKey};
2use crate::value::{Kind, Value};
3
4mod sealed {
5    pub trait Sealed {}
6}
7
8/// A type that can index into a [`Value`].
9///
10/// Sequences are indexed by `usize`, maps by strings or any other
11/// [`Value`] as key.  This is used by [`Kind::get`] and the `Index`
12/// implementation of [`Value`].
13///
14/// ```
15/// use deser_value::value;
16///
17/// let value = value!({"items": [1, 2], 42: "answer"});
18/// assert_eq!(value["items"][1], 2);
19/// assert_eq!(value[&value!(42)], "answer");
20/// assert!(value["missing"].is_null());
21/// ```
22pub trait ValueIndex: sealed::Sealed {
23    #[doc(hidden)]
24    fn index_into<'v>(&self, value: &'v Kind) -> Option<&'v Value>;
25
26    #[doc(hidden)]
27    fn index_into_mut<'v>(&self, value: &'v mut Kind) -> Option<&'v mut Value>;
28
29    #[doc(hidden)]
30    fn index_or_insert<'v>(&self, value: &'v mut Value) -> &'v mut Value;
31}
32
33impl sealed::Sealed for usize {}
34
35impl ValueIndex for usize {
36    fn index_into<'v>(&self, value: &'v Kind) -> Option<&'v Value> {
37        match value {
38            Kind::Seq(seq) => seq.get(*self),
39            _ => None,
40        }
41    }
42
43    fn index_into_mut<'v>(&self, value: &'v mut Kind) -> Option<&'v mut Value> {
44        match value {
45            Kind::Seq(seq) => seq.get_mut(*self),
46            _ => None,
47        }
48    }
49
50    fn index_or_insert<'v>(&self, value: &'v mut Value) -> &'v mut Value {
51        match &mut value.kind {
52            Kind::Seq(seq) => {
53                let len = seq.len();
54                seq.get_mut(*self).unwrap_or_else(|| {
55                    panic!(
56                        "index {} out of bounds for sequence of length {}",
57                        self, len
58                    )
59                })
60            }
61            other => panic!("cannot index into {} with an integer", other.name()),
62        }
63    }
64}
65
66/// Indexes into maps by key.
67fn index_or_insert_key<'v, K: MapKey + ?Sized>(
68    key: &K,
69    make_key: impl FnOnce() -> Value,
70    value: &'v mut Value,
71) -> &'v mut Value {
72    if let Kind::Null = value.kind {
73        value.kind = Kind::Map(Map::new());
74    }
75    match &mut value.kind {
76        Kind::Map(map) => {
77            if let Some(index) = map.get_index_of(key) {
78                map.get_index_mut(index).unwrap().1
79            } else {
80                map.get_or_insert_with(make_key(), Value::null)
81            }
82        }
83        other => panic!("cannot index into {} with a key", other.name()),
84    }
85}
86
87impl sealed::Sealed for str {}
88
89impl ValueIndex for str {
90    fn index_into<'v>(&self, value: &'v Kind) -> Option<&'v Value> {
91        value.as_map().and_then(|map| map.get(self))
92    }
93
94    fn index_into_mut<'v>(&self, value: &'v mut Kind) -> Option<&'v mut Value> {
95        value.as_map_mut().and_then(|map| map.get_mut(self))
96    }
97
98    fn index_or_insert<'v>(&self, value: &'v mut Value) -> &'v mut Value {
99        index_or_insert_key(self, || Value::from(self), value)
100    }
101}
102
103impl sealed::Sealed for String {}
104
105impl ValueIndex for String {
106    fn index_into<'v>(&self, value: &'v Kind) -> Option<&'v Value> {
107        self.as_str().index_into(value)
108    }
109
110    fn index_into_mut<'v>(&self, value: &'v mut Kind) -> Option<&'v mut Value> {
111        self.as_str().index_into_mut(value)
112    }
113
114    fn index_or_insert<'v>(&self, value: &'v mut Value) -> &'v mut Value {
115        self.as_str().index_or_insert(value)
116    }
117}
118
119impl sealed::Sealed for Value {}
120
121impl ValueIndex for Value {
122    fn index_into<'v>(&self, value: &'v Kind) -> Option<&'v Value> {
123        value.as_map().and_then(|map| map.get(self))
124    }
125
126    fn index_into_mut<'v>(&self, value: &'v mut Kind) -> Option<&'v mut Value> {
127        value.as_map_mut().and_then(|map| map.get_mut(self))
128    }
129
130    fn index_or_insert<'v>(&self, value: &'v mut Value) -> &'v mut Value {
131        index_or_insert_key(self, || self.clone(), value)
132    }
133}
134
135impl<T: ValueIndex + ?Sized> sealed::Sealed for &T {}
136
137impl<T: ValueIndex + ?Sized> ValueIndex for &T {
138    fn index_into<'v>(&self, value: &'v Kind) -> Option<&'v Value> {
139        (**self).index_into(value)
140    }
141
142    fn index_into_mut<'v>(&self, value: &'v mut Kind) -> Option<&'v mut Value> {
143        (**self).index_into_mut(value)
144    }
145
146    fn index_or_insert<'v>(&self, value: &'v mut Value) -> &'v mut Value {
147        (**self).index_or_insert(value)
148    }
149}