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}