// 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}; /// Array type, implemented using LinkedList. /// /// # Situation /// * When the average number of Array entries does not exceed 15 (estimated value). /// /// * When the average number of Array entries exceeds 15 (estimated value), but do not or rarely made query operation. /// /// # Attention /// * Only open `list_array` feature can be used, and conflicts with other array-related features. /// /// # Examples /// ``` /// use ylong_json::Array; /// /// let array = Array::new(); /// ``` #[derive(Default, Clone, PartialEq)] pub struct Array { inner: LinkedList, } impl Array { /// Creates an empty Array instance. /// /// # Examples /// ``` /// use ylong_json::Array; /// /// let array = Array::new(); /// ``` pub fn new() -> Self { Self { inner: LinkedList::new(), } } /// Gets length of Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.len(), 0); /// /// array.push(JsonValue::Null); /// assert_eq!(array.len(), 1); /// ``` pub fn len(&self) -> usize { self.inner.len() } /// Determines whether Array is empty. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.is_empty(), true); /// /// array.push(JsonValue::Null); /// assert_eq!(array.is_empty(), false); /// ``` pub fn is_empty(&self) -> bool { self.inner.is_empty() } /// Insert a new JsonValue at the end of Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.len(), 0); /// /// array.push(JsonValue::Null); /// assert_eq!(array.len(), 1); /// ``` pub fn push(&mut self, value: JsonValue) { self.inner.push_back(value); } /// Pops the element at the end of Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.pop(), None); /// /// array.push(JsonValue::Null); /// assert_eq!(array.pop(), Some(JsonValue::Null)); /// ``` pub fn pop(&mut self) -> Option { self.inner.pop_back() } /// Gets a common iterator of Array. /// /// # Examples /// ``` /// use ylong_json::Array; /// /// let array = Array::new(); /// let iter = array.iter(); /// ``` pub fn iter(&self) -> Iter<'_, JsonValue> { self.inner.iter() } /// Gets a mutable iterator of Array. /// /// # Examples /// ``` /// use ylong_json::Array; /// /// let mut array = Array::new(); /// let iter_mut = array.iter_mut(); /// ``` pub fn iter_mut(&mut self) -> IterMut<'_, JsonValue> { self.inner.iter_mut() } /// Returns a common reference to the specified index ** member ** in Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// array.push(JsonValue::Null); /// assert_eq!(array.get(0), Some(&JsonValue::Null)); /// assert_eq!(array.get(1), None); /// ``` pub fn get(&self, index: usize) -> Option<&JsonValue> { self.get_cursor(index)?.current() } /// Returns a mutable reference to the specified index ** member ** in Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// array.push(JsonValue::Null); /// assert_eq!(array.get_mut(0), Some(&mut JsonValue::Null)); /// assert_eq!(array.get_mut(1), None); /// ``` pub fn get_mut(&mut self, index: usize) -> Option<&mut JsonValue> { // Using 'get_cursor_mut' causes a problem referencing temporary variables. self.get_node_mut(index).map(|n| n.get_element_mut()) } /// Returns a common reference to the trailing ** member ** in Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.last(), None); /// array.push(JsonValue::Null); /// assert_eq!(array.last(), Some(&JsonValue::Null)); /// ``` pub fn last(&self) -> Option<&JsonValue> { self.inner.back() } /// Returns a mutable reference to the trailing ** member ** in Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.last_mut(), None); /// array.push(JsonValue::Null); /// assert_eq!(array.last_mut(), Some(&mut JsonValue::Null)); /// ``` pub fn last_mut(&mut self) -> Option<&mut JsonValue> { self.inner.back_mut() } /// Removes the node in Array with the specified index. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// array.push(JsonValue::Null); /// array.push(JsonValue::Boolean(true)); /// array.push(JsonValue::Null); /// /// assert_eq!(array.len(), 3); /// let second = array.remove(1); /// assert_eq!(second, Some(JsonValue::Boolean(true))); /// assert_eq!(array.len(), 2); /// ``` pub fn remove(&mut self, index: usize) -> Option { self.get_cursor_mut(index)?.remove_current() } /// Returns a common reference to the specified index ** node ** in Array. /// /// After getting a common reference to a node, the corresponding node cannot be released. /// Otherwise undefined behavior will occur. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// array.push(JsonValue::Null); /// assert_eq!(array.get_node(0).is_some(), true); /// assert_eq!(array.get_node(1).is_none(), true); /// ``` pub fn get_node(&self, index: usize) -> Option<&Node> { self.get_cursor(index)?.current_node() } /// Returns a mutable reference to the specified index ** node ** in Array. /// /// After getting a mutable reference to a node, the corresponding node cannot be released. /// Otherwise undefined behavior will occur. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// let value = JsonValue::Null; /// array.push(value); /// assert_eq!(array.get_node_mut(0).is_some(), true); /// assert_eq!(array.get_node_mut(1).is_none(), true); /// ``` pub fn get_node_mut(&mut self, index: usize) -> Option<&mut Node> { self.get_cursor_mut(index)?.current_node() } /// Returns a common reference to the trailing ** node ** in Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.last_node().is_none(), true); /// array.push(JsonValue::Null); /// assert_eq!(array.last_node().is_some(), true); /// ``` pub fn last_node(&self) -> Option<&Node> { self.inner.back_node() } /// Returns a mutable reference to the trailing ** node ** in Array. /// /// # Examples /// ``` /// use ylong_json::{Array, JsonValue}; /// /// let mut array = Array::new(); /// assert_eq!(array.last_node_mut().is_none(), true); /// array.push(JsonValue::Null); /// assert_eq!(array.last_node_mut().is_some(), true); /// ``` pub fn last_node_mut(&mut self) -> Option<&mut Node> { self.inner.back_node_mut() } /// Gets the common cursor of the specified index node. fn get_cursor(&self, index: usize) -> Option> { let len = self.len(); // If index is greater than the array length, returns. // If index is less than half the array length, searches from front to back; // If index is greater than half the array length, searches from the back to the front. return if index >= len { None } else if index >= (len - 1) / 2 { let mut steps = len - 1 - index; let mut cursor = self.inner.cursor_back(); while steps != 0 { let _ = cursor.index()?; cursor.move_prev(); steps -= 1; } Some(cursor) } else { let mut steps = index; let mut cursor = self.inner.cursor_front(); while steps != 0 { let _ = cursor.index()?; cursor.move_next(); steps -= 1; } Some(cursor) }; } /// Gets the mutable cursor of the specified index node. fn get_cursor_mut(&mut self, index: usize) -> Option> { let len = self.len(); // If index is greater than the array length, returns. // If index is less than half the array length, searches from front to back; // If index is greater than half the array length, searches from the back to the front. return if index >= len { None } else if index >= (len - 1) / 2 { let mut steps = len - 1 - index; let mut cursor = self.inner.cursor_back_mut(); while steps != 0 { let _ = cursor.index()?; cursor.move_prev(); steps -= 1; } Some(cursor) } else { let mut steps = index; let mut cursor = self.inner.cursor_front_mut(); while steps != 0 { let _ = cursor.index()?; cursor.move_next(); steps -= 1; } Some(cursor) }; } } impl Display for Array { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { write!(f, "[")?; for (n, item) in self.inner.iter().enumerate() { if n != 0 { write!(f, ",")?; } write!(f, "{item}")?; } write!(f, "]") } } impl Debug for Array { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { Display::fmt(self, f) } } #[cfg(test)] mod ut_linked_list { use crate::{Array, JsonValue}; /// UT test for `Array::is_empty`. /// /// # Title /// ut_array_is_empty /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::is_empty`. /// 3. Checks if the test results are correct. #[test] fn ut_array_is_empty() { assert!(Array::new().is_empty()); assert!(!array!(1).is_empty()); } /// UT test for `Array::pop`. /// /// # Title /// ut_array_pop /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::pop`. /// 3. Checks if the test results are correct. #[test] fn ut_array_pop() { let mut array = array!(1); assert_eq!(array.pop(), Some(JsonValue::new_number(1.into()))); assert_eq!(array.pop(), None); } /// UT test for `Array::iter_mut`. /// /// # Title /// ut_array_iter_mut /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::iter_mut`. /// 3. Checks if the test results are correct. #[test] fn ut_array_iter_mut() { let mut array = array!(1); let mut iter = array.iter_mut(); assert_eq!(iter.next(), Some(&mut JsonValue::new_number(1.into()))); assert_eq!(iter.next(), None); } /// UT test for `Array::last`. /// /// # Title /// ut_array_last /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::last`. /// 3. Checks if the test results are correct. #[test] fn ut_array_last() { let array = array!(1); assert_eq!(array.last(), Some(&JsonValue::new_number(1.into()))); let array = Array::new(); assert_eq!(array.last(), None); } /// UT test for `Array::get_node`. /// /// # Title /// ut_array_get_node /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::get_node`. /// 3. Checks if the test results are correct. #[test] fn ut_array_get_node() { let array = array!(1, 2, 3, 4, 5, 6); assert!(array.get_node(0).is_some()); assert!(array.get_node(1).is_some()); assert!(array.get_node(2).is_some()); assert!(array.get_node(3).is_some()); assert!(array.get_node(4).is_some()); assert!(array.get_node(5).is_some()); assert!(array.get_node(6).is_none()); } /// UT test for `Array::get_node_mut`. /// /// # Title /// ut_array_get_node_mut /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::get_node_mut`. /// 3. Checks if the test results are correct. #[test] fn ut_array_get_node_mut() { let mut array = array!(1, 2, 3, 4, 5, 6); assert!(array.get_node_mut(0).is_some()); assert!(array.get_node_mut(1).is_some()); assert!(array.get_node_mut(2).is_some()); assert!(array.get_node_mut(3).is_some()); assert!(array.get_node_mut(4).is_some()); assert!(array.get_node_mut(5).is_some()); assert!(array.get_node_mut(6).is_none()); } /// UT test for `Array::last_node`. /// /// # Title /// ut_array_last_node /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::last_node`. /// 3. Checks if the test results are correct. #[test] fn ut_array_last_node() { let array = array!(1); assert!(array.last_node().is_some()); let array = Array::new(); assert!(array.last_node().is_none()); } /// UT test for `Array::last_node_mut`. /// /// # Title /// ut_array_last_node_mut /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::last_node_mut`. /// 3. Checks if the test results are correct. #[test] fn ut_array_last_node_mut() { let mut array = array!(1); assert!(array.last_node_mut().is_some()); let mut array = Array::new(); assert!(array.last_node_mut().is_none()); } /// UT test for `Array::fmt`. /// /// # Title /// ut_array_fmt /// /// # Brief /// 1. Creates some `Array`s. /// 2. Calls `Array::fmt`. /// 3. Checks if the test results are correct. #[test] fn ut_array_fmt() { let array = array!(1, 2); assert_eq!(format!("{array}"), "[1,2]"); assert_eq!(format!("{array:?}"), "[1,2]"); } }