1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![feature(test)]
//! # Art
//!
//! A library for modeling artistic concepts.

pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;

extern crate test;
mod tests;

pub mod kinds {
    /// The primary colors according to the RYB color model.
    #[derive(Debug, PartialEq, PartialOrd)]
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }

    /// The secondary colors according to the RYB color model.
    #[derive(Debug, PartialEq)]
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}

pub mod utils {
    use crate::kinds::*;

    /// Combines two primary colors in equal amounts to create
    /// a secondary color.
    pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        if c1 == c2 {
            panic!("That's not possible!");
        }

        let mixture = [c1, c2];

        if mixture.iter().any(|x| *x == PrimaryColor::Red) {
            if mixture.iter().any(|x| *x == PrimaryColor::Blue) {
                return SecondaryColor::Purple;
            } else if mixture.iter().any(|x| *x == PrimaryColor::Yellow) {
                return SecondaryColor::Orange;
            }
        }
        SecondaryColor::Green
    }

    pub fn mix_dumb_arr(mixture: &[PrimaryColor]) -> SecondaryColor {
        use PrimaryColor::*;
        use SecondaryColor::*;

        match mixture {
            [Red, Blue] => Purple,
            [Blue, Red] => Purple,
            [Red, Yellow] => Orange,
            [Yellow, Red] => Orange,
            [Blue, Yellow] => Green,
            [Yellow, Blue] => Green,
            _ => panic!("That's not possible"),
        }
    }

    pub fn mix_dumb(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        use PrimaryColor::*;
        use SecondaryColor::*;

        match [c1, c2] {
            [Red, Blue] => Purple,
            [Blue, Red] => Purple,
            [Red, Yellow] => Orange,
            [Yellow, Red] => Orange,
            [Blue, Yellow] => Green,
            [Yellow, Blue] => Green,
            _ => panic!("That's not possible"),
        }
    }

    pub fn mix_match(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        if c1 == c2 {
            panic!("That's not possible!");
        }

        match (c1, c2) {
            (PrimaryColor::Red, other) | (other, PrimaryColor::Red) => match other {
                PrimaryColor::Blue => SecondaryColor::Purple,
                PrimaryColor::Yellow => SecondaryColor::Orange,
                _ => unreachable!(),
            },
            _ => SecondaryColor::Green,
        }
    }

    pub fn mix_cmp(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        use PrimaryColor::*;
        use SecondaryColor::*;

        match if c1 > c2 { [c2, c1] } else { [c1, c2] } {
            [Red, Blue] => Purple,
            [Red, Yellow] => Orange,
            [Yellow, Blue] => Green,
            _ => panic!("That's not possible!"),
        }
    }

    pub fn mix_u8(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        let mut mix = 0_u8;
        for c in [c1, c2] {
            match c {
                PrimaryColor::Red => mix |= 0x01,
                PrimaryColor::Blue => mix |= 0x02,
                PrimaryColor::Yellow => mix |= 0x04,
            }
        }

        match mix {
            0x03 => SecondaryColor::Purple,
            0x05 => SecondaryColor::Orange,
            0x06 => SecondaryColor::Green,
            _ => panic!("That's not possible!"),
        }
    }
}