1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use crate::{Array, JsonValue, Object};
15 
16 /// Static NULL, which is returned if the searched key-value pair does not exist.
17 static NULL: JsonValue = JsonValue::Null;
18 
19 /// This trait can be used to get an index based on the subscript of an internal member of JsonValue.
20 pub trait Index: private::IndexSealed {
21     /// Gets a common reference to the value with the specified subscript (or key) from a JsonValue.
index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue22     fn index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue;
23 
24     /// Gets a mutable reference to the value of the specified subscript (or key) from a JsonValue.
index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue25     fn index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue;
26 
27     /// Removes the member with the specified subscript (or key) from a JsonValue.
index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>28     fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>;
29 }
30 
31 impl Index for usize {
32     /// Uses the array subscript to visit the Array type of JsonValue
33     /// and get a common reference to the corresponding JsonValue.
34     /// A null type will be returned in the following two cases:
35     ///
36     /// 1.Use a subscript to visit non-array types.
37     ///
38     /// 2.The subscript exceeds the current length of the Array type.
39     ///
40     /// # Examples
41     /// ```
42     /// use ylong_json::{JsonValue, Array};
43     ///
44     /// // Non-array types
45     /// assert_eq!(JsonValue::Number(0.0.into())[0], JsonValue::Null);
46     ///
47     /// // Array type
48     /// let mut array = Array::new();
49     /// array.push(JsonValue::Null);
50     /// array.push(JsonValue::Boolean(true));
51     /// array.push(JsonValue::Number(0.0.into()));
52     ///
53     /// let value = JsonValue::Array(array);
54     ///
55     /// // When subscript < length
56     /// assert_eq!(value[0], JsonValue::Null);
57     /// assert_eq!(value[1], JsonValue::Boolean(true));
58     /// assert_eq!(value[2], JsonValue::Number(0.0.into()));
59     /// // When subscript >= length
60     /// assert_eq!(value[3], JsonValue::Null);
61     /// ```
index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue62     fn index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue {
63         if let JsonValue::Array(ref array) = value {
64             if *self < array.len() {
65                 return array.get(*self).unwrap();
66             }
67         }
68         &NULL
69     }
70 
71     /// Uses the array subscript to visit the Array type of JsonValue
72     /// and get a mutable reference to the corresponding JsonValue.
73     ///
74     /// If the visited JsonValue is not Array type, the JsonValue will be
75     /// replaced with an empty Array type and visits again with that subscript.
76     ///
77     /// If the visited JsonValue is Array type, but the subscript exceeds the length of the array,
78     /// then adds a Null type JsonValue at the end of the array and return a mutable reference of it.
79     ///
80     /// # Examples
81     /// ```
82     /// use ylong_json::{JsonValue, Array};
83     ///
84     /// // Non-array types
85     /// let mut value = JsonValue::Null;
86     /// value[0] = JsonValue::Null;
87     ///
88     /// let mut array = Array::new();
89     /// array.push(JsonValue::Null);
90     /// assert_eq!(value, JsonValue::Array(array));
91     ///
92     /// // Array type
93     /// let mut array = Array::new();
94     /// array.push(JsonValue::Null);
95     /// let mut value = JsonValue::Array(array);
96     ///
97     /// // Contains the subscript
98     /// value[0] = JsonValue::Number(0.0.into());
99     /// assert_eq!(value[0], JsonValue::Number(0.0.into()));
100     /// assert_eq!(value.try_as_array().unwrap().len(), 1);
101     ///
102     /// // Does not contain the subscript
103     /// value[1] = JsonValue::Boolean(true);
104     /// assert_eq!(value[1], JsonValue::Boolean(true));
105     /// assert_eq!(value.try_as_array().unwrap().len(), 2);
106     /// ```
index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue107     fn index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue {
108         if let JsonValue::Array(ref mut array) = value {
109             return if *self < array.len() {
110                 array.get_mut(*self).unwrap()
111             } else {
112                 array.push(JsonValue::Null);
113                 array.last_mut().unwrap()
114             };
115         }
116         *value = JsonValue::new_array(Array::new());
117         self.index_into_mut(value)
118     }
119 
120     /// Removes the element at the specified location of Array type JsonValue and returns that content.
121     ///
122     /// # Examples
123     /// ```
124     /// use ylong_json::{JsonValue, Array};
125     ///
126     /// let mut array = Array::new();
127     /// array.push(1i32.into());
128     ///
129     /// let mut value: JsonValue = JsonValue::Array(array);
130     /// assert_eq!(value[0], 1i32.into());
131     ///
132     /// let ret = value.remove(0);
133     /// assert_eq!(value[0], JsonValue::Null);
134     /// assert_eq!(ret.unwrap(), 1i32.into());
135     /// ```
index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>136     fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue> {
137         if let JsonValue::Array(ref mut array) = value {
138             if *self < array.len() {
139                 return array.remove(*self);
140             }
141         }
142         None
143     }
144 }
145 
146 impl Index for str {
147     /// Uses key to visit Object type JsonValue, and returns a common reference to corresponding JsonValue.
148     /// A null type will be returned in the following two cases:
149     ///
150     /// 1.Uses key to visit non-object types.
151     ///
152     /// 2.The searched Object type does not contain the key.
153     ///
154     /// # Examples
155     /// ```
156     /// use ylong_json::{JsonValue, Object};
157     ///
158     /// // Non-object types
159     /// assert_eq!(JsonValue::Number(0.0.into())["key"], JsonValue::Null);
160     ///
161     /// // Object type
162     /// let mut object = Object::new();
163     /// object.insert(String::from("key"), JsonValue::Number(0.0.into()));
164     ///
165     /// let value = JsonValue::Object(object);
166     ///
167     /// // The key exists.
168     /// assert_eq!(value["key"], JsonValue::Number(0.0.into()));
169     ///
170     /// // The key does not exist.
171     /// assert_eq!(value["not exist"], JsonValue::Null);
172     /// ```
index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue173     fn index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue {
174         if let JsonValue::Object(ref object) = value {
175             return object.get(self).unwrap_or(&NULL);
176         }
177         &NULL
178     }
179 
180     /// Uses key to visit Object type JsonValue, and returns a mutable reference to corresponding JsonValue.
181     ///
182     /// If the visited JsonValue is not Object type, the JsonValue will be
183     /// replaced with an empty Object type and visits again with that key.
184     ///
185     /// If the visited JsonValue is of object type but does not contain the key, a key-value pair of
186     /// the key and a null type will be inserted and returns a mutable reference to the JsonValue.
187     ///
188     ///
189     /// # Examples
190     /// ```
191     /// use ylong_json::{JsonValue, Object};
192     ///
193     /// // Non-object types
194     /// let mut value = JsonValue::Null;
195     /// let mut object = Object::new();
196     /// object.insert(String::from("key"), JsonValue::Number(0.0.into()));
197     ///
198     /// value["key"] = JsonValue::Number(0.0.into());
199     /// assert_eq!(value, JsonValue::Object(object));
200     ///
201     /// // Object type
202     /// let mut object = Object::new();
203     /// object.insert(String::from("key"), JsonValue::Number(0.0.into()));
204     /// let mut value = JsonValue::Object(object);
205     ///
206     /// // Contains the key.
207     /// value["key"] = JsonValue::Boolean(true);
208     /// assert_eq!(value["key"], JsonValue::Boolean(true));
209     /// assert_eq!(value.try_as_mut_object().unwrap().len(), 1);
210     ///
211     /// // Dose not contain the key.
212     /// value["not exist"] = JsonValue::Number(1.1.into());
213     /// assert_eq!(value["not exist"], JsonValue::Number(1.1.into()));
214     /// assert_eq!(value.try_as_mut_object().unwrap().len(), 2);
215     /// ```
index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue216     fn index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue {
217         if let JsonValue::Object(ref mut object) = value {
218             #[cfg(feature = "list_object")]
219             {
220                 return object.get_key_mut_maybe_insert(self);
221             }
222             #[cfg(feature = "vec_object")]
223             {
224                 if let Some(pos) = object.iter().position(|(k, _)| k == self) {
225                     return object.get_mut_by_position(pos).unwrap();
226                 }
227                 object.insert(String::from(self), JsonValue::Null);
228                 return object.last_mut().unwrap();
229             }
230             #[cfg(feature = "btree_object")]
231             {
232                 if !object.contains_key(self) {
233                     object.insert(String::from(self), JsonValue::Null);
234                 }
235                 return object.get_mut(self).unwrap();
236             }
237         }
238         *value = JsonValue::Object(Object::new());
239         self.index_into_mut(value)
240     }
241 
242     /// Removes the element at the specified location of Object type JsonValue and returns that content.
243     ///
244     /// # Examples
245     /// ```
246     /// use ylong_json::{Object, JsonValue};
247     ///
248     /// let mut object = Object::new();
249     /// object.insert(String::from("key"), "value".into());
250     ///
251     /// let mut value: JsonValue = object.into();
252     /// assert_eq!(value["key"], "value".into());
253     ///
254     /// let ret = value.remove("key");
255     /// assert_eq!(value["key"], JsonValue::Null);
256     /// assert_eq!(ret.unwrap(), "value".into());
257     /// ```
index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>258     fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue> {
259         if let JsonValue::Object(ref mut object) = value {
260             return object.remove(self);
261         }
262         None
263     }
264 }
265 
266 impl Index for String {
267     /// Same as 'Index for str'.
index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue268     fn index_into<'a>(&self, value: &'a JsonValue) -> &'a JsonValue {
269         self.as_str().index_into(value)
270     }
271 
272     /// Same as 'Index for str'.
index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue273     fn index_into_mut<'a>(&self, value: &'a mut JsonValue) -> &'a mut JsonValue {
274         self.as_str().index_into_mut(value)
275     }
276 
277     /// Same as 'Index for str'.
index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>278     fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue> {
279         self.as_str().index_remove(value)
280     }
281 }
282 
283 impl<'a, T> Index for &'a T
284 where
285     T: ?Sized + Index,
286 {
287     /// Implements Index for the relevant reference type.
index_into<'v>(&self, value: &'v JsonValue) -> &'v JsonValue288     fn index_into<'v>(&self, value: &'v JsonValue) -> &'v JsonValue {
289         (**self).index_into(value)
290     }
291 
292     /// Implements Index for the relevant reference type.
index_into_mut<'v>(&self, value: &'v mut JsonValue) -> &'v mut JsonValue293     fn index_into_mut<'v>(&self, value: &'v mut JsonValue) -> &'v mut JsonValue {
294         (**self).index_into_mut(value)
295     }
296 
297     /// Implements Index for the relevant reference type.
index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>298     fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue> {
299         (**self).index_remove(value)
300     }
301 }
302 
303 // To prevent the Index by external implementation.
304 mod private {
305     pub trait IndexSealed {}
306 
307     impl IndexSealed for usize {}
308 
309     impl IndexSealed for str {}
310 
311     impl IndexSealed for String {}
312 
313     impl<'a, T> IndexSealed for &'a T where T: ?Sized + IndexSealed {}
314 }
315 
316 #[cfg(test)]
317 mod ut_index {
318     use crate::{Array, Index, JsonValue, Object};
319 
320     /// UT test for `usize::index_into`.
321     ///
322     /// # Title
323     /// ut_usize_index_into
324     ///
325     /// # Brief
326     /// 1. Creates some `usize`s and some `JsonValue`s.
327     /// 2. Calls `Index::index_into`.
328     /// 3. Checks if the test results are correct.
329     #[test]
ut_usize_index_into()330     fn ut_usize_index_into() {
331         let value = JsonValue::new_boolean(true);
332         assert!(1usize.index_into(&value).is_null());
333     }
334 
335     /// UT test for `usize::index_into_mut`.
336     ///
337     /// # Title
338     /// ut_usize_index_into_mut
339     ///
340     /// # Brief
341     /// 1. Creates some `usize`s and some `JsonValue`s.
342     /// 2. Calls `Index::index_into_mut`.
343     /// 3. Checks if the test results are correct.
344     #[test]
ut_usize_index_into_mut()345     fn ut_usize_index_into_mut() {
346         let mut value = JsonValue::new_array(array!(1));
347         assert!(0usize.index_into_mut(&mut value).is_number());
348         assert!(1usize.index_into_mut(&mut value).is_null());
349 
350         let mut value = JsonValue::new_null();
351         assert!(0usize.index_into_mut(&mut value).is_null());
352         assert!(value.is_array())
353     }
354 
355     /// UT test for `usize::index_remove`.
356     ///
357     /// # Title
358     /// ut_usize_index_remove
359     ///
360     /// # Brief
361     /// 1. Creates some `usize`s and some `JsonValue`s.
362     /// 2. Calls `Index::index_remove`.
363     /// 3. Checks if the test results are correct.
364     #[test]
ut_usize_index_remove()365     fn ut_usize_index_remove() {
366         let mut value = JsonValue::new_array(array!(1));
367         assert_eq!(
368             0usize.index_remove(&mut value),
369             Some(JsonValue::new_number(1.into()))
370         );
371         assert!(0usize.index_remove(&mut value).is_none());
372     }
373 
374     /// UT test for `str::index_into`.
375     ///
376     /// # Title
377     /// ut_str_index_into
378     ///
379     /// # Brief
380     /// 1. Creates some `str`s and some `JsonValue`s.
381     /// 2. Calls `Index::index_into`.
382     /// 3. Checks if the test results are correct.
383     #[test]
ut_str_index_into()384     fn ut_str_index_into() {
385         let value = JsonValue::new_boolean(true);
386         assert!("key".index_into(&value).is_null());
387     }
388 
389     /// UT test for `str::index_into_mut`.
390     ///
391     /// # Title
392     /// ut_str_index_into_mut
393     ///
394     /// # Brief
395     /// 1. Creates some `str`s and some `JsonValue`s.
396     /// 2. Calls `Index::index_into_mut`.
397     /// 3. Checks if the test results are correct.
398     #[test]
ut_str_index_into_mut()399     fn ut_str_index_into_mut() {
400         let mut value = JsonValue::new_object(object!("key1" => "value1"));
401         assert!("key1".index_into_mut(&mut value).is_string());
402         assert!("key2".index_into_mut(&mut value).is_null());
403 
404         let mut value = JsonValue::new_null();
405         assert!("key1".index_into_mut(&mut value).is_null());
406         assert!(value.is_object())
407     }
408 
409     /// UT test for `str::index_remove`.
410     ///
411     /// # Title
412     /// ut_str_index_remove
413     ///
414     /// # Brief
415     /// 1. Creates some `str`s and some `JsonValue`s.
416     /// 2. Calls `Index::index_remove`.
417     /// 3. Checks if the test results are correct.
418     #[test]
ut_str_index_remove()419     fn ut_str_index_remove() {
420         let mut value = JsonValue::new_object(object!("key1" => "value1"));
421         assert_eq!(
422             "key1".index_remove(&mut value),
423             Some(JsonValue::new_string("value1"))
424         );
425 
426         let mut value = JsonValue::new_null();
427         assert!("key1".index_remove(&mut value).is_none());
428     }
429 
430     /// UT test for `String::index_into`.
431     ///
432     /// # Title
433     /// ut_string_index_into
434     ///
435     /// # Brief
436     /// 1. Creates some `String`s and some `JsonValue`s.
437     /// 2. Calls `Index::index_into`.
438     /// 3. Checks if the test results are correct.
439     #[test]
ut_string_index_into()440     fn ut_string_index_into() {
441         let value = JsonValue::new_boolean(true);
442         assert!(String::from("key").index_into(&value).is_null());
443     }
444 
445     /// UT test for `String::index_into_mut`.
446     ///
447     /// # Title
448     /// ut_string_index_into_mut
449     ///
450     /// # Brief
451     /// 1. Creates some `String`s and some `JsonValue`s.
452     /// 2. Calls `Index::index_into_mut`.
453     /// 3. Checks if the test results are correct.
454     #[test]
ut_string_index_into_mut()455     fn ut_string_index_into_mut() {
456         let mut value = JsonValue::new_object(object!("key1" => "value1"));
457         assert!(String::from("key1").index_into_mut(&mut value).is_string());
458         assert!(String::from("key2").index_into_mut(&mut value).is_null());
459 
460         let mut value = JsonValue::new_null();
461         assert!(String::from("key1").index_into_mut(&mut value).is_null());
462         assert!(value.is_object())
463     }
464 
465     /// UT test for `String::index_remove`.
466     ///
467     /// # Title
468     /// ut_string_index_remove
469     ///
470     /// # Brief
471     /// 1. Creates some `String`s and some `JsonValue`s.
472     /// 2. Calls `Index::index_remove`.
473     /// 3. Checks if the test results are correct.
474     #[test]
ut_string_index_remove()475     fn ut_string_index_remove() {
476         let mut value = JsonValue::new_object(object!("key1" => "value1"));
477         assert_eq!(
478             String::from("key1").index_remove(&mut value),
479             Some(JsonValue::new_string("value1"))
480         );
481         assert!(String::from("key1").index_remove(&mut value).is_none());
482     }
483 }
484