// Copyright (c) 2023 Huawei Device Co., Ltd. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use crate::{Cursor, CursorMut, Iter, IterMut, JsonValue, LinkedList, Node}; use core::fmt::{Debug, Display, Formatter}; use core::ptr::null; /// Object type, implemented using LinkedList. /// /// # Situation /// * When the average number of items under Object is less than 15 (estimated value). /// /// * When the average number of items under Object exceeds 15 (estimated), but do not or rarely made the query operation. /// /// # Attention /// * Only opening the 'list_object' feature, this Object type can be used , and it conflicts with other objects. /// /// * This Object ** does not provide the ** de-duplicate function. /// * Users are required to ensure that there are no duplicate entries. /// /// * The output order of this Object is the same as the insertion order. /// /// # Examples /// ``` /// use ylong_json::Object; /// /// let object = Object::new(); /// ``` #[derive(Default, Clone, PartialEq)] pub struct Object { inner: LinkedList<(String, JsonValue)>, } impl Object { /// Creates an empty Object。 /// /// # Examples /// ``` /// use ylong_json::Object; /// /// let object = Object::new(); /// assert_eq!(object.is_empty(), true); /// ``` pub fn new() -> Self { Self { inner: LinkedList::new(), } } /// Gets the length of Object. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object}; /// /// let mut object = Object::new(); /// assert_eq!(object.len(), 0); /// object.insert(String::from("null"), JsonValue::Null); /// assert_eq!(object.len(), 1); /// ``` pub fn len(&self) -> usize { self.inner.len() } /// Determines whether the Object is empty. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object}; /// /// let mut object = Object::new(); /// assert_eq!(object.is_empty(), true); /// object.insert(String::from("null"), JsonValue::Null); /// assert_eq!(object.is_empty(), false); /// ``` pub fn is_empty(&self) -> bool { self.inner.is_empty() } /// Checks whether the specified key exists in the Object. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object, Number}; /// /// let mut object = Object::new(); /// object.insert(String::from("null"), JsonValue::Null); /// /// assert_eq!(object.contains_key("null"), true); /// assert_eq!(object.contains_key("no_such_key"), false); /// ``` pub fn contains_key(&self, key: &str) -> bool { self.get_cursor(key).is_some() } /// Inserts the specified key and value into an Object, appending them to the end without deduplication. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object}; /// /// let mut object = Object::new(); /// assert_eq!(object.len(), 0); /// object.insert(String::from("null"), JsonValue::Null); /// assert_eq!(object.len(), 1); /// ``` pub fn insert(&mut self, key: String, value: JsonValue) { self.inner.push_back((key, value)) } /// Removes the element under the specified key from the Object.If there is an element with /// the same name in the Object, deletes the one with the smallest subscript. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object, Number}; /// /// let mut object = Object::new(); /// object.insert(String::from("null"), JsonValue::Null); /// assert_eq!(object.len(), 1); /// assert_eq!(object.remove("null"), Some(JsonValue::Null)); /// assert_eq!(object.len(), 0); /// ``` pub fn remove(&mut self, key: &str) -> Option { self.get_cursor_mut(key)?.remove_current().map(|(_, v)| v) } /// Gets a common iterator of Object. /// /// # Examples /// ``` /// use ylong_json::Object; /// /// let object = Object::new(); /// let iter = object.iter(); /// ``` pub fn iter(&self) -> Iter<'_, (String, JsonValue)> { self.inner.iter() } /// Gets a mutable iterator of Object. /// /// # Examples /// ``` /// use ylong_json::Object; /// /// let mut object = Object::new(); /// let iter_mut = object.iter_mut(); /// ``` pub fn iter_mut(&mut self) -> IterMut<'_, (String, JsonValue)> { self.inner.iter_mut() } /// Gets a common reference to the element in Object with the specified key. /// If there is an element with the same name, returns the one with the smallest subscript. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object, Number}; /// /// let mut object = Object::new(); /// object.insert(String::from("test"), JsonValue::Number(Number::from(123))); /// /// assert_eq!(object.get("test"), Some(&JsonValue::Number(Number::from(123)))); /// assert_eq!(object.get("no_such_key"), None); /// ``` pub fn get(&self, key: &str) -> Option<&JsonValue> { self.get_cursor(key)?.current().map(|(_, v)| v) } /// Gets a mutable reference to the element in Object with the specified key. /// If there is an element with the same name, returns the one with the smallest subscript. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object}; /// /// let mut object = Object::new(); /// object.insert(String::from("null"), JsonValue::Null); /// /// assert_eq!(object.get_mut("null"), Some(&mut JsonValue::Null)); /// assert_eq!(object.get_mut("no_such_key"), None); /// ``` pub fn get_mut(&mut self, key: &str) -> Option<&mut JsonValue> { // Using get_cursor_mut causes a problem referencing temporary variables. self.get_node_mut(key).map(|n| &mut n.get_element_mut().1) } /// Gets a common reference to the node in Object with the specified key. /// If there is an element with the same name, returns the one with the smallest subscript. /// /// After getting a common reference to a node, the node cannot be released. Otherwise, undefined behavior occurs. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object}; /// /// let mut object = Object::new(); /// assert_eq!(object.get_node("no_such_key").is_none(), true); /// /// object.insert(String::from("null"), JsonValue::Null); /// assert_eq!(object.get_node("null").is_some(), true); /// ``` pub fn get_node(&self, key: &str) -> Option<&Node<(String, JsonValue)>> { self.get_cursor(key)?.current_node() } /// Gets a mutable reference to the node in Object with the specified key. /// If there is an element with the same name, returns the one with the smallest subscript. /// /// After getting a mutable reference to a node, the node cannot be released. Otherwise, undefined behavior occurs. /// /// # Examples /// ``` /// use ylong_json::{JsonValue, Object}; /// /// let mut object = Object::new(); /// assert_eq!(object.get_node_mut("no_such_key").is_none(), true); /// /// object.insert(String::from("null"), JsonValue::Null); /// assert_eq!(object.get_node_mut("null").is_some(), true); /// ``` pub fn get_node_mut(&mut self, key: &str) -> Option<&mut Node<(String, JsonValue)>> { self.get_cursor_mut(key)?.current_node() } /// Gets the last node. #[cfg(feature = "c_adapter")] pub(crate) fn last_node_mut(&mut self) -> Option<&mut Node<(String, JsonValue)>> { let mut cursor = self.inner.cursor_back_mut(); let _ = cursor.index()?; cursor.current_node() } /// Needs using this method to avoid the life cycle check, which involves unsafe operations. pub(crate) fn get_key_mut_maybe_insert(&mut self, key: &str) -> &mut JsonValue { let mut cursor = self.inner.cursor_front(); let mut ptr = null(); while cursor.index().is_some() { let current = cursor.current().unwrap(); if current.0 == key { ptr = cursor.current_node_ptr(); break; } cursor.move_next(); } if ptr.is_null() { self.insert(String::from(key), JsonValue::Null); &mut self.inner.back_mut().unwrap().1 } else { unsafe { &mut (*(ptr as *mut Node<(String, JsonValue)>)) .get_element_mut() .1 } } } /// Gets the common cursor of the node corresponding to the specified key. fn get_cursor(&self, key: &str) -> Option> { let mut cursor = self.inner.cursor_front(); while cursor.index().is_some() { let (k, _) = cursor.current().unwrap(); if key == k { return Some(cursor); } cursor.move_next(); } None } /// Gets the mutable cursor of the node corresponding to the specified key. fn get_cursor_mut(&mut self, key: &str) -> Option> { let mut cursor = self.inner.cursor_front_mut(); while cursor.index().is_some() { let (k, _) = cursor.current().unwrap(); if key == k { return Some(cursor); } cursor.move_next(); } None } } impl Display for Object { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { write!(f, "{{")?; for (n, (key, value)) in self.inner.iter().enumerate() { if n != 0 { write!(f, ",")?; } write!(f, "\"{key}\":{value}")?; } write!(f, "}}") } } impl Debug for Object { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Display::fmt(self, f) } } #[cfg(test)] mod ut_linked_list { use crate::{JsonValue, Object}; /// UT test for `Object::contains_key`. /// /// # Title /// ut_object_contains_key /// /// # Brief /// 1. Creates a `Object`. /// 2. Calls `Object::contains_key` on it. /// 3. Checks if the test results are correct. #[test] fn ut_object_contains_key() { let object = object!("key1" => "value1"); assert!(object.contains_key("key1")); assert!(!object.contains_key("key2")); } /// UT test for `Object::iter_mut`. /// /// # Title /// ut_object_iter_mut /// /// # Brief /// 1. Creates a `Object`. /// 2. Calls `Object::iter_mut` on it. /// 3. Checks if the test results are correct. #[test] fn ut_object_iter_mut() { let mut object = object!("key1" => "value1"); let mut iter_mut = object.iter_mut(); assert_eq!( iter_mut.next(), Some(&mut (String::from("key1"), JsonValue::new_string("value1"))) ); assert_eq!(iter_mut.next(), None); } /// UT test for `Object::get_mut`. /// /// # Title /// ut_object_get_mut /// /// # Brief /// 1. Creates a `Object`. /// 2. Calls `Object::get_mut` on it. /// 3. Checks if the test results are correct. #[test] fn ut_object_get_mut() { let mut object = object!("key1" => "value1"); assert_eq!( object.get_mut("key1"), Some(&mut JsonValue::new_string("value1")) ); assert_eq!(object.get_mut("key2"), None); } /// UT test for `Object::get_node`. /// /// # Title /// ut_object_get_node /// /// # Brief /// 1. Creates a `Object`. /// 2. Calls `Object::get_node` on it. /// 3. Checks if the test results are correct. #[test] fn ut_object_get_node() { let object = object!("key1" => "value1"); assert!(object.get_node("key1").is_some()); assert!(object.get_node("key2").is_none()); } /// UT test for `Object::get_node_mut`. /// /// # Title /// ut_object_get_node_mut /// /// # Brief /// 1. Creates a `Object`. /// 2. Calls `Object::get_node_mut` on it. /// 3. Checks if the test results are correct. #[test] fn ut_object_get_node_mut() { let mut object = object!("key1" => "value1"); assert!(object.get_node_mut("key1").is_some()); assert!(object.get_node_mut("key2").is_none()); } /// UT test for `Object::fmt`. /// /// # Title /// ut_object_fmt /// /// # Brief /// 1. Creates a `Object`. /// 2. Calls `Object::fmt` on it. /// 3. Checks if the test results are correct. #[test] fn ut_object_fmt() { let object = object!("key1" => "value1"; "key2" => "value2"); assert_eq!( format!("{object}"), "{\"key1\":\"value1\",\"key2\":\"value2\"}" ); assert_eq!( format!("{object:?}"), "{\"key1\":\"value1\",\"key2\":\"value2\"}" ); } }