gem 0.1.0

Color representations and conversions
use crate::{
    alpha::{AlphaFirst, AlphaLast},
    rgb::{HasBlue, HasGreen, HasRed},
};

impl<A, C> HasRed for AlphaFirst<A, C>
where
    A: Copy,
    C: Copy + HasRed,
{
    type Component = C::Component;

    fn red(&self) -> Self::Component {
        self.color().red()
    }

    fn set_red(&mut self, value: Self::Component) {
        *self = Self::with_color(self.alpha(), self.color().with_red(value));
    }
}

impl<A, C> HasGreen for AlphaFirst<A, C>
where
    A: Copy,
    C: Copy + HasGreen,
{
    type Component = C::Component;

    fn green(&self) -> Self::Component {
        self.color().green()
    }

    fn set_green(&mut self, value: Self::Component) {
        *self = Self::with_color(self.alpha(), self.color().with_green(value));
    }
}

impl<A, C> HasBlue for AlphaFirst<A, C>
where
    A: Copy,
    C: Copy + HasBlue,
{
    type Component = C::Component;

    fn blue(&self) -> Self::Component {
        self.color().blue()
    }

    fn set_blue(&mut self, value: Self::Component) {
        *self = Self::with_color(self.alpha(), self.color().with_blue(value));
    }
}

impl<A, C> HasRed for AlphaLast<A, C>
where
    A: Copy,
    C: Copy + HasRed,
{
    type Component = C::Component;

    fn red(&self) -> Self::Component {
        self.color().red()
    }

    fn set_red(&mut self, value: Self::Component) {
        *self = Self::with_color(self.alpha(), self.color().with_red(value));
    }
}

impl<A, C> HasGreen for AlphaLast<A, C>
where
    A: Copy,
    C: Copy + HasGreen,
{
    type Component = C::Component;

    fn green(&self) -> Self::Component {
        self.color().green()
    }

    fn set_green(&mut self, value: Self::Component) {
        *self = Self::with_color(self.alpha(), self.color().with_green(value));
    }
}

impl<A, C> HasBlue for AlphaLast<A, C>
where
    A: Copy,
    C: Copy + HasBlue,
{
    type Component = C::Component;

    fn blue(&self) -> Self::Component {
        self.color().blue()
    }

    fn set_blue(&mut self, value: Self::Component) {
        *self = Self::with_color(self.alpha(), self.color().with_blue(value));
    }
}

// An alpha wrapper's RGB channel range is entirely determined by its inner
// color; alpha itself has no bearing on `Srgb` conversion.
impl<A, C> crate::space::RgbChannelScale for AlphaFirst<A, C>
where
    A: Copy + Default,
    C: Copy + crate::space::RgbChannelScale,
{
    const RED_MAX: f32 = C::RED_MAX;
    const GREEN_MAX: f32 = C::GREEN_MAX;
    const BLUE_MAX: f32 = C::BLUE_MAX;
}

impl<A, C> From<crate::space::Srgb> for AlphaFirst<A, C>
where
    A: Copy + Default,
    C: Copy + crate::space::RgbChannelScale,
    <C as HasRed>::Component: crate::space::Channel,
    <C as HasGreen>::Component: crate::space::Channel,
    <C as HasBlue>::Component: crate::space::Channel,
{
    fn from(c: crate::space::Srgb) -> Self {
        crate::space::FromSrgb::from_srgb(c)
    }
}

impl<A, C> crate::space::RgbChannelScale for AlphaLast<A, C>
where
    A: Copy + Default,
    C: Copy + crate::space::RgbChannelScale,
{
    const RED_MAX: f32 = C::RED_MAX;
    const GREEN_MAX: f32 = C::GREEN_MAX;
    const BLUE_MAX: f32 = C::BLUE_MAX;
}

impl<A, C> From<crate::space::Srgb> for AlphaLast<A, C>
where
    A: Copy + Default,
    C: Copy + crate::space::RgbChannelScale,
    <C as HasRed>::Component: crate::space::Channel,
    <C as HasGreen>::Component: crate::space::Channel,
    <C as HasBlue>::Component: crate::space::Channel,
{
    fn from(c: crate::space::Srgb) -> Self {
        crate::space::FromSrgb::from_srgb(c)
    }
}

#[cfg(test)]
mod tests {
    use crate::rgb::Rgb888;

    use super::*;

    #[test]
    fn alpha_first_set_red() {
        let mut color = AlphaFirst::<u8, Rgb888>::with_color(255, Rgb888::from_rgb(0, 0, 0));
        color.set_red(128);
        assert_eq!(color.red(), 128);
    }

    #[test]
    fn alpha_first_set_green() {
        let mut color = AlphaFirst::<u8, Rgb888>::with_color(255, Rgb888::from_rgb(0, 0, 0));
        color.set_green(128);
        assert_eq!(color.green(), 128);
    }

    #[test]
    fn alpha_first_set_blue() {
        let mut color = AlphaFirst::<u8, Rgb888>::with_color(255, Rgb888::from_rgb(0, 0, 0));
        color.set_blue(128);
        assert_eq!(color.blue(), 128);
    }

    #[test]
    fn alpha_last_set_red() {
        let mut color = AlphaLast::<u8, Rgb888>::with_color(255, Rgb888::from_rgb(0, 0, 0));
        color.set_red(128);
        assert_eq!(color.red(), 128);
    }

    #[test]
    fn alpha_last_set_green() {
        let mut color = AlphaLast::<u8, Rgb888>::with_color(255, Rgb888::from_rgb(0, 0, 0));
        color.set_green(128);
        assert_eq!(color.green(), 128);
    }

    #[test]
    fn alpha_last_set_blue() {
        let mut color = AlphaLast::<u8, Rgb888>::with_color(255, Rgb888::from_rgb(0, 0, 0));
        color.set_blue(128);
        assert_eq!(color.blue(), 128);
    }
}