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}