Skip to main content

hexga_array/
array.rs

1use super::*;
2use std::cmp::Ordering;
3
4/// An array that is indexable, without any information if the type and the size are generic.
5/// Check [`ArrayWithType`] and [ArrayWithSize] for editable generic type.
6pub trait Array<T, const N: usize>:
7    From<[T; N]> + Into<[T; N]> + Index<usize, Output = T> + IndexMut<usize, Output = T>
8{
9    const DIMENSION: usize = N;
10
11    fn array(&self) -> &[T; N];
12    fn array_mut(&mut self) -> &mut [T; N];
13
14    /// Fill non existing component with [`Default`]
15    fn to_array_resized<const M: usize>(self) -> [T; M]
16    where
17        T: Default,
18    {
19        let mut it = <Self as Into<[T; N]>>::into(self).into_iter();
20        <[T; M]>::from_fn(|_| it.next().unwrap_or_default())
21    }
22
23    /// Fill non existing component with the [`Clone`]d given value
24    fn to_array_resized_with_value<const M: usize>(self, fill: T) -> [T; M]
25    where
26        T: Clone,
27    {
28        let mut it = <Self as Into<[T; N]>>::into(self).into_iter();
29        <[T; M]>::from_fn(|_| it.next().unwrap_or_else(|| fill.clone()))
30    }
31}
32impl<T, const N: usize> Array<T, N> for [T; N]
33{
34    fn array(&self) -> &[T; N] { self }
35    fn array_mut(&mut self) -> &mut [T; N] { self }
36}
37
38/// An type equivalent to an array with a generic size that can be changed
39///
40/// ex, `[T;N]` is an array with a generic size, but `struct RGBA([T;4])` don't have a generic size (always 4 components)
41pub trait ArrayWithSize<T, const N: usize>: Array<T, N>
42{
43    type WithSize<const M: usize>: ArrayWithSize<T, M>;
44
45    /// Resize the array to the given size, filling non existing component with [`Default`]
46    /// Fill non existing component with [`Default`]
47    fn resize<const M: usize>(self) -> Self::WithSize<M>
48    where
49        T: Default,
50    {
51        Self::WithSize::from_array(self.to_array_resized())
52    }
53
54    /// Fill non existing component with the [`Clone`]d given value
55    fn resize_with_value<const M: usize>(self, value: T) -> Self::WithSize<M>
56    where
57        T: Clone,
58    {
59        Self::WithSize::from_array(self.to_array_resized_with_value(value))
60    }
61}
62impl<T, const N: usize> ArrayWithSize<T, N> for [T; N]
63{
64    type WithSize<const M: usize> = [T; M];
65}
66
67/// An array with a generic type that can be changed
68///
69/// ex, `[T;N]` is an array with a generic type, but `struct VecF32<const N: usize>([f32;N])` don't have a generic type (4 components)
70pub trait ArrayWithType<T, const N: usize>: Array<T, N>
71{
72    type WithType<T2>: ArrayWithType<T2, N>;
73}
74impl<T, const N: usize> ArrayWithType<T, N> for [T; N]
75{
76    type WithType<T2> = [T2; N];
77}
78
79impl<S, T, const N: usize> ArrayMin<T, N> for S where S: Array<T, N> {}
80/// Assuming the size N != 0
81pub trait ArrayMin<T, const N: usize>: Array<T, N>
82{
83    fn min_element_by<F>(&self, mut compare: F) -> &T
84    where
85        F: FnMut(&T, &T) -> Ordering,
86    {
87        self.array()
88            .iter()
89            .min_by(|a, b| compare(a, b))
90            .expect("size can't be empty")
91    }
92    fn min_element_by_key<F, K>(&self, mut f: F) -> &T
93    where
94        F: FnMut(&T) -> K,
95        K: Ord,
96    {
97        self.min_element_by(|a, b| f(a).cmp(&f(b)))
98    }
99    fn min_element_mut_by<F>(&mut self, mut compare: F) -> &mut T
100    where
101        F: FnMut(&T, &T) -> Ordering,
102    {
103        self.array_mut()
104            .iter_mut()
105            .min_by(|a, b| compare(a, b))
106            .expect("size can't be empty")
107    }
108    fn min_element_mut_by_key<F, K>(&mut self, mut f: F) -> &mut T
109    where
110        F: FnMut(&T) -> K,
111        K: Ord,
112    {
113        self.min_element_mut_by(|a, b| f(a).cmp(&f(b)))
114    }
115    fn min_element(&self) -> &T
116    where
117        T: PartialOrd,
118    {
119        self.array()
120            .iter()
121            .min_by(|a, b| a.partial_cmp(b).unwrap())
122            .expect("size can't be empty")
123    }
124    fn min_element_mut(&mut self) -> &mut T
125    where
126        T: PartialOrd,
127    {
128        self.array_mut()
129            .iter_mut()
130            .min_by(|a, b| a.partial_cmp(b).unwrap())
131            .expect("size can't be empty")
132    }
133    fn min_element_idx(&self) -> usize
134    where
135        T: PartialOrd,
136    {
137        self.array()
138            .iter()
139            .enumerate()
140            .min_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
141            .map(|(idx, _)| idx)
142            .unwrap()
143    }
144}
145
146/// Assuming the size N != 0
147impl<S, T, const N: usize> ArrayMax<T, N> for S where S: Array<T, N> {}
148pub trait ArrayMax<T, const N: usize>: Array<T, N>
149{
150    fn max_element_by<F>(&self, mut compare: F) -> &T
151    where
152        F: FnMut(&T, &T) -> Ordering,
153    {
154        self.array()
155            .iter()
156            .max_by(|a, b| compare(a, b))
157            .expect("size can't be empty")
158    }
159    fn max_element_by_key<F, K>(&self, mut f: F) -> &T
160    where
161        F: FnMut(&T) -> K,
162        K: Ord,
163    {
164        self.max_element_by(|a, b| f(a).cmp(&f(b)))
165    }
166    fn max_element_mut_by<F>(&mut self, mut compare: F) -> &mut T
167    where
168        F: FnMut(&T, &T) -> Ordering,
169    {
170        self.array_mut()
171            .iter_mut()
172            .max_by(|a, b| compare(a, b))
173            .expect("size can't be empty")
174    }
175    fn max_element_mut_by_key<F, K>(&mut self, mut f: F) -> &mut T
176    where
177        F: FnMut(&T) -> K,
178        K: Ord,
179    {
180        self.max_element_mut_by(|a, b| f(a).cmp(&f(b)))
181    }
182    fn max_element(&self) -> &T
183    where
184        T: PartialOrd,
185    {
186        self.array()
187            .iter()
188            .max_by(|a, b| a.partial_cmp(b).unwrap())
189            .expect("size can't be empty")
190    }
191    fn max_element_mut(&mut self) -> &mut T
192    where
193        T: PartialOrd,
194    {
195        self.array_mut()
196            .iter_mut()
197            .max_by(|a, b| a.partial_cmp(b).unwrap())
198            .expect("size can't be empty")
199    }
200    fn max_element_idx(&self) -> usize
201    where
202        T: PartialOrd,
203    {
204        self.array()
205            .iter()
206            .enumerate()
207            .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
208            .map(|(idx, _)| idx)
209            .unwrap()
210    }
211}