palette/cast/
from_into_arrays_traits.rs

1use super::{
2    from_array_array, from_array_slice, from_array_slice_mut, into_array_array, into_array_slice,
3    into_array_slice_mut, ArrayCast,
4};
5
6#[cfg(feature = "alloc")]
7use super::{from_array_slice_box, from_array_vec, into_array_slice_box, into_array_vec};
8
9/// Trait for casting a collection of colors from a collection of arrays without
10/// copying.
11///
12/// This trait is meant as a more convenient alternative to the free functions
13/// in [`cast`][crate::cast], to allow method chaining among other things.
14///
15/// ## Examples
16///
17/// ```
18/// use palette::{cast::FromArrays, Srgb};
19///
20/// let array: [_; 2] = [[64, 139, 10], [93, 18, 214]];
21/// let slice: &[_] = &[[64, 139, 10], [93, 18, 214]];
22/// let slice_mut: &mut [_] = &mut [[64, 139, 10], [93, 18, 214]];
23/// let vec: Vec<_> = vec![[64, 139, 10], [93, 18, 214]];
24///
25/// assert_eq!(
26///     <[Srgb<u8>; 2]>::from_arrays(array),
27///     [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]
28/// );
29///
30/// assert_eq!(
31///     <&[Srgb<u8>]>::from_arrays(slice),
32///     [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]
33/// );
34///
35/// assert_eq!(
36///     <&mut [Srgb<u8>]>::from_arrays(slice_mut),
37///     [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]
38/// );
39///
40/// assert_eq!(
41///     Vec::<Srgb<u8>>::from_arrays(vec),
42///     vec![Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]
43/// );
44/// ```
45///
46/// Owning types can be cast as slices, too:
47///
48/// ```
49/// use palette::{cast::FromArrays, Srgb};
50///
51/// let array: [_; 2] = [[64, 139, 10], [93, 18, 214]];
52/// let mut vec: Vec<_> = vec![[64, 139, 10], [93, 18, 214]];
53///
54/// assert_eq!(
55///     <&[Srgb<u8>]>::from_arrays(&array),
56///     [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]
57/// );
58///
59/// assert_eq!(
60///     <&mut [Srgb<u8>]>::from_arrays(&mut vec),
61///     [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]
62/// );
63/// ```
64pub trait FromArrays<A> {
65    /// Cast a collection of arrays into an collection of colors.
66    fn from_arrays(arrays: A) -> Self;
67}
68
69impl<T, C, const N: usize, const M: usize> FromArrays<[[T; N]; M]> for [C; M]
70where
71    C: ArrayCast<Array = [T; N]>,
72{
73    #[inline]
74    fn from_arrays(arrays: [[T; N]; M]) -> Self {
75        from_array_array(arrays)
76    }
77}
78
79macro_rules! impl_from_arrays_slice {
80    ($($owning:ty $(where ($($ty_input:tt)+))?),*) => {
81        $(
82            impl<'a, T, C, const N: usize $(, $($ty_input)+)?> FromArrays<&'a $owning> for &'a [C]
83            where
84                C: ArrayCast<Array = [T; N]>,
85            {
86                #[inline]
87                fn from_arrays(arrays: &'a $owning) -> Self {
88                    from_array_slice(arrays)
89                }
90            }
91
92            impl<'a, T, C, const N: usize $(, $($ty_input)+)?> FromArrays<&'a mut $owning> for &'a mut [C]
93            where
94                C: ArrayCast<Array = [T; N]>,
95            {
96                #[inline]
97                fn from_arrays(arrays: &'a mut $owning) -> Self {
98                    from_array_slice_mut(arrays)
99                }
100            }
101        )*
102    };
103}
104
105impl_from_arrays_slice!([[T; N]], [[T; N]; M] where (const M: usize));
106
107#[cfg(feature = "alloc")]
108impl_from_arrays_slice!(alloc::boxed::Box<[[T; N]]>, alloc::vec::Vec<[T; N]>);
109
110#[cfg(feature = "alloc")]
111impl<T, C, const N: usize> FromArrays<alloc::boxed::Box<[[T; N]]>> for alloc::boxed::Box<[C]>
112where
113    C: ArrayCast<Array = [T; N]>,
114{
115    #[inline]
116    fn from_arrays(arrays: alloc::boxed::Box<[[T; N]]>) -> Self {
117        from_array_slice_box(arrays)
118    }
119}
120
121#[cfg(feature = "alloc")]
122impl<T, C, const N: usize> FromArrays<alloc::vec::Vec<[T; N]>> for alloc::vec::Vec<C>
123where
124    C: ArrayCast<Array = [T; N]>,
125{
126    #[inline]
127    fn from_arrays(arrays: alloc::vec::Vec<[T; N]>) -> Self {
128        from_array_vec(arrays)
129    }
130}
131
132/// Trait for casting a collection of colors into a collection of arrays without
133/// copying.
134///
135/// This trait is meant as a more convenient alternative to the free functions
136/// in [`cast`][crate::cast], to allow method chaining among other things.
137///
138/// ## Examples
139///
140/// ```
141/// use palette::{cast::IntoArrays, Srgb};
142///
143/// let array: [_; 2] = [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
144/// let slice: &[_] = &[Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
145/// let slice_mut: &mut [_] = &mut [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
146/// let vec: Vec<_> = vec![Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
147///
148/// assert_eq!(array.into_arrays(), [[64, 139, 10], [93, 18, 214]]);
149/// assert_eq!(slice.into_arrays(), [[64, 139, 10], [93, 18, 214]]);
150/// assert_eq!(slice_mut.into_arrays(), [[64, 139, 10], [93, 18, 214]]);
151/// assert_eq!(vec.into_arrays(), vec![[64, 139, 10], [93, 18, 214]]);
152/// ```
153///
154/// Owning types can be cast as slices, too:
155///
156/// ```
157/// use palette::{cast::IntoArrays, Srgb};
158///
159/// let array: [_; 2] = [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
160/// let mut vec: Vec<_> = vec![Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
161///
162/// assert_eq!((&array).into_arrays(), [[64, 139, 10], [93, 18, 214]]);
163/// assert_eq!((&mut vec).into_arrays(), [[64, 139, 10], [93, 18, 214]]);
164/// ```
165pub trait IntoArrays<A> {
166    /// Cast this collection of colors into a collection of arrays.
167    fn into_arrays(self) -> A;
168}
169
170impl<T, C, const N: usize, const M: usize> IntoArrays<[[T; N]; M]> for [C; M]
171where
172    C: ArrayCast<Array = [T; N]>,
173{
174    #[inline]
175    fn into_arrays(self) -> [[T; N]; M] {
176        into_array_array(self)
177    }
178}
179
180macro_rules! impl_into_arrays_slice {
181    ($($owning:ty $(where ($($ty_input:tt)+))?),*) => {
182        $(
183            impl<'a, T, C, const N: usize $(, $($ty_input)+)?> IntoArrays<&'a [[T; N]]> for &'a $owning
184            where
185                C: ArrayCast<Array = [T; N]>,
186            {
187                #[inline]
188                fn into_arrays(self) -> &'a [[T; N]]  {
189                    into_array_slice(self)
190                }
191            }
192
193            impl<'a, T, C, const N: usize $(, $($ty_input)+)?> IntoArrays<&'a mut [[T; N]]> for &'a mut $owning
194            where
195                C: ArrayCast<Array = [T; N]>,
196            {
197                #[inline]
198                fn into_arrays(self) -> &'a mut [[T; N]] {
199                    into_array_slice_mut(self)
200                }
201            }
202        )*
203    };
204}
205
206impl_into_arrays_slice!([C], [C; M] where (const M: usize));
207
208#[cfg(feature = "alloc")]
209impl_into_arrays_slice!(alloc::boxed::Box<[C]>, alloc::vec::Vec<C>);
210
211#[cfg(feature = "alloc")]
212impl<T, C, const N: usize> IntoArrays<alloc::boxed::Box<[[T; N]]>> for alloc::boxed::Box<[C]>
213where
214    C: ArrayCast<Array = [T; N]>,
215{
216    #[inline]
217    fn into_arrays(self) -> alloc::boxed::Box<[[T; N]]> {
218        into_array_slice_box(self)
219    }
220}
221
222#[cfg(feature = "alloc")]
223impl<T, C, const N: usize> IntoArrays<alloc::vec::Vec<[T; N]>> for alloc::vec::Vec<C>
224where
225    C: ArrayCast<Array = [T; N]>,
226{
227    #[inline]
228    fn into_arrays(self) -> alloc::vec::Vec<[T; N]> {
229        into_array_vec(self)
230    }
231}
232
233/// Trait for casting a collection of arrays from a collection of colors without
234/// copying.
235///
236/// This trait is meant as a more convenient alternative to the free functions
237/// in [`cast`][crate::cast], to allow method chaining among other things.
238///
239/// ## Examples
240///
241/// ```
242/// use palette::{cast::ArraysFrom, Srgb};
243///
244/// let array: [_; 2] = [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
245/// let slice: &[_] = &[Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
246/// let slice_mut: &mut [_] = &mut [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
247/// let vec: Vec<_> = vec![Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
248///
249/// assert_eq!(<[_; 2]>::arrays_from(array), [[64, 139, 10], [93, 18, 214]]);
250/// assert_eq!(<&[_]>::arrays_from(slice), [[64, 139, 10], [93, 18, 214]]);
251/// assert_eq!(<&mut [_]>::arrays_from(slice_mut), [[64, 139, 10], [93, 18, 214]]);
252/// assert_eq!(Vec::<_>::arrays_from(vec), vec![[64, 139, 10], [93, 18, 214]]);
253/// ```
254///
255/// Owning types can be cast as slices, too:
256///
257/// ```
258/// use palette::{cast::ArraysFrom, Srgb};
259///
260/// let array: [_; 2] = [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
261/// let mut vec: Vec<_> = vec![Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)];
262///
263/// assert_eq!(<&[_]>::arrays_from(&array), [[64, 139, 10], [93, 18, 214]]);
264/// assert_eq!(<&mut [_]>::arrays_from(&mut vec), [[64, 139, 10], [93, 18, 214]]);
265/// ```
266pub trait ArraysFrom<C> {
267    /// Cast a collection of colors into a collection of arrays.
268    fn arrays_from(colors: C) -> Self;
269}
270
271impl<T, C> ArraysFrom<C> for T
272where
273    C: IntoArrays<T>,
274{
275    #[inline]
276    fn arrays_from(colors: C) -> Self {
277        colors.into_arrays()
278    }
279}
280
281/// Trait for casting a collection of arrays into a collection of colors
282/// without copying.
283///
284/// This trait is meant as a more convenient alternative to the free functions
285/// in [`cast`][crate::cast], to allow method chaining among other things.
286///
287/// ## Examples
288///
289/// ```
290/// use palette::{cast::ArraysInto, Srgb};
291///
292/// let array: [_; 2] = [[64, 139, 10], [93, 18, 214]];
293/// let slice: &[_] = &[[64, 139, 10], [93, 18, 214]];
294/// let slice_mut: &mut [_] = &mut [[64, 139, 10], [93, 18, 214]];
295/// let vec: Vec<_> = vec![[64, 139, 10], [93, 18, 214]];
296///
297/// let colors: [Srgb<u8>; 2] = array.arrays_into();
298/// assert_eq!(colors, [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]);
299///
300/// let colors: &[Srgb<u8>] = slice.arrays_into();
301/// assert_eq!(colors, [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]);
302///
303/// let colors: &mut [Srgb<u8>] = slice_mut.arrays_into();
304/// assert_eq!(colors, [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]);
305///
306/// let colors: Vec<Srgb<u8>> = vec.arrays_into();
307/// assert_eq!(colors, vec![Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]);
308/// ```
309///
310/// Owning types can be cast as slices, too:
311///
312/// ```
313/// use palette::{cast::ArraysInto, Srgb};
314///
315/// let array: [_; 2] = [[64, 139, 10], [93, 18, 214]];
316/// let mut vec: Vec<_> = vec![[64, 139, 10], [93, 18, 214]];
317///
318/// let colors: &[Srgb<u8>] = (&array).arrays_into();
319/// assert_eq!(colors, [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]);
320///
321/// let colors: &mut [Srgb<u8>] = (&mut vec).arrays_into();
322/// assert_eq!(colors, [Srgb::new(64u8, 139, 10), Srgb::new(93, 18, 214)]);
323/// ```
324pub trait ArraysInto<C> {
325    /// Cast this collection of arrays into a collection of colors.
326    fn arrays_into(self) -> C;
327}
328
329impl<T, C> ArraysInto<C> for T
330where
331    C: FromArrays<T>,
332{
333    #[inline]
334    fn arrays_into(self) -> C {
335        C::from_arrays(self)
336    }
337}
338
339#[cfg(test)]
340mod test {
341    use crate::Srgb;
342
343    use super::{ArraysFrom, ArraysInto, FromArrays, IntoArrays};
344
345    #[test]
346    fn from_arrays() {
347        let slice: &[[u8; 3]] = &[[1, 2, 3], [4, 5, 6]];
348        let slice_mut: &mut [[u8; 3]] = &mut [[1, 2, 3], [4, 5, 6]];
349        let mut array: [[u8; 3]; 2] = [[1, 2, 3], [4, 5, 6]];
350
351        let _ = <&[Srgb<u8>]>::from_arrays(slice);
352        let _ = <&[Srgb<u8>]>::from_arrays(&array);
353
354        let _ = <&mut [Srgb<u8>]>::from_arrays(slice_mut);
355        let _ = <&mut [Srgb<u8>]>::from_arrays(&mut array);
356
357        let _ = <[Srgb<u8>; 2]>::from_arrays(array);
358    }
359
360    #[cfg(feature = "alloc")]
361    #[test]
362    fn from_arrays_alloc() {
363        let mut slice_box: Box<[[u8; 3]]> = vec![[1, 2, 3], [4, 5, 6]].into_boxed_slice();
364        let mut vec: Vec<[u8; 3]> = vec![[1, 2, 3], [4, 5, 6]];
365
366        let _ = <&[Srgb<u8>]>::from_arrays(&slice_box);
367        let _ = <&[Srgb<u8>]>::from_arrays(&vec);
368
369        let _ = <&mut [Srgb<u8>]>::from_arrays(&mut slice_box);
370        let _ = <&mut [Srgb<u8>]>::from_arrays(&mut vec);
371
372        let _ = Box::<[Srgb<u8>]>::from_arrays(slice_box);
373        let _ = Vec::<Srgb<u8>>::from_arrays(vec);
374    }
375
376    #[test]
377    fn arrays_into() {
378        let slice: &[[u8; 3]] = &[[1, 2, 3], [4, 5, 6]];
379        let slice_mut: &mut [[u8; 3]] = &mut [[1, 2, 3], [4, 5, 6]];
380        let mut array: [[u8; 3]; 2] = [[1, 2, 3], [4, 5, 6]];
381
382        let _: &[Srgb<u8>] = slice.arrays_into();
383        let _: &[Srgb<u8>] = (&array).arrays_into();
384
385        let _: &mut [Srgb<u8>] = slice_mut.arrays_into();
386        let _: &mut [Srgb<u8>] = (&mut array).arrays_into();
387
388        let _: [Srgb<u8>; 2] = array.arrays_into();
389    }
390
391    #[cfg(feature = "alloc")]
392    #[test]
393    fn arrays_into_alloc() {
394        let mut slice_box: Box<[[u8; 3]]> = vec![[1, 2, 3], [4, 5, 6]].into_boxed_slice();
395        let mut vec: Vec<[u8; 3]> = vec![[1, 2, 3], [4, 5, 6]];
396
397        let _: &[Srgb<u8>] = (&slice_box).arrays_into();
398        let _: &[Srgb<u8>] = (&vec).arrays_into();
399
400        let _: &mut [Srgb<u8>] = (&mut slice_box).arrays_into();
401        let _: &mut [Srgb<u8>] = (&mut vec).arrays_into();
402
403        let _: Box<[Srgb<u8>]> = slice_box.arrays_into();
404        let _: Vec<Srgb<u8>> = vec.arrays_into();
405    }
406
407    #[test]
408    fn into_arrays() {
409        let slice: &[Srgb<u8>] = &[Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
410        let slice_mut: &mut [Srgb<u8>] = &mut [Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
411        let mut array: [Srgb<u8>; 2] = [Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
412
413        let _: &[[u8; 3]] = slice.into_arrays();
414        let _: &[[u8; 3]] = (&array).into_arrays();
415
416        let _: &mut [[u8; 3]] = slice_mut.into_arrays();
417        let _: &mut [[u8; 3]] = (&mut array).into_arrays();
418
419        let _: [[u8; 3]; 2] = array.into_arrays();
420    }
421
422    #[cfg(feature = "alloc")]
423    #[test]
424    fn into_arrays_alloc() {
425        let mut slice_box: Box<[Srgb<u8>]> =
426            vec![Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)].into_boxed_slice();
427        let mut vec: Vec<Srgb<u8>> = vec![Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
428
429        let _: &[[u8; 3]] = (&slice_box).into_arrays();
430        let _: &[[u8; 3]] = (&vec).into_arrays();
431
432        let _: &mut [[u8; 3]] = (&mut slice_box).into_arrays();
433        let _: &mut [[u8; 3]] = (&mut vec).into_arrays();
434
435        let _: Box<[[u8; 3]]> = slice_box.into_arrays();
436        let _: Vec<[u8; 3]> = vec.into_arrays();
437    }
438
439    #[test]
440    fn arrays_from() {
441        let slice: &[Srgb<u8>] = &[Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
442        let slice_mut: &mut [Srgb<u8>] = &mut [Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
443        let mut array: [Srgb<u8>; 2] = [Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
444
445        let _ = <&[[u8; 3]]>::arrays_from(slice);
446        let _ = <&[[u8; 3]]>::arrays_from(&array);
447
448        let _ = <&mut [[u8; 3]]>::arrays_from(slice_mut);
449        let _ = <&mut [[u8; 3]]>::arrays_from(&mut array);
450
451        let _ = <[[u8; 3]; 2]>::arrays_from(array);
452    }
453
454    #[cfg(feature = "alloc")]
455    #[test]
456    fn arrays_from_alloc() {
457        let mut slice_box: Box<[Srgb<u8>]> =
458            vec![Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)].into_boxed_slice();
459        let mut vec: Vec<Srgb<u8>> = vec![Srgb::new(1, 2, 3), Srgb::new(4, 5, 6)];
460
461        let _ = <&[[u8; 3]]>::arrays_from(&slice_box);
462        let _ = <&[[u8; 3]]>::arrays_from(&vec);
463
464        let _ = <&mut [[u8; 3]]>::arrays_from(&mut slice_box);
465        let _ = <&mut [[u8; 3]]>::arrays_from(&mut vec);
466
467        let _ = Box::<[[u8; 3]]>::arrays_from(slice_box);
468        let _ = Vec::<[u8; 3]>::arrays_from(vec);
469    }
470}