#[cfg(feature = "serialize")]
#[macro_use]
extern crate serde;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct Rgb24 {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}
impl Rgb24 {
    pub const fn new(r: u8, g: u8, b: u8) -> Self {
        Self { r, g, b }
    }
    pub fn to_f32_rgb(self) -> [f32; 3] {
        [
            self.r as f32 / 255.,
            self.g as f32 / 255.,
            self.b as f32 / 255.,
        ]
    }
    pub fn to_f32_rgba(self, opacity: f32) -> [f32; 4] {
        [
            self.r as f32 / 255.,
            self.g as f32 / 255.,
            self.b as f32 / 255.,
            opacity,
        ]
    }
    pub fn saturating_add(self, other: Self) -> Self {
        Self {
            r: self.r.saturating_add(other.r),
            g: self.g.saturating_add(other.g),
            b: self.b.saturating_add(other.b),
        }
    }
    pub fn saturating_sub(self, other: Self) -> Self {
        Self {
            r: self.r.saturating_sub(other.r),
            g: self.g.saturating_sub(other.g),
            b: self.b.saturating_sub(other.b),
        }
    }
    pub fn saturating_scalar_mul(self, scalar: u32) -> Self {
        fn single_channel(channel: u8, scalar: u32) -> u8 {
            let as_u32 = channel as u32 * scalar;
            as_u32.min(::std::u8::MAX as u32) as u8
        }
        Self {
            r: single_channel(self.r, scalar),
            g: single_channel(self.g, scalar),
            b: single_channel(self.b, scalar),
        }
    }
    pub fn scalar_div(self, scalar: u32) -> Self {
        fn single_channel(channel: u8, scalar: u32) -> u8 {
            let as_u32 = channel as u32 / scalar;
            as_u32.min(::std::u8::MAX as u32) as u8
        }
        Self {
            r: single_channel(self.r, scalar),
            g: single_channel(self.g, scalar),
            b: single_channel(self.b, scalar),
        }
    }
    pub fn saturating_scalar_mul_div(self, numerator: u32, denominator: u32) -> Self {
        fn single_channel(channel: u8, numerator: u32, denominator: u32) -> u8 {
            let as_u32 = ((channel as u32) * (numerator)) / denominator;
            as_u32.min(::std::u8::MAX as u32) as u8
        }
        Self {
            r: single_channel(self.r, numerator, denominator),
            g: single_channel(self.g, numerator, denominator),
            b: single_channel(self.b, numerator, denominator),
        }
    }
}
pub const fn rgb24(r: u8, g: u8, b: u8) -> Rgb24 {
    Rgb24::new(r, g, b)
}
#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn add() {
        let a = rgb24(255, 0, 200);
        let b = rgb24(0, 255, 200);
        let c = a.saturating_add(b);
        assert_eq!(c, rgb24(255, 255, 255));
    }
    #[test]
    fn sub() {
        let a = rgb24(255, 0, 200);
        let b = rgb24(0, 255, 200);
        let c = a.saturating_sub(b);
        assert_eq!(c, rgb24(255, 0, 0));
    }
    #[test]
    fn mul_div() {
        assert_eq!(
            rgb24(1, 2, 3).saturating_scalar_mul_div(1500, 1000),
            rgb24(1, 3, 4)
        );
        assert_eq!(
            rgb24(1, 2, 3).saturating_scalar_mul_div(1500, 1),
            rgb24(255, 255, 255)
        );
    }
    #[test]
    fn mul() {
        assert_eq!(
            rgb24(20, 40, 60).saturating_scalar_mul(2),
            rgb24(40, 80, 120),
        );
        assert_eq!(
            rgb24(20, 40, 60).saturating_scalar_mul(10000),
            rgb24(255, 255, 255),
        );
    }
    #[test]
    fn div() {
        assert_eq!(rgb24(20, 40, 60).scalar_div(2), rgb24(10, 20, 30));
        assert_eq!(rgb24(255, 255, 255).scalar_div(256), rgb24(0, 0, 0));
    }
    #[test]
    #[should_panic]
    fn div_by_zero() {
        rgb24(0, 0, 0).scalar_div(0);
    }
}