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
14use crate::{Array, JsonValue, Object};
15
16/// Static NULL, which is returned if the searched key-value pair does not exist.
17static 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.
20pub trait Index: private::IndexSealed {
21    /// Gets a common reference to the value with the specified subscript (or key) from a JsonValue.
22    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.
25    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.
28    fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue>;
29}
30
31impl 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    /// ```
62    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    /// ```
107    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    /// ```
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
146impl 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    /// ```
173    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    /// ```
216    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    /// ```
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
266impl Index for String {
267    /// Same as 'Index for str'.
268    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'.
273    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'.
278    fn index_remove(&self, value: &mut JsonValue) -> Option<JsonValue> {
279        self.as_str().index_remove(value)
280    }
281}
282
283impl<'a, T> Index for &'a T
284where
285    T: ?Sized + Index,
286{
287    /// Implements Index for the relevant reference type.
288    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.
293    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.
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.
304mod 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)]
317mod 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]
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]
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]
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]
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]
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]
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]
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]
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]
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