devela/data/list/array/d1/methods/general.rs
1// devela::data::list::array::d1::methods::general
2//
3//! 1-dimensional array general methods (Storage-independent).
4//
5// TOC
6// - constructors
7// - methods
8// - T: PartialEq methods
9// - Option<T> methods
10
11use crate::{
12 array_from_fn, iif, Array, ElementNotFound, IndexOutOfBounds, MismatchedBounds, Storage,
13};
14
15/// # Constructors
16impl<T, const CAP: usize, S: Storage> Array<T, CAP, S> {
17 /// Returns a new `Array` from the given primitive `array`.
18 pub fn new(array: [T; CAP]) -> Self {
19 Self { data: array.into() }
20 }
21
22 /// Returns a new `Array`, where each element `T` is the returned value from `f`.
23 ///
24 /// See: `array::`[`from_fn`][core::array::from_fn]
25 pub fn from_fn<F: FnMut(usize) -> T>(f: F) -> Self {
26 Self { data: array_from_fn(f).into() }
27 }
28 // WAIT [array_try_from_fn](https://github.com/rust-lang/rust/issues/89379)
29}
30
31/// # Methods
32impl<T, const CAP: usize, S: Storage> Array<T, CAP, S> {
33 /// Returns the total capacity of the array, equals `CAP`.
34 #[must_use]
35 pub const fn capacity(&self) -> usize {
36 CAP
37 }
38
39 /// Returns a shared slice containing the entire array.
40 #[must_use]
41 pub fn as_slice(&self) -> &[T] {
42 self.data.as_slice()
43 }
44
45 /// Returns an exclusive slice containing the entire array.
46 #[must_use]
47 pub fn as_mut_slice(&mut self) -> &mut [T] {
48 self.data.as_mut_slice()
49 }
50
51 /// Fills all elements of the array with the given `element`.
52 pub fn fill(&mut self, element: T)
53 where
54 T: Clone,
55 {
56 self.iter_mut().for_each(|i| *i = element.clone());
57 }
58
59 /// Fills all elements of the array with the default value.
60 pub fn fill_default(&mut self)
61 where
62 T: Default,
63 {
64 self.iter_mut().for_each(|i| *i = T::default());
65 }
66}
67
68/// # `T: PartialEq` methods
69impl<T: PartialEq, const CAP: usize, S: Storage> Array<T, CAP, S> {
70 /// Returns `true` if the array contains `element`.
71 ///
72 /// # Example
73 /// ```
74 /// # use devela::Array;
75 /// let a = Array::<_, 5>::new([5, 78, 42, 33, 9]);
76 /// assert![a.contains(&9)];
77 /// assert![!a.contains(&8)];
78 /// ```
79 #[must_use]
80 pub fn contains(&self, element: &T) -> bool {
81 self.iter().any(|n| n == element)
82 }
83
84 /// Returns `true` if the array contains `element`,
85 /// from the `start` index (inclusive).
86 ///
87 /// # Errors
88 /// Returns [`IndexOutOfBounds`] if `start >= CAP`.
89 pub fn contains_from(&self, element: &T, start: usize) -> Result<bool, IndexOutOfBounds> {
90 iif![start >= CAP; return Err(IndexOutOfBounds(Some(start)))];
91 Ok(self.iter().skip(start).any(|n| n == element))
92 }
93
94 /// Returns `true` if the array contains `element`,
95 /// from the `start` index (inclusive).
96 ///
97 /// # Errors
98 /// Returns [`IndexOutOfBounds`] if `end >= CAP`.
99 pub fn contains_until(&self, element: &T, end: usize) -> Result<bool, IndexOutOfBounds> {
100 iif![end >= CAP; return Err(IndexOutOfBounds(Some(end)))];
101 Ok(self.iter().take(end + 1).any(|n| n == element))
102 }
103
104 /// Returns `true` if the array contains `element`,
105 /// between the range `start..=end` (inclusive).
106 ///
107 /// # Errors
108 /// Returns [`MismatchedBounds::IndexOutOfBounds`] if either `start` or `end` `>= CAP`,
109 /// or [`MismatchedBounds::MismatchedIndices`] if `start > end`.
110 pub fn contains_between(
111 &self,
112 element: &T,
113 start: usize,
114 end: usize,
115 ) -> Result<bool, MismatchedBounds> {
116 iif![start >= CAP; return Err(MismatchedBounds::IndexOutOfBounds(Some(start)))];
117 iif![end >= CAP; return Err(MismatchedBounds::IndexOutOfBounds(Some(end)))];
118 iif![start > end; return Err(MismatchedBounds::MismatchedIndices)];
119 Ok(self.iter().skip(start).take(end - start + 1).any(|n| n == element))
120 }
121
122 /// Finds the index of the first occurrence of `element` in the array.
123 ///
124 /// # Example
125 /// ```
126 /// # use devela::{Array, ElementNotFound};
127 /// let a = Array::<_, 5>::new([5, 78, 42, 33, 9]);
128 /// assert_eq![a.find_index(&9), Ok(4)];
129 /// assert_eq![a.find_index(&8), Err(ElementNotFound)];
130 /// ```
131 /// # Errors
132 /// Returns [`ElementNotFound`] if the `element` can't be found.
133 pub fn find_index(&self, element: &T) -> Result<usize, ElementNotFound> {
134 self.iter()
135 .enumerate()
136 .find_map(|(i, n)| (n == element).then_some(i))
137 .ok_or(ElementNotFound)
138 }
139}
140
141/// # `Option<T>` methods
142impl<T, const CAP: usize, S: Storage> Array<Option<T>, CAP, S> {
143 /// Takes out some element at `index`, leaving `None` in its place.
144 #[must_use]
145 pub fn take(&mut self, index: usize) -> Option<T> {
146 self.get_mut(index)?.take()
147 }
148
149 /// Replaces some element at `index` with `value`, returning the old one.
150 #[must_use]
151 pub fn replace(&mut self, index: usize, value: T) -> Option<T> {
152 self.get_mut(index)?.replace(value)
153 }
154
155 /// Sets the element at `index` to `None`.
156 pub fn unset(&mut self, index: usize) {
157 self[index] = None;
158 }
159
160 /// Clears the array by setting all elements to `None`.
161 pub fn clear(&mut self) {
162 self.iter_mut().for_each(|i| *i = None);
163 }
164
165 /// Returns the number of `Some` elements in the array.
166 #[must_use]
167 pub fn count_some(&self) -> usize {
168 self.iter().filter(|opt| opt.is_some()).count()
169 }
170 /// Returns the number of `None` elements in the array.
171 #[must_use]
172 pub fn count_none(&self) -> usize {
173 self.iter().filter(|opt| opt.is_none()).count()
174 }
175
176 /// Returns the number of `None` elements in the array.
177 #[must_use]
178 pub fn is_empty(&self) -> bool {
179 self.iter().all(|opt| opt.is_some())
180 }
181
182 /// Returns the number of `None` elements in the array.
183 #[must_use]
184 pub fn is_full(&self) -> bool {
185 self.iter().all(|opt| opt.is_some())
186 }
187
188 /// Fills all `None` elements of the array with the given cloned `value`.
189 pub fn fill_none(&mut self, value: T)
190 where
191 T: Clone,
192 {
193 self.iter_mut().filter(|opt| opt.is_none()).for_each(|opt| *opt = Some(value.clone()));
194 }
195
196 /// Returns the index of the first `None` element.
197 ///
198 /// # Errors
199 /// Returns [`ElementNotFound`] if the array is full.
200 pub fn first_none(&self) -> Result<usize, ElementNotFound> {
201 self.iter().position(|opt| opt.is_none()).ok_or(ElementNotFound)
202 }
203 /// Returns some reference to the first `None` element.
204 ///
205 /// # Errors
206 /// Returns [`ElementNotFound`] if the array is full.
207 pub fn first_none_ref(&self) -> Result<&Option<T>, ElementNotFound> {
208 self.iter().find(|opt| opt.is_none()).ok_or(ElementNotFound)
209 }
210 /// Returns some exclusive reference to the first `None` element.
211 ///
212 /// # Errors
213 /// Returns [`ElementNotFound`] if the array is full.
214 pub fn first_none_mut(&mut self) -> Result<&mut Option<T>, ElementNotFound> {
215 self.iter_mut().find(|opt| opt.is_none()).ok_or(ElementNotFound)
216 }
217
218 /// Returns the index of the first `Some` element.
219 ///
220 /// # Errors
221 /// Returns [`ElementNotFound`] if the array is full.
222 pub fn first_some(&self) -> Result<usize, ElementNotFound> {
223 self.iter().position(|opt| opt.is_some()).ok_or(ElementNotFound)
224 }
225 /// Returns some reference to the first `Some` element
226 ///
227 /// # Errors
228 /// Returns [`ElementNotFound`] if the array is full.
229 pub fn first_some_ref(&self) -> Result<&Option<T>, ElementNotFound> {
230 self.iter().find(|opt| opt.is_some()).ok_or(ElementNotFound)
231 }
232 /// Returns some exclusive reference to the first `Some` element.
233 ///
234 /// # Errors
235 /// Returns [`ElementNotFound`] if the array is full.
236 pub fn first_some_mut(&mut self) -> Result<&mut Option<T>, ElementNotFound> {
237 self.iter_mut().find(|opt| opt.is_some()).ok_or(ElementNotFound)
238 }
239}