sonic_rs/
index.rs

1use crate::{
2    util::{private::Sealed, reborrow::DormantMutRef},
3    JsonValueMutTrait, JsonValueTrait, PointerNode, Value,
4};
5
6impl<I> std::ops::Index<I> for Value
7where
8    I: Index,
9{
10    type Output = Value;
11
12    /// Index into an array `Value` using the syntax `value[0]` and index into an
13    /// object `Value` using the syntax `value["k"]`.
14    ///
15    /// Returns a null `Value` if the `Value` type does not match the index, or the
16    /// index does not exist in the array or object.
17    ///
18    /// For retrieving deeply nested values, you should have a look at the `Value::pointer` method.
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// use sonic_rs::{json, pointer, JsonValueTrait};
24    ///
25    /// let data = json!({
26    ///     "x": {
27    ///         "y": ["z", "zz"]
28    ///     }
29    /// });
30    ///
31    /// assert_eq!(data["x"]["y"], json!(["z", "zz"]));
32    /// assert_eq!(data["x"]["y"][0], json!("z"));
33    ///
34    /// assert_eq!(data["a"], json!(null)); // returns null for undefined values
35    /// assert_eq!(data["a"]["b"], json!(null)); // does not panic
36    ///
37    /// // use pointer for retrieving nested values
38    /// assert_eq!(data.pointer(&pointer!["x", "y", 0]).unwrap(), &json!("z"));
39    /// ```
40    #[inline]
41    fn index(&self, index: I) -> &Value {
42        static NULL: Value = Value::new();
43        index.value_index_into(self).unwrap_or(&NULL)
44    }
45}
46
47impl<I: Index> std::ops::IndexMut<I> for Value {
48    /// Write the index of a mutable `Value`, and use the syntax `value[0] = ...`
49    /// in an array and `value["k"] = ...` in an object.
50    ///
51    /// If the index is a number, the value must be an array of length bigger
52    /// than the index. Indexing into a value that is not an array or an array
53    /// that is too small will panic.
54    ///
55    /// If the index is a string, the value must be an object or null which is
56    /// treated like an empty object. If the key is not already present in the
57    /// object, it will be inserted with a value of null. Indexing into a value
58    /// that is neither an object nor null will panic.
59    ///
60    /// # Examples
61    ///
62    /// ```
63    /// # use sonic_rs::json;
64    /// # use sonic_rs::object;
65    /// let mut data = json!({ "x": 0, "z": null });
66    ///
67    /// // replace an existing key
68    /// data["x"] = json!(1);
69    ///
70    /// // insert a new key
71    /// data["y"] = json!([1, 2, 3]);
72    ///
73    /// // replace an array value
74    /// data["y"][0] = json!(true);
75    ///
76    /// // inserted a deeply nested key
77    /// data["a"]["b"]["c"]["d"] = json!(true);
78    ///
79    /// //insert an key in a null value
80    /// data["z"]["zz"] = json!("insert in null");
81    ///
82    /// data["z"]["zz1"] = object!{}.into();
83    ///
84    ///
85    /// assert_eq!(data, json!({
86    ///   "x": 1,
87    ///   "y": [true, 2, 3],
88    ///   "a": { "b": {"c": {"d": true}}},
89    ///    "z": {"zz": "insert in null", "zz1": {}}
90    /// }));
91    /// ```
92    #[inline]
93    fn index_mut(&mut self, index: I) -> &mut Value {
94        index.index_or_insert(self)
95    }
96}
97
98/// An indexing trait for JSON.
99pub trait Index: Sealed {
100    /// Return None if the index is not already in the array or object.
101    #[doc(hidden)]
102    fn value_index_into<'v>(&self, v: &'v Value) -> Option<&'v Value>;
103
104    /// Return None if the key is not already in the array or object.
105    #[doc(hidden)]
106    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value>;
107
108    /// Panic if array index out of bounds. If key is not already in the object,
109    /// insert it with a value of null. Panic if Value is a type that cannot be
110    /// indexed into, except if Value is null then it can be treated as an empty
111    /// object.
112    #[doc(hidden)]
113    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value;
114
115    #[doc(hidden)]
116    fn as_key(&self) -> Option<&str> {
117        None
118    }
119
120    #[doc(hidden)]
121    fn as_index(&self) -> Option<usize> {
122        None
123    }
124}
125
126impl Index for usize {
127    fn value_index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
128        if !v.is_array() {
129            return None;
130        }
131        v.get_index(*self)
132    }
133
134    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
135        if !v.is_array() {
136            return None;
137        }
138        v.get_index_mut(*self)
139    }
140
141    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
142        let typ = v.get_type();
143        let len = v.len();
144        v.as_array_mut()
145            .unwrap_or_else(|| panic!("cannot access index in non-array value type {typ:?}"))
146            .0
147            .get_index_mut(*self)
148            .unwrap_or_else(|| panic!("index {} out of bounds (len: {})", *self, len))
149    }
150
151    fn as_index(&self) -> Option<usize> {
152        Some(*self)
153    }
154}
155
156macro_rules! impl_str_index {
157    ($($t: ty),*) => {
158        $(
159            impl Index for &$t {
160                #[inline]
161                fn value_index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
162                    if !v.is_object() {
163                        return None;
164                    }
165                    v.get_key(*self)
166                }
167
168                #[inline]
169                fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
170                    if !v.is_object() {
171                        return None;
172                    }
173                    v.get_key_mut(*self)
174                }
175
176                #[inline]
177                fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
178                    if v.is_null() {
179                        *v = Value::new_object_with(8);
180                    }
181
182                    let typ = v.get_type();
183                    let (obj, mut dormant_obj) = DormantMutRef::new(v);
184                    obj.as_object_mut()
185                        .expect(&format!("cannot access key in non-object value {:?}", typ))
186                        .0
187                        .get_key_mut(*self).unwrap_or_else(|| {
188                            let o =  unsafe { dormant_obj.reborrow() };
189                            let inserted = o.insert(&self, Value::new_null());
190                            inserted
191                        })
192                }
193
194                #[inline]
195                fn as_key(&self) -> Option<&str> {
196                    Some(self.as_ref())
197                }
198            }
199        )*
200    };
201}
202
203impl_str_index!(str, String, faststr::FastStr);
204
205impl Index for PointerNode {
206    #[inline]
207    fn value_index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
208        match self {
209            PointerNode::Index(i) => i.value_index_into(v),
210            PointerNode::Key(k) => k.value_index_into(v),
211        }
212    }
213
214    #[inline]
215    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
216        match self {
217            PointerNode::Index(i) => i.index_into_mut(v),
218            PointerNode::Key(k) => k.index_into_mut(v),
219        }
220    }
221
222    #[inline]
223    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
224        match self {
225            PointerNode::Index(i) => i.index_or_insert(v),
226            PointerNode::Key(k) => k.index_or_insert(v),
227        }
228    }
229
230    #[inline]
231    fn as_index(&self) -> Option<usize> {
232        match self {
233            PointerNode::Index(i) => Some(*i),
234            PointerNode::Key(_) => None,
235        }
236    }
237
238    #[inline]
239    fn as_key(&self) -> Option<&str> {
240        match self {
241            PointerNode::Index(_) => None,
242            PointerNode::Key(k) => Some(k.as_ref()),
243        }
244    }
245}
246
247impl<T> Index for &T
248where
249    T: ?Sized + Index,
250{
251    #[inline]
252    fn value_index_into<'v>(&self, v: &'v Value) -> Option<&'v Value> {
253        (**self).value_index_into(v)
254    }
255
256    #[inline]
257    fn index_into_mut<'v>(&self, v: &'v mut Value) -> Option<&'v mut Value> {
258        (**self).index_into_mut(v)
259    }
260
261    #[inline]
262    fn index_or_insert<'v>(&self, v: &'v mut Value) -> &'v mut Value {
263        (**self).index_or_insert(v)
264    }
265
266    #[inline]
267    fn as_index(&self) -> Option<usize> {
268        (**self).as_index()
269    }
270
271    #[inline]
272    fn as_key(&self) -> Option<&str> {
273        (**self).as_key()
274    }
275}