1 use std::{convert::AsRef, convert::TryFrom, result::Result, str::FromStr}; 2 3 #[cfg(feature = "serde")] 4 use serde::{Deserialize, Serialize}; 5 6 /// Represents a color. 7 /// 8 /// # Platform-specific Notes 9 /// 10 /// The following list of 16 base colors are available for almost all terminals (Windows 7 and 8 included). 11 /// 12 /// | Light | Dark | 13 /// | :--| :-- | 14 /// | `Grey` | `Black` | 15 /// | `Red` | `DarkRed` | 16 /// | `Green` | `DarkGreen` | 17 /// | `Yellow` | `DarkYellow` | 18 /// | `Blue` | `DarkBlue` | 19 /// | `Magenta` | `DarkMagenta` | 20 /// | `Cyan` | `DarkCyan` | 21 /// | `White` | `DarkWhite` | 22 /// 23 /// Most UNIX terminals and Windows 10 consoles support additional colors. 24 /// See [`Color::Rgb`](enum.Color.html#variant.Rgb) or [`Color::AnsiValue`](enum.Color.html#variant.AnsiValue) for 25 /// more info. 26 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] 27 #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] 28 pub enum Color { 29 /// Resets the terminal color. 30 Reset, 31 32 /// Black color. 33 Black, 34 35 /// Dark grey color. 36 DarkGrey, 37 38 /// Light red color. 39 Red, 40 41 /// Dark red color. 42 DarkRed, 43 44 /// Light green color. 45 Green, 46 47 /// Dark green color. 48 DarkGreen, 49 50 /// Light yellow color. 51 Yellow, 52 53 /// Dark yellow color. 54 DarkYellow, 55 56 /// Light blue color. 57 Blue, 58 59 /// Dark blue color. 60 DarkBlue, 61 62 /// Light magenta color. 63 Magenta, 64 65 /// Dark magenta color. 66 DarkMagenta, 67 68 /// Light cyan color. 69 Cyan, 70 71 /// Dark cyan color. 72 DarkCyan, 73 74 /// White color. 75 White, 76 77 /// Grey color. 78 Grey, 79 80 /// An RGB color. See [RGB color model](https://en.wikipedia.org/wiki/RGB_color_model) for more info. 81 /// 82 /// Most UNIX terminals and Windows 10 supported only. 83 /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info. 84 Rgb { r: u8, g: u8, b: u8 }, 85 86 /// An ANSI color. See [256 colors - cheat sheet](https://jonasjacek.github.io/colors/) for more info. 87 /// 88 /// Most UNIX terminals and Windows 10 supported only. 89 /// See [Platform-specific notes](enum.Color.html#platform-specific-notes) for more info. 90 AnsiValue(u8), 91 } 92 93 impl TryFrom<&str> for Color { 94 type Error = (); 95 96 /// Try to create a `Color` from the string representation. This returns an error if the string does not match. try_from(src: &str) -> Result<Self, Self::Error>97 fn try_from(src: &str) -> Result<Self, Self::Error> { 98 let src = src.to_lowercase(); 99 100 match src.as_ref() { 101 "black" => Ok(Color::Black), 102 "dark_grey" => Ok(Color::DarkGrey), 103 "red" => Ok(Color::Red), 104 "dark_red" => Ok(Color::DarkRed), 105 "green" => Ok(Color::Green), 106 "dark_green" => Ok(Color::DarkGreen), 107 "yellow" => Ok(Color::Yellow), 108 "dark_yellow" => Ok(Color::DarkYellow), 109 "blue" => Ok(Color::Blue), 110 "dark_blue" => Ok(Color::DarkBlue), 111 "magenta" => Ok(Color::Magenta), 112 "dark_magenta" => Ok(Color::DarkMagenta), 113 "cyan" => Ok(Color::Cyan), 114 "dark_cyan" => Ok(Color::DarkCyan), 115 "white" => Ok(Color::White), 116 "grey" => Ok(Color::Grey), 117 _ => Err(()), 118 } 119 } 120 } 121 122 impl FromStr for Color { 123 type Err = (); 124 125 /// Creates a `Color` from the string representation. 126 /// 127 /// # Notes 128 /// 129 /// * Returns `Color::White` in case of an unknown color. 130 /// * Does not return `Err` and you can safely unwrap. from_str(src: &str) -> Result<Self, Self::Err>131 fn from_str(src: &str) -> Result<Self, Self::Err> { 132 Ok(Color::try_from(src).unwrap_or(Color::White)) 133 } 134 } 135 136 impl From<(u8, u8, u8)> for Color { 137 /// Creates a 'Color' from the tuple representation. from(val: (u8, u8, u8)) -> Self138 fn from(val: (u8, u8, u8)) -> Self { 139 let (r, g, b) = val; 140 Self::Rgb { r, g, b } 141 } 142 } 143 144 #[cfg(test)] 145 mod tests { 146 use super::Color; 147 148 #[test] test_known_color_conversion()149 fn test_known_color_conversion() { 150 assert_eq!("black".parse(), Ok(Color::Black)); 151 assert_eq!("dark_grey".parse(), Ok(Color::DarkGrey)); 152 assert_eq!("red".parse(), Ok(Color::Red)); 153 assert_eq!("dark_red".parse(), Ok(Color::DarkRed)); 154 assert_eq!("green".parse(), Ok(Color::Green)); 155 assert_eq!("dark_green".parse(), Ok(Color::DarkGreen)); 156 assert_eq!("yellow".parse(), Ok(Color::Yellow)); 157 assert_eq!("dark_yellow".parse(), Ok(Color::DarkYellow)); 158 assert_eq!("blue".parse(), Ok(Color::Blue)); 159 assert_eq!("dark_blue".parse(), Ok(Color::DarkBlue)); 160 assert_eq!("magenta".parse(), Ok(Color::Magenta)); 161 assert_eq!("dark_magenta".parse(), Ok(Color::DarkMagenta)); 162 assert_eq!("cyan".parse(), Ok(Color::Cyan)); 163 assert_eq!("dark_cyan".parse(), Ok(Color::DarkCyan)); 164 assert_eq!("white".parse(), Ok(Color::White)); 165 assert_eq!("grey".parse(), Ok(Color::Grey)); 166 } 167 168 #[test] test_unknown_color_conversion_yields_white()169 fn test_unknown_color_conversion_yields_white() { 170 assert_eq!("foo".parse(), Ok(Color::White)); 171 } 172 173 #[test] test_know_rgb_color_conversion()174 fn test_know_rgb_color_conversion() { 175 assert_eq!(Color::from((0, 0, 0)), Color::Rgb { r: 0, g: 0, b: 0 }); 176 assert_eq!( 177 Color::from((255, 255, 255)), 178 Color::Rgb { 179 r: 255, 180 g: 255, 181 b: 255 182 } 183 ); 184 } 185 } 186