nsys-color-utils 0.2.2

Color utilities
Documentation
//! Color primitives

use derive_more::{From, TryInto};
use crate::constants::*;
use crate::{RGB8, RGBA8};

#[derive(Clone, Copy, Debug, Eq, PartialEq, From, TryInto)]
pub enum Color {
  Named (Named),
  Raw   (RGBA8)
}

impl_newtype!{
  Named { Monochrome, Hue }
}
impl_newtype!{
  Terminal { Monochrome, Primary, Secondary }
}
impl_newtype!{
  Hue { Primary, Secondary, Tertiary }
}

impl_primitive!{
  Monochrome {
    Black => BLACK,
    White => WHITE,
    Grey  => GREY
  }
}
impl_primitive!{
  Primary {
    Red   => RED,
    Green => GREEN,
    Blue  => BLUE
  }
}
impl_primitive!{
  Secondary {
    Cyan    => CYAN,
    Yellow  => YELLOW,
    Magenta => MAGENTA
  }
}
impl_primitive!{
  Tertiary {
    Azure      => AZURE,
    Viridian   => VIRIDIAN,
    Chartreuse => CHARTREUSE,
    Orange     => ORANGE,
    Rose       => ROSE,
    Violet     => VIOLET
  }
}

impl Color {
  pub const BLACK   : Self = Color::Named (Named::Monochrome (Monochrome::Black));
  pub const WHITE   : Self = Color::Named (Named::Monochrome (Monochrome::White));
  pub const GREY    : Self = Color::Named (Named::Monochrome (Monochrome::Grey));
  pub const RED     : Self = Color::Named (Named::Hue (Hue::Primary (Primary::Red)));
  pub const GREEN   : Self = Color::Named (Named::Hue (Hue::Primary (Primary::Green)));
  pub const BLUE    : Self = Color::Named (Named::Hue (Hue::Primary (Primary::Blue)));
  pub const CYAN        : Self =
    Color::Named (Named::Hue (Hue::Secondary (Secondary::Cyan)));
  pub const MAGENTA     : Self =
    Color::Named (Named::Hue (Hue::Secondary (Secondary::Magenta)));
  pub const YELLOW      : Self =
    Color::Named (Named::Hue (Hue::Secondary (Secondary::Yellow)));
  pub const AZURE       : Self =
    Color::Named (Named::Hue (Hue::Tertiary (Tertiary::Azure)));
  pub const VIRIDIAN    : Self =
    Color::Named (Named::Hue (Hue::Tertiary (Tertiary::Viridian)));
  pub const CHARTREUSE  : Self =
    Color::Named (Named::Hue (Hue::Tertiary (Tertiary::Chartreuse)));
  pub const ORANGE      : Self =
    Color::Named (Named::Hue (Hue::Tertiary (Tertiary::Orange)));
  pub const ROSE        : Self =
    Color::Named (Named::Hue (Hue::Tertiary (Tertiary::Rose)));
  pub const VIOLET      : Self =
    Color::Named (Named::Hue (Hue::Tertiary (Tertiary::Violet)));
  pub const TRANSPARENT : Self = Color::Raw (RGBA8::new (0, 0, 0, 0));

  pub fn raw (&self) -> RGBA8 {
    match self {
      Color::Named (named) => (*named).into(),
      Color::Raw   (raw)   => *raw
    }
  }

  pub const fn named (&self) -> Option <Named> {
    match self {
      Color::Named (named) => Some (*named),
      Color::Raw   (_)     => None
    }
  }
}

impl From <RGB8> for Color {
  fn from (rgb : RGB8) -> Self {
    Color::Raw (rgb.into())
  }
}

macro impl_primitive {
  ( $primitive:ident {
      $($color:ident => $value:ident),+
    }
  ) => {
    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    pub enum $primitive {
      $($color),+
    }
    impl From <$primitive> for RGBA8 {
      fn from (primitive : $primitive) -> RGBA8 {
        use $crate::WithAlphaOpaque;
        match primitive {
          $($primitive::$color => $value.rgba()),+
        }
      }
    }
  }
}

macro impl_newtype {
  ( $newtype:ident {
      $($colors:ident),+
    }
  ) => {
    #[derive(Clone, Copy, Debug, Eq, PartialEq, From, TryInto)]
    pub enum $newtype {
      $($colors ($colors)),+
    }
    impl From <$newtype> for RGBA8 {
      fn from (newtype : $newtype) -> RGBA8 {
        match newtype {
          $($newtype::$colors (colors) => colors.into()),+
        }
      }
    }
  }
}