palette/cast/
as_uints_traits.rs

1use super::{from_uint_slice, from_uint_slice_mut, into_uint_slice, into_uint_slice_mut, UintCast};
2
3/// Trait for casting a reference to a collection of colors into a reference to
4/// a collection of unsigned integers without copying.
5///
6/// This trait is meant as a more convenient alternative to the free functions
7/// in [`cast`][crate::cast], to allow method chaining among other things.
8///
9/// ## Examples
10///
11/// ```
12/// use palette::{cast::AsUints, rgb::PackedArgb, Srgba};
13///
14/// let array: [PackedArgb; 2] = [
15///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
16///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
17/// ];
18/// let slice: &[PackedArgb] = &[
19///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
20///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
21/// ];
22/// let vec: Vec<PackedArgb> = vec![
23///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
24///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
25/// ];
26///
27/// assert_eq!(array.as_uints(), &[0xFF17C64C, 0xFF5D12D6]);
28/// assert_eq!(slice.as_uints(), &[0xFF17C64C, 0xFF5D12D6]);
29/// assert_eq!(vec.as_uints(), &[0xFF17C64C, 0xFF5D12D6]);
30/// ```
31pub trait AsUints<A: ?Sized> {
32    /// Cast this collection of colors into a collection of unsigned integers.
33    fn as_uints(&self) -> &A;
34}
35
36/// Trait for casting a mutable reference to a collection of colors into a
37/// mutable reference to a collection of unsigned integers without copying.
38///
39/// This trait is meant as a more convenient alternative to the free functions
40/// in [`cast`][crate::cast], to allow method chaining among other things.
41///
42/// ## Examples
43///
44/// ```
45/// use palette::{cast::AsUintsMut, rgb::PackedArgb, Srgba};
46///
47/// let mut array: [PackedArgb; 2] = [
48///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
49///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
50/// ];
51/// let slice_mut: &mut [PackedArgb] = &mut [
52///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
53///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
54/// ];
55/// let mut vec: Vec<PackedArgb> = vec![
56///     Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
57///     Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
58/// ];
59///
60/// assert_eq!(array.as_uints_mut(), &mut [0xFF17C64C, 0xFF5D12D6]);
61/// assert_eq!(slice_mut.as_uints_mut(), &mut [0xFF17C64C, 0xFF5D12D6]);
62/// assert_eq!(vec.as_uints_mut(), &mut [0xFF17C64C, 0xFF5D12D6]);
63/// ```
64pub trait AsUintsMut<A: ?Sized> {
65    /// Cast this collection of colors into a mutable collection of unsigned integers.
66    fn as_uints_mut(&mut self) -> &mut A;
67}
68
69macro_rules! impl_as_uints {
70    ($($owning:ty $(where ($($ty_input:tt)+))?),*) => {
71        $(
72            impl<'a, C $(, $($ty_input)+)?> AsUints<[C::Uint]> for $owning
73            where
74                C: UintCast,
75            {
76                #[inline]
77                fn as_uints(&self) -> &[C::Uint] {
78                    into_uint_slice(self.as_ref())
79                }
80            }
81
82            impl<'a, C $(, $($ty_input)+)?> AsUintsMut<[C::Uint]> for $owning
83            where
84                C: UintCast,
85            {
86                #[inline]
87                fn as_uints_mut(&mut self) -> &mut [C::Uint] {
88                    into_uint_slice_mut(self.as_mut())
89                }
90            }
91        )*
92    };
93}
94
95impl_as_uints!([C], [C; N] where (const N: usize));
96
97#[cfg(feature = "alloc")]
98impl_as_uints!(alloc::boxed::Box<[C]>, alloc::vec::Vec<C>);
99
100/// Trait for casting a reference to a collection of unsigned integers into a
101/// reference to a collection of colors without copying.
102///
103/// This trait is meant as a more convenient alternative to the free functions
104/// in [`cast`][crate::cast], to allow method chaining among other things.
105///
106/// ## Examples
107///
108/// ```
109/// use palette::{cast::UintsAs, rgb::PackedArgb, Srgba};
110///
111/// let array: [_; 2] = [0xFF17C64C, 0xFF5D12D6];
112/// let slice: &[_] = &[0xFF17C64C, 0xFF5D12D6];
113/// let vec: Vec<_> = vec![0xFF17C64C, 0xFF5D12D6];
114///
115/// let colors: &[PackedArgb] = array.uints_as();
116/// assert_eq!(
117///     colors,
118///     &[
119///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
120///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
121///     ]
122/// );
123///
124/// let colors: &[PackedArgb] = slice.uints_as();
125/// assert_eq!(
126///     colors,
127///     &[
128///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
129///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
130///     ]
131/// );
132///
133/// let colors: &[PackedArgb] = vec.uints_as();
134/// assert_eq!(
135///     colors,
136///     &[
137///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
138///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
139///     ]
140/// );
141/// ```
142pub trait UintsAs<C: ?Sized> {
143    /// Cast this collection of unsigned integers into a collection of colors.
144    fn uints_as(&self) -> &C;
145}
146
147/// Trait for casting a mutable reference to a collection of unsigned integers
148/// into a mutable reference to a collection of colors without copying.
149///
150/// This trait is meant as a more convenient alternative to the free functions
151/// in [`cast`][crate::cast], to allow method chaining among other things.
152///
153/// ## Examples
154///
155/// ```
156/// use palette::{cast::UintsAsMut, rgb::PackedArgb, Srgba};
157///
158/// let mut array: [_; 2] = [0xFF17C64C, 0xFF5D12D6];
159/// let slice_mut: &mut [_] = &mut [0xFF17C64C, 0xFF5D12D6];
160/// let mut vec: Vec<_> = vec![0xFF17C64C, 0xFF5D12D6];
161///
162/// let colors: &mut [PackedArgb] = array.uints_as_mut();
163/// assert_eq!(
164///     colors,
165///     &mut [
166///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
167///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
168///     ]
169/// );
170///
171/// let colors: &mut [PackedArgb] = slice_mut.uints_as_mut();
172/// assert_eq!(
173///     colors,
174///     &mut [
175///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
176///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
177///     ]
178/// );
179///
180/// let colors: &mut [PackedArgb] = vec.uints_as_mut();
181/// assert_eq!(
182///     colors,
183///     &mut [
184///         Srgba::new(0x17, 0xC6, 0x4C, 0xFF).into(),
185///         Srgba::new(0x5D, 0x12, 0xD6, 0xFF).into()
186///     ]
187/// );
188/// ```
189pub trait UintsAsMut<C: ?Sized> {
190    /// Cast this collection of unsigned integers into a mutable collection of colors.
191    fn uints_as_mut(&mut self) -> &mut C;
192}
193
194macro_rules! impl_uints_as {
195    ($($owning:ty $(where ($($ty_input:tt)+))?),*) => {
196        $(
197            impl<'a, C $(, $($ty_input)+)?> UintsAs<[C]> for $owning
198            where
199                C: UintCast,
200            {
201                #[inline]
202                fn uints_as(&self) -> &[C] {
203                    from_uint_slice(self.as_ref())
204                }
205            }
206
207            impl<'a, C $(, $($ty_input)+)?> UintsAsMut<[C]> for $owning
208            where
209                C: UintCast,
210            {
211                #[inline]
212                fn uints_as_mut(&mut self) -> &mut [C] {
213                    from_uint_slice_mut(self.as_mut())
214                }
215            }
216        )*
217    };
218}
219
220impl_uints_as!([C::Uint], [C::Uint; N] where (const N: usize));
221
222#[cfg(feature = "alloc")]
223impl_uints_as!(alloc::boxed::Box<[C::Uint]>, alloc::vec::Vec<C::Uint>);
224
225#[cfg(test)]
226mod test {
227    use crate::{rgb::PackedRgba, Srgba};
228
229    use super::{AsUints, AsUintsMut, UintsAs, UintsAsMut};
230
231    #[test]
232    fn as_uints() {
233        let slice: &[PackedRgba] = &[Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
234        let slice_mut: &mut [PackedRgba] =
235            &mut [Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
236        let mut slice_box: Box<[PackedRgba]> =
237            vec![Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()].into_boxed_slice();
238        let mut vec: Vec<PackedRgba> =
239            vec![Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
240        let mut array: [PackedRgba; 2] =
241            [Srgba::new(1, 2, 3, 4).into(), Srgba::new(5, 6, 7, 8).into()];
242
243        let _: &[u32] = slice.as_uints();
244        let _: &[u32] = slice_box.as_uints();
245        let _: &[u32] = vec.as_uints();
246        let _: &[u32] = array.as_uints();
247
248        let _: &mut [u32] = slice_mut.as_uints_mut();
249        let _: &mut [u32] = slice_box.as_uints_mut();
250        let _: &mut [u32] = vec.as_uints_mut();
251        let _: &mut [u32] = array.as_uints_mut();
252    }
253
254    #[test]
255    fn uints_as() {
256        let slice: &[u32] = &[0x01020304, 0x05060708];
257        let slice_mut: &mut [u32] = &mut [0x01020304, 0x05060708];
258        let mut slice_box: Box<[u32]> = vec![0x01020304, 0x05060708].into_boxed_slice();
259        let mut vec: Vec<u32> = vec![0x01020304, 0x05060708];
260        let mut array: [u32; 2] = [0x01020304, 0x05060708];
261
262        let _: &[PackedRgba] = slice.uints_as();
263        let _: &[PackedRgba] = slice_box.uints_as();
264        let _: &[PackedRgba] = vec.uints_as();
265        let _: &[PackedRgba] = array.uints_as();
266
267        let _: &mut [PackedRgba] = slice_mut.uints_as_mut();
268        let _: &mut [PackedRgba] = slice_box.uints_as_mut();
269        let _: &mut [PackedRgba] = vec.uints_as_mut();
270        let _: &mut [PackedRgba] = array.uints_as_mut();
271    }
272}