palette/cast/
from_into_uints_traits.rs

1use super::{
2    from_uint_array, from_uint_slice, from_uint_slice_mut, into_uint_array, into_uint_slice,
3    into_uint_slice_mut, UintCast,
4};
5
6#[cfg(feature = "alloc")]
7use super::{from_uint_slice_box, from_uint_vec, into_uint_slice_box, into_uint_vec};
8
9/// Trait for casting a collection of colors from a collection of unsigned
10/// integers without 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::FromUints, rgb::PackedArgb, Srgba};
19///
20/// let array: [_; 2] = [0xFF17C64C, 0xFF5D12D6];
21/// let slice: &[_] = &[0xFF17C64C, 0xFF5D12D6];
22/// let slice_mut: &mut [_] = &mut [0xFF17C64C, 0xFF5D12D6];
23/// let vec: Vec<_> = vec![0xFF17C64C, 0xFF5D12D6];
24///
25/// assert_eq!(
26///     <[PackedArgb; 2]>::from_uints(array),
27///     [
28///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
29///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
30///     ]
31/// );
32///
33/// assert_eq!(
34///     <&[PackedArgb]>::from_uints(slice),
35///     [
36///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
37///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
38///     ]
39/// );
40///
41/// assert_eq!(
42///     <&mut [PackedArgb]>::from_uints(slice_mut),
43///     [
44///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
45///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
46///     ]
47/// );
48///
49/// assert_eq!(
50///     Vec::<PackedArgb>::from_uints(vec),
51///     vec![
52///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
53///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
54///     ]
55/// );
56/// ```
57///
58/// Owning types can be cast as slices, too:
59///
60/// ```
61/// use palette::{cast::FromUints, rgb::PackedArgb, Srgba};
62///
63/// let array: [_; 2] = [0xFF17C64C, 0xFF5D12D6];
64/// let mut vec: Vec<_> = vec![0xFF17C64C, 0xFF5D12D6];
65///
66/// assert_eq!(
67///     <&[PackedArgb]>::from_uints(&array),
68///     [
69///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
70///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
71///     ]
72/// );
73///
74/// assert_eq!(
75///     <&mut [PackedArgb]>::from_uints(&mut vec),
76///     [
77///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
78///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
79///     ]
80/// );
81/// ```
82pub trait FromUints<U> {
83    /// Cast a collection of unsigned integers into an collection of colors.
84    fn from_uints(uints: U) -> Self;
85}
86
87impl<C, const N: usize> FromUints<[C::Uint; N]> for [C; N]
88where
89    C: UintCast,
90{
91    #[inline]
92    fn from_uints(uints: [C::Uint; N]) -> Self {
93        from_uint_array(uints)
94    }
95}
96
97macro_rules! impl_from_uints_slice {
98    ($($owning:ty $(where ($($ty_input:tt)+))?),*) => {
99        $(
100            impl<'a, C $(, $($ty_input)+)?> FromUints<&'a $owning> for &'a [C]
101            where
102                C: UintCast,
103            {
104                #[inline]
105                fn from_uints(uints: &'a $owning) -> Self {
106                    from_uint_slice(uints)
107                }
108            }
109
110            impl<'a, C $(, $($ty_input)+)?> FromUints<&'a mut $owning> for &'a mut [C]
111            where
112                C: UintCast,
113            {
114                #[inline]
115                fn from_uints(uints: &'a mut $owning) -> Self {
116                    from_uint_slice_mut(uints)
117                }
118            }
119        )*
120    };
121}
122
123impl_from_uints_slice!([C::Uint], [C::Uint; N] where (const N: usize));
124
125#[cfg(feature = "alloc")]
126impl_from_uints_slice!(alloc::boxed::Box<[C::Uint]>, alloc::vec::Vec<C::Uint>);
127
128#[cfg(feature = "alloc")]
129impl<C> FromUints<alloc::boxed::Box<[C::Uint]>> for alloc::boxed::Box<[C]>
130where
131    C: UintCast,
132{
133    #[inline]
134    fn from_uints(uints: alloc::boxed::Box<[C::Uint]>) -> Self {
135        from_uint_slice_box(uints)
136    }
137}
138
139#[cfg(feature = "alloc")]
140impl<C> FromUints<alloc::vec::Vec<C::Uint>> for alloc::vec::Vec<C>
141where
142    C: UintCast,
143{
144    #[inline]
145    fn from_uints(uints: alloc::vec::Vec<C::Uint>) -> Self {
146        from_uint_vec(uints)
147    }
148}
149
150/// Trait for casting a collection of colors into a collection of unsigned
151/// integers without copying.
152///
153/// This trait is meant as a more convenient alternative to the free functions
154/// in [`cast`][crate::cast], to allow method chaining among other things.
155///
156/// ## Examples
157///
158/// ```
159/// use palette::{cast::IntoUints, rgb::PackedArgb, Srgba};
160///
161/// let array: [PackedArgb; 2] = [
162///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
163///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
164/// ];
165/// let slice: &[PackedArgb] = &[
166///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
167///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
168/// ];
169/// let slice_mut: &mut [PackedArgb] = &mut [
170///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
171///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
172/// ];
173/// let vec: Vec<PackedArgb> = vec![
174///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
175///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
176/// ];
177///
178/// assert_eq!(array.into_uints(), [0xFF17C64C, 0xFF5D12D6]);
179/// assert_eq!(slice.into_uints(), [0xFF17C64C, 0xFF5D12D6]);
180/// assert_eq!(slice_mut.into_uints(), [0xFF17C64C, 0xFF5D12D6]);
181/// assert_eq!(vec.into_uints(), vec![0xFF17C64C, 0xFF5D12D6]);
182/// ```
183///
184/// Owning types can be cast as slices, too:
185///
186/// ```
187/// use palette::{cast::IntoUints, rgb::PackedArgb, Srgba};
188///
189/// let array: [PackedArgb; 2] = [
190///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
191///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
192/// ];
193/// let mut vec: Vec<PackedArgb> = vec![
194///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
195///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
196/// ];
197///
198/// assert_eq!((&array).into_uints(), [0xFF17C64C, 0xFF5D12D6]);
199/// assert_eq!((&mut vec).into_uints(), [0xFF17C64C, 0xFF5D12D6]);
200/// ```
201pub trait IntoUints<U> {
202    /// Cast this collection of colors into a collection of unsigned integers.
203    fn into_uints(self) -> U;
204}
205
206impl<C, const N: usize> IntoUints<[C::Uint; N]> for [C; N]
207where
208    C: UintCast,
209{
210    #[inline]
211    fn into_uints(self) -> [C::Uint; N] {
212        into_uint_array(self)
213    }
214}
215
216macro_rules! impl_into_uints_slice {
217    ($($owning:ty $(where ($($ty_input:tt)+))?),*) => {
218        $(
219            impl<'a, C $(, $($ty_input)+)?> IntoUints<&'a [C::Uint]> for &'a $owning
220            where
221                C: UintCast,
222            {
223                #[inline]
224                fn into_uints(self) -> &'a [C::Uint]  {
225                    into_uint_slice(self)
226                }
227            }
228
229            impl<'a, C $(, $($ty_input)+)?> IntoUints<&'a mut [C::Uint]> for &'a mut $owning
230            where
231                C: UintCast,
232            {
233                #[inline]
234                fn into_uints(self) -> &'a mut [C::Uint] {
235                    into_uint_slice_mut(self)
236                }
237            }
238        )*
239    };
240}
241
242impl_into_uints_slice!([C], [C; M] where (const M: usize));
243
244#[cfg(feature = "alloc")]
245impl_into_uints_slice!(alloc::boxed::Box<[C]>, alloc::vec::Vec<C>);
246
247#[cfg(feature = "alloc")]
248impl<C> IntoUints<alloc::boxed::Box<[C::Uint]>> for alloc::boxed::Box<[C]>
249where
250    C: UintCast,
251{
252    #[inline]
253    fn into_uints(self) -> alloc::boxed::Box<[C::Uint]> {
254        into_uint_slice_box(self)
255    }
256}
257
258#[cfg(feature = "alloc")]
259impl<C> IntoUints<alloc::vec::Vec<C::Uint>> for alloc::vec::Vec<C>
260where
261    C: UintCast,
262{
263    #[inline]
264    fn into_uints(self) -> alloc::vec::Vec<C::Uint> {
265        into_uint_vec(self)
266    }
267}
268
269/// Trait for casting a collection of unsigned integers from a collection of
270/// colors without copying.
271///
272/// This trait is meant as a more convenient alternative to the free functions
273/// in [`cast`][crate::cast], to allow method chaining among other things.
274///
275/// ## Examples
276///
277/// ```
278/// use palette::{cast::UintsFrom, rgb::PackedArgb, Srgba};
279///
280/// let array: [PackedArgb; 2] = [
281///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
282///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
283/// ];
284/// let slice: &[PackedArgb] = &[
285///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
286///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
287/// ];
288/// let slice_mut: &mut [PackedArgb] = &mut [
289///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
290///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
291/// ];
292/// let vec: Vec<PackedArgb> = vec![
293///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
294///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
295/// ];
296///
297/// assert_eq!(<[_; 2]>::uints_from(array), [0xFF17C64C, 0xFF5D12D6]);
298/// assert_eq!(<&[_]>::uints_from(slice), [0xFF17C64C, 0xFF5D12D6]);
299/// assert_eq!(<&mut [_]>::uints_from(slice_mut), [0xFF17C64C, 0xFF5D12D6]);
300/// assert_eq!(Vec::<_>::uints_from(vec), vec![0xFF17C64C, 0xFF5D12D6]);
301/// ```
302///
303/// Owning types can be cast as slices, too:
304///
305/// ```
306/// use palette::{cast::UintsFrom, rgb::PackedArgb, Srgba};
307///
308/// let array: [PackedArgb; 2] = [
309///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
310///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
311/// ];
312/// let mut vec: Vec<PackedArgb> = vec![
313///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
314///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
315/// ];
316///
317/// assert_eq!(<&[_]>::uints_from(&array), [0xFF17C64C, 0xFF5D12D6]);
318/// assert_eq!(<&mut [_]>::uints_from(&mut vec), [0xFF17C64C, 0xFF5D12D6]);
319/// ```
320pub trait UintsFrom<C> {
321    /// Cast a collection of colors into a collection of unsigned integers.
322    fn uints_from(colors: C) -> Self;
323}
324
325impl<C, U> UintsFrom<C> for U
326where
327    C: IntoUints<U>,
328{
329    #[inline]
330    fn uints_from(colors: C) -> Self {
331        colors.into_uints()
332    }
333}
334
335/// Trait for casting a collection of unsigned integers into a collection of
336/// colors without copying.
337///
338/// This trait is meant as a more convenient alternative to the free functions
339/// in [`cast`][crate::cast], to allow method chaining among other things.
340///
341/// ## Examples
342///
343/// ```
344/// use palette::{cast::UintsInto, rgb::PackedArgb, Srgba};
345///
346/// let array: [_; 2] = [0xFF17C64C, 0xFF5D12D6];
347/// let slice: &[_] = &[0xFF17C64C, 0xFF5D12D6];
348/// let slice_mut: &mut [_] = &mut [0xFF17C64C, 0xFF5D12D6];
349/// let vec: Vec<_> = vec![0xFF17C64C, 0xFF5D12D6];
350///
351/// let colors: [PackedArgb; 2] = array.uints_into();
352/// assert_eq!(colors, [
353///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
354///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
355/// ]);
356///
357/// let colors: &[PackedArgb] = slice.uints_into();
358/// assert_eq!(colors, [
359///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
360///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
361/// ]);
362///
363/// let colors: &mut [PackedArgb] = slice_mut.uints_into();
364/// assert_eq!(colors, [
365///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
366///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
367/// ]);
368///
369/// let colors: Vec<PackedArgb> = vec.uints_into();
370/// assert_eq!(colors, vec![
371///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
372///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
373/// ]);
374/// ```
375///
376/// Owning types can be cast as slices, too:
377///
378/// ```
379/// use palette::{cast::UintsInto, rgb::PackedArgb, Srgba};
380///
381/// let array: [_; 2] = [0xFF17C64C, 0xFF5D12D6];
382/// let mut vec: Vec<_> = vec![0xFF17C64C, 0xFF5D12D6];
383///
384/// let colors: &[PackedArgb] = (&array).uints_into();
385/// assert_eq!(colors, [
386///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
387///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
388/// ]);
389///
390/// let colors: &mut [PackedArgb] = (&mut vec).uints_into();
391/// assert_eq!(colors, [
392///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
393///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
394/// ]);
395/// ```
396pub trait UintsInto<C> {
397    /// Cast this collection of unsigned integers into a collection of colors.
398    fn uints_into(self) -> C;
399}
400
401impl<C, U> UintsInto<C> for U
402where
403    C: FromUints<U>,
404{
405    #[inline]
406    fn uints_into(self) -> C {
407        C::from_uints(self)
408    }
409}
410
411#[cfg(test)]
412mod test {
413    use crate::{rgb::PackedRgba, Srgba};
414
415    use super::{FromUints, IntoUints, UintsFrom, UintsInto};
416
417    #[test]
418    fn from_uints() {
419        let slice: &[u32] = &[0x01020304, 0x05060708];
420        let slice_mut: &mut [u32] = &mut [0x01020304, 0x05060708];
421        let mut array: [u32; 2] = [0x01020304, 0x05060708];
422
423        let _ = <&[PackedRgba]>::from_uints(slice);
424        let _ = <&[PackedRgba]>::from_uints(&array);
425
426        let _ = <&mut [PackedRgba]>::from_uints(slice_mut);
427        let _ = <&mut [PackedRgba]>::from_uints(&mut array);
428
429        let _ = <[PackedRgba; 2]>::from_uints(array);
430    }
431
432    #[cfg(feature = "alloc")]
433    #[test]
434    fn from_uints_alloc() {
435        let mut slice_box: Box<[u32]> = vec![0x01020304, 0x05060708].into_boxed_slice();
436        let mut vec: Vec<u32> = vec![0x01020304, 0x05060708];
437
438        let _ = <&[PackedRgba]>::from_uints(&slice_box);
439        let _ = <&[PackedRgba]>::from_uints(&vec);
440
441        let _ = <&mut [PackedRgba]>::from_uints(&mut slice_box);
442        let _ = <&mut [PackedRgba]>::from_uints(&mut vec);
443
444        let _ = Box::<[PackedRgba]>::from_uints(slice_box);
445        let _ = Vec::<PackedRgba>::from_uints(vec);
446    }
447
448    #[test]
449    fn uints_into() {
450        let slice: &[u32] = &[0x01020304, 0x05060708];
451        let slice_mut: &mut [u32] = &mut [0x01020304, 0x05060708];
452        let mut array: [u32; 2] = [0x01020304, 0x05060708];
453
454        let _: &[PackedRgba] = slice.uints_into();
455        let _: &[PackedRgba] = (&array).uints_into();
456
457        let _: &mut [PackedRgba] = slice_mut.uints_into();
458        let _: &mut [PackedRgba] = (&mut array).uints_into();
459
460        let _: [PackedRgba; 2] = array.uints_into();
461    }
462
463    #[cfg(feature = "alloc")]
464    #[test]
465    fn uints_into_alloc() {
466        let mut slice_box: Box<[u32]> = vec![0x01020304, 0x05060708].into_boxed_slice();
467        let mut vec: Vec<u32> = vec![0x01020304, 0x05060708];
468
469        let _: &[PackedRgba] = (&slice_box).uints_into();
470        let _: &[PackedRgba] = (&vec).uints_into();
471
472        let _: &mut [PackedRgba] = (&mut slice_box).uints_into();
473        let _: &mut [PackedRgba] = (&mut vec).uints_into();
474
475        let _: Box<[PackedRgba]> = slice_box.uints_into();
476        let _: Vec<PackedRgba> = vec.uints_into();
477    }
478
479    #[test]
480    fn into_uints() {
481        let slice: &[PackedRgba] = &[Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
482        let slice_mut: &mut [PackedRgba] =
483            &mut [Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
484        let mut array: [PackedRgba; 2] =
485            [Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
486
487        let _: &[u32] = slice.into_uints();
488        let _: &[u32] = (&array).into_uints();
489
490        let _: &mut [u32] = slice_mut.into_uints();
491        let _: &mut [u32] = (&mut array).into_uints();
492
493        let _: [u32; 2] = array.into_uints();
494    }
495
496    #[cfg(feature = "alloc")]
497    #[test]
498    fn into_uints_alloc() {
499        let mut slice_box: Box<[PackedRgba]> =
500            vec![Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()].into_boxed_slice();
501        let mut vec: Vec<PackedRgba> =
502            vec![Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
503
504        let _: &[u32] = (&slice_box).into_uints();
505        let _: &[u32] = (&vec).into_uints();
506
507        let _: &mut [u32] = (&mut slice_box).into_uints();
508        let _: &mut [u32] = (&mut vec).into_uints();
509
510        let _: Box<[u32]> = slice_box.into_uints();
511        let _: Vec<u32> = vec.into_uints();
512    }
513
514    #[test]
515    fn uints_from() {
516        let slice: &[PackedRgba] = &[Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
517        let slice_mut: &mut [PackedRgba] =
518            &mut [Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
519        let mut array: [PackedRgba; 2] =
520            [Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
521
522        let _ = <&[u32]>::uints_from(slice);
523        let _ = <&[u32]>::uints_from(&array);
524
525        let _ = <&mut [u32]>::uints_from(slice_mut);
526        let _ = <&mut [u32]>::uints_from(&mut array);
527
528        let _ = <[u32; 2]>::uints_from(array);
529    }
530
531    #[cfg(feature = "alloc")]
532    #[test]
533    fn uints_from_alloc() {
534        let mut slice_box: Box<[PackedRgba]> =
535            vec![Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()].into_boxed_slice();
536        let mut vec: Vec<PackedRgba> =
537            vec![Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
538
539        let _ = <&[u32]>::uints_from(&slice_box);
540        let _ = <&[u32]>::uints_from(&vec);
541
542        let _ = <&mut [u32]>::uints_from(&mut slice_box);
543        let _ = <&mut [u32]>::uints_from(&mut vec);
544
545        let _ = Box::<[u32]>::uints_from(slice_box);
546        let _ = Vec::<u32>::uints_from(vec);
547    }
548}