devela/data/list/array/d2/methods/general.rs
1// devela::data::list::array::d2::methods::general
2//
3//! 2-dimensional array general methods.
4//
5
6#[cfg(doc)]
7use crate::BareBox;
8use crate::{
9 Array, Array2d, Bare, Mismatch,
10 MismatchedBounds::{self, IndexOutOfBounds, MismatchedCapacity},
11 Storage,
12};
13#[cfg(feature = "alloc")]
14use crate::{Box, Boxed, Vec};
15
16/* constructors */
17
18// T: Clone, S: Bare
19impl<T: Clone, const C: usize, const R: usize, const CR: usize, const RMAJ: bool>
20 Array2d<T, C, R, CR, RMAJ, Bare>
21{
22 /// Returns a 2-dimensional grid, allocated in the stack,
23 /// using `element` to fill the remaining free data.
24 /// # Errors
25 /// Returns [`IndexOutOfBounds`] if `C * R > usize::MAX`
26 /// or [`MismatchedCapacity`] if `C * R != CR`.
27 /// # Examples
28 /// ```
29 /// # use devela::Array2d;
30 /// let g = Array2d::<_, 4, 4, {4 * 4}>::with_cloned('.');
31 /// ```
32 pub fn with_cloned(element: T) -> Result<Self, MismatchedBounds> {
33 Self::check_CR()?;
34 Ok(Self { data: Array::<T, CR, Bare>::with_cloned(element) })
35 }
36}
37// T: Copy, S: Bare
38impl<T: Copy, const C: usize, const R: usize, const CR: usize, const RMAJ: bool>
39 Array2d<T, C, R, CR, RMAJ, Bare>
40{
41 /// Returns a 2-dimensional grid, allocated in the stack,
42 /// using `element` to fill the remaining free data.
43 /// # Errors
44 /// Returns [`IndexOutOfBounds`] if `C * R > usize::MAX`
45 /// or [`MismatchedCapacity`] if `C * R != CR`.
46 /// # Examples
47 /// ```
48 /// # use devela::{Array2d, MismatchedBounds};
49 /// const GRID: Result<Array2d::<char, 4, 4, {4 * 4}>, MismatchedBounds>
50 /// = Array2d::with_copied('.');
51 /// assert![GRID.is_ok()];
52 /// ```
53 pub const fn with_copied(element: T) -> Result<Self, MismatchedBounds> {
54 match Self::check_CR() {
55 Ok(()) => Ok(Self { data: Array::<T, CR, Bare>::with_copied(element) }),
56 Err(e) => Err(e),
57 }
58 }
59}
60
61// T: Clone, S: Boxed
62#[cfg(feature = "alloc")]
63#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
64impl<T: Clone, const C: usize, const R: usize, const CR: usize, const RMAJ: bool>
65 Array2d<T, C, R, CR, RMAJ, Boxed>
66{
67 /// Returns a 2-dimensional grid, allocated in the heap,
68 /// using `element` to fill the remaining free data.
69 /// # Errors
70 /// Returns [`IndexOutOfBounds`] if `C * R > usize::MAX`
71 /// or [`MismatchedCapacity`] if `C * R != CR`.
72 /// # Examples
73 /// ```
74 /// # use devela::{Boxed, Array2d};
75 /// let g = Array2d::<_, 4, 4, {4 * 4}, true, Boxed>::with_cloned(String::from("·"));
76 /// ```
77 pub fn with_cloned(element: T) -> Result<Self, MismatchedBounds> {
78 Self::check_CR()?;
79 Ok(Self { data: Array::<T, CR, Boxed>::with_cloned(element) })
80 }
81}
82
83// Order-independent
84// T, S
85#[rustfmt::skip]
86impl<T, const C: usize, const R: usize, const CR: usize, const RMAJ: bool, S: Storage>
87 Array2d<T, C, R, CR, RMAJ, S>
88{
89 /* general queries */
90
91 /// Returns the total capacity of the array, equals `CR == C * R`.
92 #[must_use] pub const fn capacity(&self) -> usize { CR }
93
94 /// Returns the capacity of a column, equivalent to [`num_rows`][Self::num_rows] == `R`.
95 #[must_use] pub const fn cap_col(&self) -> usize { R }
96
97 /// Returns the capacity of a row, equivalent to [`num_cols`][Self::num_cols] == `C`.
98 #[must_use] pub const fn cap_row(&self) -> usize { C }
99
100 /// Returns the number of columns, equivalent to [`cap_row`][Self::cap_row] == `C`.
101 #[must_use] pub const fn num_cols(&self) -> usize { C }
102
103 /// Returns the number of rows, equivalent to [`cap_col`][Self::cap_col] == `R`.
104 #[must_use] pub const fn num_rows(&self) -> usize { R }
105
106 /// Checks the geometry of the columns, rows and their product length.
107 /// # Errors
108 /// Returns [`IndexOutOfBounds`] if `C * R > usize::MAX`
109 /// or [`MismatchedCapacity`] if `C * R != CR`.
110 #[allow(non_snake_case)]
111 pub(crate) const fn check_CR() -> Result<(), MismatchedBounds> {
112 if let Some(len) = C.checked_mul(R) {
113 if len == CR { Ok(()) } else {
114 Err(MismatchedCapacity(Mismatch::in_closed_interval(CR, CR, len, "C * R != CR")))
115 }
116 } else { Err(IndexOutOfBounds(None)) } // RETHINK: return some value
117 }
118
119 /// Checks the geometry of the columns, rows and their product length.
120 /// # Panics
121 /// Panics if `C * R > usize::MAX` or if `C * R != CR`.
122 #[allow(non_snake_case)]
123 pub(crate) const fn panic_check_CR() {
124 if let Some(len) = C.checked_mul(R) {
125 if len != CR {
126 panic![concat![ "Array2d Mismatch: C * R != CR: ",
127 stringify!(C), " * ", stringify!(R), " != ", stringify!(CR) ]];
128 }
129 } else {
130 panic![concat![ "Array2d overflow: C * R (",
131 stringify!(R), " * ", stringify!(C), " > usize::MAX)" ]];
132 }
133 }
134
135 /* slices */
136
137 /// Returns a slice containing the full grid.
138 // /// # Examples
139 // /// ```
140 // /// # use devela::Array2d;
141 // /// let g = Array2d::from([1, 2, 3]);
142 // /// assert_eq![s.as_slice(), &[1, 2, 3]];
143 // /// ```
144 #[must_use]
145 pub fn as_slice(&self) -> &[T] { self.data.as_slice() }
146
147 /// Returns the stack as an exclusive slice.
148 // /// # Examples
149 // /// ```
150 // /// # use devela::Array2d;
151 // /// let mut g = Array2d::<_, (), 2, 2, 4>::from([1, 2, 3]);
152 // /// assert_eq![s.as_mut_slice(), &mut [1, 2, 3]];
153 // /// ```
154 #[must_use]
155 pub fn as_mut_slice(&mut self) -> &mut [T] { self.data.as_mut_slice() }
156}
157
158/* Order-dependent */
159
160#[rustfmt::skip]
161impl<T, const C: usize, const R: usize, const CR: usize, S: Storage> Array2d<T, C, R, CR, true, S> {
162 /// Returns the capacity per item in the major dimension based on layout (`RMAJ`).
163 /// For row-major, this is the number of columns. For column-major, this is the number of rows.
164 #[must_use] pub const fn cap_major(&self) -> usize { C }
165
166 /// Returns the capacity per item in the minor dimension based on layout (`RMAJ`).
167 /// For row-major, this is the number of rows. For column-major, this is the number of columns.
168 #[must_use] pub const fn cap_minor(&self) -> usize { R }
169
170 /// Returns the number of items in the major dimension based on layout (`RMAJ`).
171 /// For row-major, this is the number of rows. For column-major, this is the number of columns.
172 #[must_use] pub const fn num_major(&self) -> usize { R }
173
174 /// Returns the number of items in the minor dimension based on layout (`RMAJ`).
175 /// For row-major, this is the number of columns. For column-major, this is the number of rows.
176 #[must_use] pub const fn num_minor(&self) -> usize { C }
177}
178
179#[rustfmt::skip]
180impl<T, const C: usize, const R: usize, const CR: usize, S: Storage> Array2d<T, C, R, CR, false, S> {
181 /// Returns the capacity per item in the major dimension based on layout (`RMAJ`).
182 /// For row-major, this is the number of columns. For column-major, this is the number of rows.
183 #[must_use] pub const fn cap_major(&self) -> usize { R }
184
185 /// Returns the capacity per item in the minor dimension based on layout (`RMAJ`).
186 /// For row-major, this is the number of rows. For column-major, this is the number of columns.
187 #[must_use] pub const fn cap_minor(&self) -> usize { C }
188
189 /// Returns the number of items in the major dimension based on layout (`RMAJ`).
190 /// For row-major, this is the number of rows. For column-major, this is the number of columns.
191 #[must_use] pub const fn num_major(&self) -> usize { C }
192
193 /// Returns the number of items in the minor dimension based on layout (`RMAJ`).
194 /// For row-major, this is the number of columns. For column-major, this is the number of rows.
195 #[must_use] pub const fn num_minor(&self) -> usize { R }
196}
197
198// T, S: Bare
199#[rustfmt::skip]
200impl<T, const C: usize, const R: usize, const CR: usize, const RMAJ: bool>
201 Array2d<T, C, R, CR, RMAJ, Bare>
202{
203 /// Returns the inner [`BareBox`]ed primitive array.
204 #[must_use]
205 pub fn into_array(self) -> [T; CR] { self.data.into_array() }
206}
207
208// T: Copy, S: Bare
209#[rustfmt::skip]
210impl<T: Copy, const C: usize, const R: usize, const CR: usize, const RMAJ: bool>
211 Array2d<T, C, R, CR, RMAJ, Bare>
212{
213 /// Returns the inner [`BareBox`]ed primitive array in compile-time.
214 #[must_use]
215 pub const fn into_array_copy(self) -> [T; CR] { self.data.into_array_copy() }
216}
217
218// T, S: Boxed
219#[rustfmt::skip]
220#[cfg(feature = "alloc")]
221#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
222impl<T, const C: usize, const R: usize, const CR: usize, const RMAJ: bool>
223 Array2d<T, C, R, CR, RMAJ, Boxed>
224{
225 /// Returns the inner [`Box`]ed primitive array.
226 #[must_use]
227 pub fn into_array(self) -> Box<[T; CR]> { self.data.into_array() }
228
229 /// Returns the inner [`Box`]ed primitive array as a slice.
230 #[must_use]
231 pub fn into_slice(self) -> Box<[T]> { self.data.into_slice() }
232
233 /// Returns the inner [`Box`]ed primitive array as a `Vec`.
234 #[must_use]
235 pub fn into_vec(self) -> Vec<T> { self.data.into_vec() }
236}
237
238// T: Clone, S
239#[rustfmt::skip]
240impl<T: Clone, const C: usize, const R: usize, const CR: usize, const RMAJ: bool, S: Storage>
241 Array2d<T, C, R, CR, RMAJ, S>
242{
243 /// Fills all elements of the grid with the given `element`.
244 pub fn fill(&mut self, element: T) { self.data.fill(element) }
245}
246
247// T: PartialEq, S
248impl<
249 T: PartialEq,
250 const C: usize,
251 const R: usize,
252 const CR: usize,
253 const RMAJ: bool,
254 S: Storage,
255 > Array2d<T, C, R, CR, RMAJ, S>
256{
257 /// Returns true if the array contains `element`.
258 /// # Examples
259 // /// ```
260 // /// # use devela::Array2d;
261 // /// let a = Array2d::<_, 5, 5, 25>::new([5, 78, 42, 33, 9]);
262 // /// assert![a.contains(&9)];
263 // /// assert![!a.contains(&8)];
264 // /// ```
265 #[must_use]
266 pub fn contains(&self, element: &T) -> bool {
267 self.data.iter().any(|n| n == element)
268 }
269}