quantette/types/
palette.rs

1use crate::LengthOutOfRange;
2use alloc::{borrow::ToOwned, vec::Vec};
3use core::{
4    borrow::{Borrow, BorrowMut},
5    error::Error,
6    fmt::{self, Debug},
7    num::{NonZeroU8, NonZeroU16},
8    ops::{Deref, DerefMut, Index, IndexMut},
9};
10use ref_cast::{RefCastCustom, ref_cast_custom};
11
12/// The error returned when attempting to convert an out of range integer into a [`PaletteSize`].
13#[derive(Debug, Copy, Clone, PartialEq, Eq)]
14pub struct PaletteSizeFromIntError(());
15
16impl fmt::Display for PaletteSizeFromIntError {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.write_str("out of range conversion from integer to palette size")
19    }
20}
21
22impl Error for PaletteSizeFromIntError {}
23
24/// This type is used to specify the number of colors in a palette.
25///
26/// This is a simple new type wrapper around `u16` with the invariant that it must be
27/// in the range `1..=256` specified by [`PaletteSize::MIN`] and [`PaletteSize::MAX`].
28///
29/// # Examples
30///
31/// A [`PaletteSize`] can be created from a `u8`, `u16`, `usize`, [`NonZeroU8`], or [`NonZeroU16`].
32/// To do so, use either:
33/// - The clamping functions like [`from_usize_clamped`](`PaletteSize::from_usize_clamped`).
34/// - The `TryFrom` trait implementations for [`PaletteSize`].
35///   - There are also `const` compatible functions like [`try_from_u16`](PaletteSize::try_from_u16).
36///
37/// You can also use the [`PaletteSize::MIN`] or [`PaletteSize::MAX`] constants.
38///
39/// ```
40/// # use core::num::{NonZeroU16, NonZeroU8};
41/// # use quantette::{PaletteSize, PaletteSizeFromIntError};
42/// # fn main() -> Result<(), PaletteSizeFromIntError> {
43/// let size: PaletteSize = 64u16.try_into()?;
44/// assert_eq!(size, 64u16);
45/// assert_eq!(PaletteSize::try_from(16usize)?, 16usize);
46/// assert_eq!(PaletteSize::try_from_u16(256), Some(PaletteSize::MAX));
47/// assert_eq!(PaletteSize::try_from_u16(1024), None);
48/// assert_eq!(PaletteSize::from_u16_clamped(1024), PaletteSize::MAX);
49/// assert_eq!(PaletteSize::from_nz_u8(NonZeroU8::MIN), PaletteSize::MIN);
50/// # Ok(())
51/// # }
52/// ```
53#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
54#[repr(transparent)]
55pub struct PaletteSize(NonZeroU16);
56
57impl PaletteSize {
58    /// The smallest possible palette size, which is `1`.
59    pub const MIN: Self = Self(NonZeroU16::MIN);
60
61    /// The largest possible palette size, which is `256`.
62    pub const MAX: Self = Self(NonZeroU16::new(u8::MAX as u16 + 1).unwrap());
63
64    /// Returns a [`PaletteSize`] as a [`NonZeroU16`].
65    #[inline]
66    pub const fn as_nz_u16(&self) -> NonZeroU16 {
67        self.0
68    }
69
70    /// Returns a [`PaletteSize`] as a `u16`.
71    #[inline]
72    pub const fn as_u16(&self) -> u16 {
73        self.as_nz_u16().get()
74    }
75
76    /// Returns a [`PaletteSize`] as a `usize`.
77    #[inline]
78    pub const fn as_usize(&self) -> usize {
79        self.as_u16() as usize
80    }
81
82    /// Create a [`PaletteSize`] directly from the given [`NonZeroU16`]
83    /// without ensuring that it is less than or equal to [`PaletteSize::MAX`].
84    #[inline]
85    const fn new_unchecked(value: NonZeroU16) -> Self {
86        debug_assert!(value.get() <= Self::MAX.as_u16());
87        Self(value)
88    }
89
90    /// Create a [`PaletteSize`] from a [`NonZeroU16`], returning `None` if the provided `value`
91    /// is greater than [`PaletteSize::MAX`].
92    #[must_use]
93    #[inline]
94    pub const fn try_from_nz_u16(value: NonZeroU16) -> Option<Self> {
95        if value.get() <= Self::MAX.as_u16() {
96            Some(Self::new_unchecked(value))
97        } else {
98            None
99        }
100    }
101
102    /// Create a [`PaletteSize`] from a `u16`, returning `None` if the provided `value`
103    /// is less than [`PaletteSize::MIN`] or greater than [`PaletteSize::MAX`].
104    #[must_use]
105    #[inline]
106    pub const fn try_from_u16(value: u16) -> Option<Self> {
107        if let Some(len) = NonZeroU16::new(value) {
108            Self::try_from_nz_u16(len)
109        } else {
110            None
111        }
112    }
113
114    /// Create a [`PaletteSize`] from a `usize`, returning `None` if the provided `value`
115    /// is less than [`PaletteSize::MIN`] or greater than [`PaletteSize::MAX`].
116    #[must_use]
117    #[inline]
118    pub const fn try_from_usize(value: usize) -> Option<Self> {
119        if value <= Self::MAX.as_usize() {
120            #[allow(clippy::cast_possible_truncation)]
121            if let Some(len) = NonZeroU16::new(value as u16) {
122                Some(Self::new_unchecked(len))
123            } else {
124                None
125            }
126        } else {
127            None
128        }
129    }
130
131    /// Create a [`PaletteSize`] from a [`NonZeroU16`], clamping the provided `value` to
132    /// a maximum of [`PaletteSize::MAX`].
133    #[must_use]
134    #[inline]
135    pub const fn from_nz_u16_clamped(value: NonZeroU16) -> Self {
136        if let Some(size) = Self::try_from_nz_u16(value) {
137            size
138        } else {
139            Self::MAX
140        }
141    }
142
143    /// Create a [`PaletteSize`] from a `u16`, clamping the provided `value` to
144    /// the range specified by [`PaletteSize::MIN`] and [`PaletteSize::MAX`].
145    #[must_use]
146    #[inline]
147    pub const fn from_u16_clamped(value: u16) -> Self {
148        if let Some(len) = NonZeroU16::new(value) {
149            Self::from_nz_u16_clamped(len)
150        } else {
151            Self::MIN
152        }
153    }
154
155    /// Create a [`PaletteSize`] from a `usize`, clamping the provided `value` to
156    /// the range specified by [`PaletteSize::MIN`] and [`PaletteSize::MAX`].
157    #[must_use]
158    #[inline]
159    pub const fn from_usize_clamped(value: usize) -> Self {
160        if value <= Self::MAX.as_usize() {
161            #[allow(clippy::cast_possible_truncation)]
162            if let Some(len) = NonZeroU16::new(value as u16) {
163                Self::new_unchecked(len)
164            } else {
165                Self::MIN
166            }
167        } else {
168            Self::MAX
169        }
170    }
171
172    /// Create a [`PaletteSize`] from a `u8`, returning `None` if the provided `value`
173    /// is less than [`PaletteSize::MIN`].
174    #[must_use]
175    #[inline]
176    pub const fn try_from_u8(value: u8) -> Option<Self> {
177        if let Some(len) = NonZeroU8::new(value) {
178            Some(Self::from_nz_u8(len))
179        } else {
180            None
181        }
182    }
183
184    /// Create a [`PaletteSize`] from a [`NonZeroU8`].
185    #[allow(clippy::expect_used, clippy::missing_panics_doc)] // compiler removes the `expect` with opt_level=3
186    #[must_use]
187    #[inline]
188    pub const fn from_nz_u8(len: NonZeroU8) -> Self {
189        Self::new_unchecked(
190            NonZeroU16::new(len.get() as u16).expect("nonzero u8 to be nonzero u16"),
191        )
192    }
193
194    /// Create a [`PaletteSize`] from a `u8`, clamping the provided `value` to
195    /// a minimum of [`PaletteSize::MIN`].
196    #[must_use]
197    #[inline]
198    pub const fn from_u8_clamped(len: u8) -> Self {
199        if let Some(size) = Self::try_from_u8(len) {
200            size
201        } else {
202            Self::MIN
203        }
204    }
205}
206
207impl From<PaletteSize> for NonZeroU16 {
208    #[inline]
209    fn from(size: PaletteSize) -> Self {
210        size.as_nz_u16()
211    }
212}
213
214impl From<PaletteSize> for u16 {
215    #[inline]
216    fn from(size: PaletteSize) -> Self {
217        size.as_u16()
218    }
219}
220
221impl From<PaletteSize> for usize {
222    #[inline]
223    fn from(size: PaletteSize) -> Self {
224        size.as_usize()
225    }
226}
227
228impl TryFrom<NonZeroU16> for PaletteSize {
229    type Error = PaletteSizeFromIntError;
230
231    #[inline]
232    fn try_from(value: NonZeroU16) -> Result<Self, Self::Error> {
233        Self::try_from_nz_u16(value).ok_or(PaletteSizeFromIntError(()))
234    }
235}
236
237impl TryFrom<u16> for PaletteSize {
238    type Error = PaletteSizeFromIntError;
239
240    #[inline]
241    fn try_from(value: u16) -> Result<Self, Self::Error> {
242        Self::try_from_u16(value).ok_or(PaletteSizeFromIntError(()))
243    }
244}
245
246impl TryFrom<usize> for PaletteSize {
247    type Error = PaletteSizeFromIntError;
248
249    #[inline]
250    fn try_from(value: usize) -> Result<Self, Self::Error> {
251        Self::try_from_usize(value).ok_or(PaletteSizeFromIntError(()))
252    }
253}
254
255impl From<NonZeroU8> for PaletteSize {
256    #[inline]
257    fn from(value: NonZeroU8) -> Self {
258        Self::from_nz_u8(value)
259    }
260}
261
262impl TryFrom<u8> for PaletteSize {
263    type Error = PaletteSizeFromIntError;
264
265    #[inline]
266    fn try_from(value: u8) -> Result<Self, Self::Error> {
267        Self::try_from_u8(value).ok_or(PaletteSizeFromIntError(()))
268    }
269}
270
271impl PartialEq<NonZeroU16> for PaletteSize {
272    #[inline]
273    fn eq(&self, other: &NonZeroU16) -> bool {
274        self.as_nz_u16() == *other
275    }
276}
277
278impl PartialEq<PaletteSize> for NonZeroU16 {
279    #[inline]
280    fn eq(&self, other: &PaletteSize) -> bool {
281        *self == other.as_nz_u16()
282    }
283}
284
285impl PartialEq<u16> for PaletteSize {
286    #[inline]
287    fn eq(&self, other: &u16) -> bool {
288        self.as_u16() == *other
289    }
290}
291
292impl PartialEq<PaletteSize> for u16 {
293    #[inline]
294    fn eq(&self, other: &PaletteSize) -> bool {
295        *self == other.as_u16()
296    }
297}
298
299impl PartialEq<usize> for PaletteSize {
300    #[inline]
301    fn eq(&self, other: &usize) -> bool {
302        self.as_usize() == *other
303    }
304}
305
306impl PartialEq<PaletteSize> for usize {
307    #[inline]
308    fn eq(&self, other: &PaletteSize) -> bool {
309        *self == other.as_usize()
310    }
311}
312
313impl fmt::Display for PaletteSize {
314    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
315        let Self(size) = *self;
316        write!(f, "{size}")
317    }
318}
319
320/// A [`Palette`] is a slice with a length in the range `1..=256` specified by
321/// [`Palette::MIN_LEN`] and [`Palette::MAX_LEN`].
322///
323/// This is an unsized type, meaning that it must always be used behind a pointer like `&`.
324/// The owned version of a [`Palette`] is a [`PaletteBuf`].
325///
326/// See also the [`PaletteSize`] struct which is a `u16` in the range `1..=256`.
327///
328/// # Examples
329///
330/// ```
331/// # use quantette::{Palette, LengthOutOfRange};
332/// # use palette::Srgb;
333/// # fn main() -> Result<(), LengthOutOfRange> {
334/// let mut data = vec![Srgb::new(0, 0, 0)];
335/// let palette = Palette::new(&data)?;
336/// assert_eq!(&data, palette);
337///
338/// let len = palette.len();
339/// let size = palette.size();
340/// assert_eq!(len, size);
341///
342/// let first = palette[0u8];
343/// assert_eq!(first, Srgb::new(0, 0, 0));
344/// # Ok(())
345/// # }
346/// ```
347#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RefCastCustom)]
348#[repr(transparent)]
349pub struct Palette<T>([T]);
350
351impl<T> Palette<T> {
352    /// The maximum length of a [`Palette`], which is 256.
353    pub const MAX_LENGTH: u16 = PaletteSize::MAX.as_u16();
354    /// The maximum length of a [`Palette`], which is 256.
355    pub const MAX_LEN: usize = Self::MAX_LENGTH as usize;
356
357    /// The minimum length of a [`Palette`], which is 1.
358    pub const MIN_LENGTH: u16 = PaletteSize::MIN.as_u16();
359    /// The minimum length of a [`Palette`], which is 1.
360    pub const MIN_LEN: usize = Self::MIN_LENGTH as usize;
361
362    /// Create a [`Palette`] without validating any invariants.
363    #[inline]
364    pub(crate) const fn new_unchecked(slice: &[T]) -> &Palette<T> {
365        #[ref_cast_custom]
366        #[inline]
367        const fn cast<T>(slice: &[T]) -> &Palette<T>;
368
369        debug_assert!(Self::MIN_LEN <= slice.len() && slice.len() <= Self::MAX_LEN);
370        cast(slice)
371    }
372
373    /// Create a new [`Palette`] reference from a slice.
374    ///
375    /// # Errors
376    ///
377    /// Returns an error if the length of `slice` is not in the range `1..=256` specified by
378    /// [`Palette::MIN_LEN`] and [`Palette::MAX_LEN`].
379    #[inline]
380    pub const fn new(slice: &[T]) -> Result<&Self, LengthOutOfRange> {
381        match LengthOutOfRange::check_u16(slice, Self::MIN_LENGTH, Self::MAX_LENGTH) {
382            Ok(_) => Ok(Self::new_unchecked(slice)),
383            Err(err) => Err(err),
384        }
385    }
386
387    /// Create a mutable [`Palette`] without validating any invariants.
388    #[inline]
389    pub(crate) const fn new_mut_unchecked(slice: &mut [T]) -> &mut Palette<T> {
390        #[ref_cast_custom]
391        #[inline]
392        const fn cast_mut<T>(slice: &mut [T]) -> &mut Palette<T>;
393
394        debug_assert!(Self::MIN_LEN <= slice.len() && slice.len() <= Self::MAX_LEN);
395        cast_mut(slice)
396    }
397
398    /// Create a new mutable [`Palette`] reference from a mutable slice.
399    ///
400    /// # Errors
401    ///
402    /// Returns an error if the length of `slice` is not in the range `1..=256` specified by
403    /// [`Palette::MIN_LEN`] and [`Palette::MAX_LEN`].
404    #[inline]
405    pub const fn new_mut(slice: &mut [T]) -> Result<&mut Self, LengthOutOfRange> {
406        match LengthOutOfRange::check_u16(slice, Self::MIN_LENGTH, Self::MAX_LENGTH) {
407            Ok(_) => Ok(Self::new_mut_unchecked(slice)),
408            Err(err) => Err(err),
409        }
410    }
411
412    /// Create a [`Palette`] from an array.
413    ///
414    /// This function will cause a compile error if the length of the array is not in the range
415    /// `1..=256` specified by [`Palette::MIN_LEN`] and [`Palette::MAX_LEN`].
416    #[inline]
417    pub const fn from_array<const N: usize>(array: &[T; N]) -> &Self {
418        const { assert!(Self::MIN_LEN <= N && N <= Self::MAX_LEN) };
419        Self::new_unchecked(array.as_slice())
420    }
421
422    /// Create a mutable [`Palette`] from a mutable array.
423    ///
424    /// This function will cause a compile error if the length of the array is not in the range
425    /// `1..=256` specified by [`Palette::MIN_LEN`] and [`Palette::MAX_LEN`].
426    #[inline]
427    pub fn from_mut_array<const N: usize>(array: &mut [T; N]) -> &mut Self {
428        const { assert!(Self::MIN_LEN <= N && N <= Self::MAX_LEN) };
429        Self::new_mut_unchecked(array.as_mut_slice())
430    }
431
432    /// Returns the length of a [`Palette`] as a [`PaletteSize`].
433    #[allow(clippy::missing_panics_doc)]
434    #[must_use]
435    #[inline]
436    pub const fn size(&self) -> PaletteSize {
437        let len = self.as_slice().len();
438        debug_assert!(Self::MIN_LEN <= len && len <= Self::MAX_LEN);
439        #[allow(clippy::expect_used, clippy::cast_possible_truncation)]
440        let size = NonZeroU16::new(len as u16).expect("non-empty palette");
441        PaletteSize::new_unchecked(size)
442    }
443
444    /// Convert a [`Palette`] to a slice.
445    #[inline]
446    pub const fn as_slice(&self) -> &[T] {
447        &self.0
448    }
449
450    /// Convert a mutable [`Palette`] to a mutable slice.
451    #[inline]
452    pub const fn as_mut_slice(&mut self) -> &mut [T] {
453        &mut self.0
454    }
455
456    /// Map each [`Palette`] color to a new color to create a new [`PaletteBuf`].
457    #[must_use]
458    #[inline]
459    pub fn map_ref<U>(&self, mapping: impl FnMut(&T) -> U) -> PaletteBuf<U> {
460        PaletteBuf::new_unchecked(self.iter().map(mapping).collect())
461    }
462}
463
464impl<T> Deref for Palette<T> {
465    type Target = [T];
466
467    #[inline]
468    fn deref(&self) -> &Self::Target {
469        self.as_slice()
470    }
471}
472
473impl<T> DerefMut for Palette<T> {
474    #[inline]
475    fn deref_mut(&mut self) -> &mut Self::Target {
476        self.as_mut_slice()
477    }
478}
479
480impl<T> AsRef<[T]> for Palette<T> {
481    #[inline]
482    fn as_ref(&self) -> &[T] {
483        self
484    }
485}
486
487impl<T> AsMut<[T]> for Palette<T> {
488    #[inline]
489    fn as_mut(&mut self) -> &mut [T] {
490        self
491    }
492}
493
494impl<T> Borrow<[T]> for Palette<T> {
495    #[inline]
496    fn borrow(&self) -> &[T] {
497        self
498    }
499}
500
501impl<T> BorrowMut<[T]> for Palette<T> {
502    #[inline]
503    fn borrow_mut(&mut self) -> &mut [T] {
504        self
505    }
506}
507
508impl<T: Clone> ToOwned for Palette<T> {
509    type Owned = PaletteBuf<T>;
510
511    fn to_owned(&self) -> Self::Owned {
512        PaletteBuf::new_unchecked(self.as_slice().to_vec())
513    }
514}
515
516impl<'a, T> TryFrom<&'a [T]> for &'a Palette<T> {
517    type Error = LengthOutOfRange;
518
519    #[inline]
520    fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
521        Palette::new(slice)
522    }
523}
524
525impl<'a, T> TryFrom<&'a mut [T]> for &'a mut Palette<T> {
526    type Error = LengthOutOfRange;
527
528    #[inline]
529    fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
530        Palette::new_mut(slice)
531    }
532}
533
534impl<'a, T> IntoIterator for &'a Palette<T> {
535    type Item = &'a T;
536
537    type IntoIter = <&'a [T] as IntoIterator>::IntoIter;
538
539    #[inline]
540    fn into_iter(self) -> Self::IntoIter {
541        self.as_slice().iter()
542    }
543}
544
545impl<'a, T> IntoIterator for &'a mut Palette<T> {
546    type Item = &'a mut T;
547
548    type IntoIter = <&'a mut [T] as IntoIterator>::IntoIter;
549
550    #[inline]
551    fn into_iter(self) -> Self::IntoIter {
552        self.as_mut_slice().iter_mut()
553    }
554}
555
556impl<T> Index<usize> for Palette<T> {
557    type Output = T;
558
559    #[inline]
560    fn index(&self, index: usize) -> &Self::Output {
561        &self.as_slice()[index]
562    }
563}
564
565impl<T> Index<u8> for Palette<T> {
566    type Output = T;
567
568    #[inline]
569    fn index(&self, index: u8) -> &Self::Output {
570        &self[usize::from(index)]
571    }
572}
573
574impl<T> IndexMut<usize> for Palette<T> {
575    #[inline]
576    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
577        &mut self.as_mut_slice()[index]
578    }
579}
580
581impl<T> IndexMut<u8> for Palette<T> {
582    #[inline]
583    fn index_mut(&mut self, index: u8) -> &mut Self::Output {
584        &mut self[usize::from(index)]
585    }
586}
587
588impl<T, U> PartialEq<Palette<U>> for [T]
589where
590    T: PartialEq<U>,
591{
592    #[inline]
593    fn eq(&self, other: &Palette<U>) -> bool {
594        self == other.as_slice()
595    }
596}
597
598impl<T, U> PartialEq<[U]> for Palette<T>
599where
600    T: PartialEq<U>,
601{
602    #[inline]
603    fn eq(&self, other: &[U]) -> bool {
604        self.as_slice() == other
605    }
606}
607
608impl<T, U> PartialEq<&Palette<U>> for [T]
609where
610    T: PartialEq<U>,
611{
612    #[inline]
613    fn eq(&self, other: &&Palette<U>) -> bool {
614        self == other.as_slice()
615    }
616}
617
618impl<T, U> PartialEq<[U]> for &Palette<T>
619where
620    T: PartialEq<U>,
621{
622    #[inline]
623    fn eq(&self, other: &[U]) -> bool {
624        self.as_slice() == other
625    }
626}
627
628impl<T, U> PartialEq<&mut Palette<U>> for [T]
629where
630    T: PartialEq<U>,
631{
632    #[inline]
633    fn eq(&self, other: &&mut Palette<U>) -> bool {
634        self == other.as_slice()
635    }
636}
637
638impl<T, U> PartialEq<[U]> for &mut Palette<T>
639where
640    T: PartialEq<U>,
641{
642    #[inline]
643    fn eq(&self, other: &[U]) -> bool {
644        self.as_slice() == other
645    }
646}
647
648impl<T, U> PartialEq<Palette<U>> for &[T]
649where
650    T: PartialEq<U>,
651{
652    #[inline]
653    fn eq(&self, other: &Palette<U>) -> bool {
654        *self == other.as_slice()
655    }
656}
657
658impl<T, U> PartialEq<&[U]> for Palette<T>
659where
660    T: PartialEq<U>,
661{
662    #[inline]
663    fn eq(&self, other: &&[U]) -> bool {
664        self.as_slice() == *other
665    }
666}
667
668impl<T, U> PartialEq<Palette<U>> for &mut [T]
669where
670    T: PartialEq<U>,
671{
672    #[inline]
673    fn eq(&self, other: &Palette<U>) -> bool {
674        *self == other.as_slice()
675    }
676}
677
678impl<T, U> PartialEq<&mut [U]> for Palette<T>
679where
680    T: PartialEq<U>,
681{
682    #[inline]
683    fn eq(&self, other: &&mut [U]) -> bool {
684        self.as_slice() == *other
685    }
686}
687
688impl<T, const N: usize, U> PartialEq<Palette<U>> for [T; N]
689where
690    T: PartialEq<U>,
691{
692    #[inline]
693    fn eq(&self, other: &Palette<U>) -> bool {
694        &self[..] == other.as_slice()
695    }
696}
697
698impl<T, U, const N: usize> PartialEq<[U; N]> for Palette<T>
699where
700    T: PartialEq<U>,
701{
702    #[inline]
703    fn eq(&self, other: &[U; N]) -> bool {
704        self.as_slice() == &other[..]
705    }
706}
707
708impl<T, const N: usize, U> PartialEq<&Palette<U>> for [T; N]
709where
710    T: PartialEq<U>,
711{
712    #[inline]
713    fn eq(&self, other: &&Palette<U>) -> bool {
714        &self[..] == other.as_slice()
715    }
716}
717
718impl<T, U, const N: usize> PartialEq<[U; N]> for &Palette<T>
719where
720    T: PartialEq<U>,
721{
722    #[inline]
723    fn eq(&self, other: &[U; N]) -> bool {
724        self.as_slice() == &other[..]
725    }
726}
727
728impl<T, const N: usize, U> PartialEq<&mut Palette<U>> for [T; N]
729where
730    T: PartialEq<U>,
731{
732    #[inline]
733    fn eq(&self, other: &&mut Palette<U>) -> bool {
734        &self[..] == other.as_slice()
735    }
736}
737
738impl<T, U, const N: usize> PartialEq<[U; N]> for &mut Palette<T>
739where
740    T: PartialEq<U>,
741{
742    #[inline]
743    fn eq(&self, other: &[U; N]) -> bool {
744        self.as_slice() == &other[..]
745    }
746}
747
748impl<T, U> PartialEq<Palette<U>> for Vec<T>
749where
750    T: PartialEq<U>,
751{
752    #[inline]
753    fn eq(&self, other: &Palette<U>) -> bool {
754        self.as_slice() == other.as_slice()
755    }
756}
757
758impl<T, U> PartialEq<Vec<U>> for Palette<T>
759where
760    T: PartialEq<U>,
761{
762    #[inline]
763    fn eq(&self, other: &Vec<U>) -> bool {
764        self.as_slice() == other.as_slice()
765    }
766}
767
768impl<T, U> PartialEq<&Palette<U>> for Vec<T>
769where
770    T: PartialEq<U>,
771{
772    #[inline]
773    fn eq(&self, other: &&Palette<U>) -> bool {
774        self.as_slice() == other.as_slice()
775    }
776}
777
778impl<T, U> PartialEq<Vec<U>> for &Palette<T>
779where
780    T: PartialEq<U>,
781{
782    #[inline]
783    fn eq(&self, other: &Vec<U>) -> bool {
784        self.as_slice() == other.as_slice()
785    }
786}
787
788impl<T, U> PartialEq<&mut Palette<U>> for Vec<T>
789where
790    T: PartialEq<U>,
791{
792    #[inline]
793    fn eq(&self, other: &&mut Palette<U>) -> bool {
794        self.as_slice() == other.as_slice()
795    }
796}
797
798impl<T, U> PartialEq<Vec<U>> for &mut Palette<T>
799where
800    T: PartialEq<U>,
801{
802    #[inline]
803    fn eq(&self, other: &Vec<U>) -> bool {
804        self.as_slice() == other.as_slice()
805    }
806}
807
808impl<T, U> PartialEq<Palette<U>> for PaletteBuf<T>
809where
810    T: PartialEq<U>,
811{
812    #[inline]
813    fn eq(&self, other: &Palette<U>) -> bool {
814        self.as_slice() == other.as_slice()
815    }
816}
817
818impl<T, U> PartialEq<PaletteBuf<U>> for Palette<T>
819where
820    T: PartialEq<U>,
821{
822    #[inline]
823    fn eq(&self, other: &PaletteBuf<U>) -> bool {
824        self.as_slice() == other.as_slice()
825    }
826}
827
828impl<T, U> PartialEq<&Palette<U>> for PaletteBuf<T>
829where
830    T: PartialEq<U>,
831{
832    #[inline]
833    fn eq(&self, other: &&Palette<U>) -> bool {
834        self.as_slice() == other.as_slice()
835    }
836}
837
838impl<T, U> PartialEq<PaletteBuf<U>> for &Palette<T>
839where
840    T: PartialEq<U>,
841{
842    #[inline]
843    fn eq(&self, other: &PaletteBuf<U>) -> bool {
844        self.as_slice() == other.as_slice()
845    }
846}
847
848impl<T, U> PartialEq<&mut Palette<U>> for PaletteBuf<T>
849where
850    T: PartialEq<U>,
851{
852    #[inline]
853    fn eq(&self, other: &&mut Palette<U>) -> bool {
854        self.as_slice() == other.as_slice()
855    }
856}
857
858impl<T, U> PartialEq<PaletteBuf<U>> for &mut Palette<T>
859where
860    T: PartialEq<U>,
861{
862    #[inline]
863    fn eq(&self, other: &PaletteBuf<U>) -> bool {
864        self.as_slice() == other.as_slice()
865    }
866}
867
868/// The error returned when an [`PaletteBuf`] failed to be created.
869#[derive(Debug, Clone, PartialEq, Eq)]
870pub struct CreatePaletteBufError<T>(Vec<T>);
871
872impl<T> CreatePaletteBufError<T> {
873    /// Returns a slice reference to the [`Vec`] that was used to try and create the [`PaletteBuf`].
874    #[inline]
875    pub fn as_slice(&self) -> &[T] {
876        &self.0
877    }
878
879    /// Returns the [`Vec`] that was used to try and create the [`PaletteBuf`].
880    #[must_use]
881    #[inline]
882    pub fn into_vec(self) -> Vec<T> {
883        self.0
884    }
885}
886
887impl<T> fmt::Display for CreatePaletteBufError<T> {
888    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
889        write!(
890            f,
891            "got an input with length {} which is not in the supported range of {}..={}",
892            self.0.len(),
893            PaletteBuf::<T>::MIN_LENGTH,
894            PaletteBuf::<T>::MAX_LENGTH,
895        )
896    }
897}
898
899impl<T: Debug> Error for CreatePaletteBufError<T> {}
900
901/// A [`PaletteBuf`] is an owned [`Palette`].
902///
903/// That is, an owned slice with a length in the range `1..=256` specified by
904/// [`PaletteBuf::MIN_LEN`] and [`PaletteBuf::MAX_LEN`].
905///
906/// See also the [`PaletteSize`] struct which is a `u16` in the range `1..=256`.
907///
908/// # Examples
909///
910/// ```
911/// # use quantette::{PaletteBuf, CreatePaletteBufError};
912/// # use palette::Srgb;
913/// # fn main() -> Result<(), CreatePaletteBufError<Srgb<u8>>> {
914/// let mut data = vec![Srgb::<u8>::new(0, 0, 0)];
915/// let palette = PaletteBuf::new(data.clone())?;
916/// assert_eq!(data, palette);
917///
918/// let len = palette.len();
919/// let size = palette.size();
920/// assert_eq!(len, size);
921///
922/// let first = palette[0u8];
923/// assert_eq!(first, Srgb::new(0, 0, 0));
924/// # Ok(())
925/// # }
926/// ```
927#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
928#[repr(transparent)]
929pub struct PaletteBuf<T>(Vec<T>);
930
931impl<T> PaletteBuf<T> {
932    /// The maximum length of a [`PaletteBuf`], which is 256.
933    pub const MAX_LENGTH: u16 = PaletteSize::MAX.as_u16();
934    /// The maximum length of a [`PaletteBuf`], which is 256.
935    pub const MAX_LEN: usize = Self::MAX_LENGTH as usize;
936
937    /// The minimum length of a [`PaletteBuf`], which is 1.
938    pub const MIN_LENGTH: u16 = PaletteSize::MIN.as_u16();
939    /// The minimum length of a [`PaletteBuf`], which is 1.
940    pub const MIN_LEN: usize = Self::MIN_LENGTH as usize;
941
942    /// Create a new [`PaletteBuf`] without validating invariants.
943    #[inline]
944    pub(crate) fn new_unchecked(vec: Vec<T>) -> Self {
945        debug_assert!(Self::MIN_LEN <= vec.len() && vec.len() <= Self::MAX_LEN);
946        Self(vec)
947    }
948
949    /// Create a new [`PaletteBuf`] from a [`Vec`].
950    ///
951    /// # Errors
952    ///
953    /// Returns an error if the length of `vec` is not in the range `1..=256` specified by
954    /// [`PaletteBuf::MIN_LEN`] and [`PaletteBuf::MAX_LEN`].
955    #[inline]
956    pub fn new(vec: Vec<T>) -> Result<Self, CreatePaletteBufError<T>> {
957        if Self::MIN_LEN <= vec.len() && vec.len() <= Self::MAX_LEN {
958            Ok(Self::new_unchecked(vec))
959        } else {
960            Err(CreatePaletteBufError(vec))
961        }
962    }
963
964    /// Create a [`PaletteBuf`] from an array.
965    ///
966    /// This function will cause a compile error if the length of the array is not in the range
967    /// `1..=256` specified by [`Palette::MIN_LEN`] and [`Palette::MAX_LEN`].
968    #[must_use]
969    #[inline]
970    pub fn from_array<const N: usize>(array: [T; N]) -> Self {
971        const { assert!(Self::MIN_LEN <= N && N <= Self::MAX_LEN) };
972        Self::new_unchecked(array.into_iter().collect())
973    }
974
975    /// Returns the length of a [`PaletteBuf`] as a [`PaletteSize`].
976    #[must_use]
977    #[inline]
978    pub fn size(&self) -> PaletteSize {
979        self.as_palette().size()
980    }
981
982    /// Convert a [`PaletteBuf`] reference to a slice.
983    #[inline]
984    pub fn as_slice(&self) -> &[T] {
985        &self.0
986    }
987
988    /// Convert a mutable [`PaletteBuf`] reference to a mutable slice.
989    #[inline]
990    pub fn as_mut_slice(&mut self) -> &mut [T] {
991        &mut self.0
992    }
993
994    /// Convert a [`PaletteBuf`] reference to a [`Palette`].
995    #[inline]
996    pub fn as_palette(&self) -> &Palette<T> {
997        Palette::new_unchecked(&self.0)
998    }
999
1000    /// Convert a mutable [`PaletteBuf`] reference to a mutable [`Palette`].
1001    #[inline]
1002    pub fn as_mut_palette(&mut self) -> &mut Palette<T> {
1003        Palette::new_mut_unchecked(&mut self.0)
1004    }
1005
1006    /// Convert a [`PaletteBuf`] to the underlying [`Vec`].
1007    #[must_use]
1008    #[inline]
1009    pub fn into_vec(self) -> Vec<T> {
1010        self.0
1011    }
1012
1013    /// Map each [`PaletteBuf`] color to a new color to create a new [`PaletteBuf`].
1014    ///
1015    /// See [`map_ref`](Palette::map_ref) for a non-consuming alternative.
1016    #[must_use]
1017    #[inline]
1018    pub fn map<U>(self, mapping: impl FnMut(T) -> U) -> PaletteBuf<U> {
1019        PaletteBuf::new_unchecked(self.into_iter().map(mapping).collect())
1020    }
1021
1022    /// Map a [`Palette`] to a new [`PaletteBuf`] by adapting a function that takes a slice as input
1023    /// and returns a [`Vec`] as output.
1024    ///
1025    /// To instead use a function that maps one element at a time, see [`map_ref`](Palette::map_ref)
1026    /// or [`map`](Self::map).
1027    ///
1028    /// # Examples
1029    ///
1030    /// ```
1031    /// # use quantette::{PaletteBuf, CreatePaletteBufError};
1032    /// # use palette::Srgb;
1033    /// # fn main() -> Result<(), CreatePaletteBufError<Srgb<u8>>> {
1034    /// use quantette::color_space::srgb8_to_oklab;
1035    /// let srgb_palette = PaletteBuf::<Srgb<u8>>::new(vec![Srgb::new(0, 0, 0)])?;
1036    /// let oklab_palette = PaletteBuf::from_mapping(&srgb_palette, srgb8_to_oklab);
1037    /// # Ok(())
1038    /// # }
1039    /// ```
1040    ///
1041    /// # Panics
1042    ///
1043    /// Panics if `mapping` returns a [`Vec`] with a different length than the input slice.
1044    #[must_use]
1045    #[inline]
1046    pub fn from_mapping<U>(
1047        palette: &Palette<T>,
1048        mapping: impl FnOnce(&[T]) -> Vec<U>,
1049    ) -> PaletteBuf<U> {
1050        let mapped = mapping(palette);
1051        assert_eq!(palette.len(), mapped.len());
1052        PaletteBuf::new_unchecked(mapped)
1053    }
1054
1055    /// Shorten a [`PaletteBuf`] to `length` number of elements.
1056    ///
1057    /// If `length` is greater than or equal to the [`PaletteBuf`]'s current length,
1058    /// then this has no effect.
1059    #[inline]
1060    pub fn truncate(&mut self, length: PaletteSize) {
1061        self.0.truncate(length.as_usize());
1062    }
1063}
1064
1065impl<T> Deref for PaletteBuf<T> {
1066    type Target = Palette<T>;
1067
1068    #[inline]
1069    fn deref(&self) -> &Self::Target {
1070        self.as_palette()
1071    }
1072}
1073
1074impl<T> DerefMut for PaletteBuf<T> {
1075    #[inline]
1076    fn deref_mut(&mut self) -> &mut Self::Target {
1077        self.as_mut_palette()
1078    }
1079}
1080
1081impl<T> AsRef<[T]> for PaletteBuf<T> {
1082    #[inline]
1083    fn as_ref(&self) -> &[T] {
1084        self
1085    }
1086}
1087
1088impl<T> AsRef<Palette<T>> for PaletteBuf<T> {
1089    #[inline]
1090    fn as_ref(&self) -> &Palette<T> {
1091        self
1092    }
1093}
1094
1095impl<T> AsRef<PaletteBuf<T>> for PaletteBuf<T> {
1096    #[inline]
1097    fn as_ref(&self) -> &PaletteBuf<T> {
1098        self
1099    }
1100}
1101
1102impl<T> AsMut<[T]> for PaletteBuf<T> {
1103    #[inline]
1104    fn as_mut(&mut self) -> &mut [T] {
1105        self
1106    }
1107}
1108
1109impl<T> AsMut<Palette<T>> for PaletteBuf<T> {
1110    #[inline]
1111    fn as_mut(&mut self) -> &mut Palette<T> {
1112        self
1113    }
1114}
1115
1116impl<T> AsMut<PaletteBuf<T>> for PaletteBuf<T> {
1117    #[inline]
1118    fn as_mut(&mut self) -> &mut PaletteBuf<T> {
1119        self
1120    }
1121}
1122
1123impl<T> Borrow<[T]> for PaletteBuf<T> {
1124    #[inline]
1125    fn borrow(&self) -> &[T] {
1126        self
1127    }
1128}
1129
1130impl<T> Borrow<Palette<T>> for PaletteBuf<T> {
1131    #[inline]
1132    fn borrow(&self) -> &Palette<T> {
1133        self
1134    }
1135}
1136
1137impl<T> BorrowMut<[T]> for PaletteBuf<T> {
1138    #[inline]
1139    fn borrow_mut(&mut self) -> &mut [T] {
1140        self
1141    }
1142}
1143
1144impl<T> BorrowMut<Palette<T>> for PaletteBuf<T> {
1145    #[inline]
1146    fn borrow_mut(&mut self) -> &mut Palette<T> {
1147        self
1148    }
1149}
1150
1151impl<T: Clone> From<&Palette<T>> for PaletteBuf<T> {
1152    #[inline]
1153    fn from(palette: &Palette<T>) -> Self {
1154        palette.to_owned()
1155    }
1156}
1157
1158impl<T: Clone> From<&mut Palette<T>> for PaletteBuf<T> {
1159    #[inline]
1160    fn from(palette: &mut Palette<T>) -> Self {
1161        palette.to_owned()
1162    }
1163}
1164
1165impl<T> TryFrom<Vec<T>> for PaletteBuf<T> {
1166    type Error = CreatePaletteBufError<T>;
1167
1168    #[inline]
1169    fn try_from(container: Vec<T>) -> Result<Self, Self::Error> {
1170        Self::new(container)
1171    }
1172}
1173
1174impl<T: Clone> TryFrom<&[T]> for PaletteBuf<T> {
1175    type Error = LengthOutOfRange;
1176
1177    #[inline]
1178    fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
1179        Palette::new(slice).map(Self::from)
1180    }
1181}
1182
1183impl<T: Clone> TryFrom<&mut [T]> for PaletteBuf<T> {
1184    type Error = LengthOutOfRange;
1185
1186    #[inline]
1187    fn try_from(slice: &mut [T]) -> Result<Self, Self::Error> {
1188        Palette::new_mut(slice).map(Self::from)
1189    }
1190}
1191
1192impl<T> IntoIterator for PaletteBuf<T> {
1193    type Item = T;
1194
1195    type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
1196
1197    #[inline]
1198    fn into_iter(self) -> Self::IntoIter {
1199        self.0.into_iter()
1200    }
1201}
1202
1203impl<'a, T> IntoIterator for &'a PaletteBuf<T> {
1204    type Item = &'a T;
1205
1206    type IntoIter = <&'a [T] as IntoIterator>::IntoIter;
1207
1208    #[inline]
1209    fn into_iter(self) -> Self::IntoIter {
1210        self.as_slice().iter()
1211    }
1212}
1213
1214impl<'a, T> IntoIterator for &'a mut PaletteBuf<T> {
1215    type Item = &'a mut T;
1216
1217    type IntoIter = <&'a mut [T] as IntoIterator>::IntoIter;
1218
1219    #[inline]
1220    fn into_iter(self) -> Self::IntoIter {
1221        self.as_mut_slice().iter_mut()
1222    }
1223}
1224
1225impl<T> Index<usize> for PaletteBuf<T> {
1226    type Output = T;
1227
1228    #[inline]
1229    fn index(&self, index: usize) -> &Self::Output {
1230        &self.as_palette()[index]
1231    }
1232}
1233
1234impl<T> Index<u8> for PaletteBuf<T> {
1235    type Output = T;
1236
1237    #[inline]
1238    fn index(&self, index: u8) -> &Self::Output {
1239        &self.as_palette()[index]
1240    }
1241}
1242
1243impl<T> IndexMut<usize> for PaletteBuf<T> {
1244    #[inline]
1245    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1246        &mut self.as_mut_palette()[index]
1247    }
1248}
1249
1250impl<T> IndexMut<u8> for PaletteBuf<T> {
1251    #[inline]
1252    fn index_mut(&mut self, index: u8) -> &mut Self::Output {
1253        &mut self.as_mut_palette()[index]
1254    }
1255}
1256
1257impl<T, U> PartialEq<[U]> for PaletteBuf<T>
1258where
1259    T: PartialEq<U>,
1260{
1261    #[inline]
1262    fn eq(&self, other: &[U]) -> bool {
1263        self.as_slice() == other
1264    }
1265}
1266
1267impl<T, U> PartialEq<PaletteBuf<U>> for [T]
1268where
1269    T: PartialEq<U>,
1270{
1271    #[inline]
1272    fn eq(&self, other: &PaletteBuf<U>) -> bool {
1273        self == other.as_slice()
1274    }
1275}
1276
1277impl<T, U> PartialEq<&[U]> for PaletteBuf<T>
1278where
1279    T: PartialEq<U>,
1280{
1281    #[inline]
1282    fn eq(&self, other: &&[U]) -> bool {
1283        self.as_slice() == *other
1284    }
1285}
1286
1287impl<T, U> PartialEq<PaletteBuf<U>> for &[T]
1288where
1289    T: PartialEq<U>,
1290{
1291    #[inline]
1292    fn eq(&self, other: &PaletteBuf<U>) -> bool {
1293        *self == other.as_slice()
1294    }
1295}
1296
1297impl<T, U> PartialEq<&mut [U]> for PaletteBuf<T>
1298where
1299    T: PartialEq<U>,
1300{
1301    #[inline]
1302    fn eq(&self, other: &&mut [U]) -> bool {
1303        self.as_slice() == *other
1304    }
1305}
1306
1307impl<T, U> PartialEq<PaletteBuf<U>> for &mut [T]
1308where
1309    T: PartialEq<U>,
1310{
1311    #[inline]
1312    fn eq(&self, other: &PaletteBuf<U>) -> bool {
1313        *self == other.as_slice()
1314    }
1315}
1316
1317impl<T, U, const N: usize> PartialEq<[U; N]> for PaletteBuf<T>
1318where
1319    T: PartialEq<U>,
1320{
1321    #[inline]
1322    fn eq(&self, other: &[U; N]) -> bool {
1323        self.as_slice() == &other[..]
1324    }
1325}
1326
1327impl<T, const N: usize, U> PartialEq<PaletteBuf<U>> for [T; N]
1328where
1329    T: PartialEq<U>,
1330{
1331    #[inline]
1332    fn eq(&self, other: &PaletteBuf<U>) -> bool {
1333        &self[..] == other.as_slice()
1334    }
1335}
1336
1337impl<T, U> PartialEq<Vec<U>> for PaletteBuf<T>
1338where
1339    T: PartialEq<U>,
1340{
1341    #[inline]
1342    fn eq(&self, other: &Vec<U>) -> bool {
1343        self.as_slice() == other.as_slice()
1344    }
1345}
1346
1347impl<T, U> PartialEq<PaletteBuf<U>> for Vec<T>
1348where
1349    T: PartialEq<U>,
1350{
1351    #[inline]
1352    fn eq(&self, other: &PaletteBuf<U>) -> bool {
1353        self.as_slice() == other.as_slice()
1354    }
1355}