use serde::de::{self, Unexpected, Visitor}; use std::fmt; use std::marker::PhantomData; use termion::color; #[derive(Debug)] pub struct Color(Box); unsafe impl Sync for Color {} unsafe impl Send for Color {} impl Color { pub fn new(c: C) -> Self { Color(Box::new(c)) } } impl PartialEq for Color { fn eq(&self, other: &Self) -> bool { format!("{}{}", color::Fg(self), color::Bg(self)) == format!("{}{}", color::Fg(other), color::Bg(other)) } } impl Eq for Color {} impl color::Color for Color { fn write_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.write_fg(f) } fn write_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.write_bg(f) } } impl<'a> color::Color for &'a Color { fn write_fg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.write_fg(f) } fn write_bg(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.write_bg(f) } } impl Default for Color { fn default() -> Self { Color::new(color::Reset) } } pub struct ColorVisitor { marker: PhantomData Color>, } impl ColorVisitor { fn new() -> Self { ColorVisitor { marker: PhantomData, } } } impl<'de> Visitor<'de> for ColorVisitor { type Value = Color; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("A color") } fn visit_str(self, v: &str) -> Result where E: de::Error, { match v.to_lowercase().as_ref() { "black" => Ok(Color(Box::new(color::Black))), "blue" => Ok(Color(Box::new(color::Blue))), "cyan" => Ok(Color(Box::new(color::Cyan))), "green" => Ok(Color(Box::new(color::Green))), "light black" | "light_black" => { Ok(Color(Box::new(color::LightBlack))) } "light blue" | "light_blue" => { Ok(Color(Box::new(color::LightBlue))) } "light cyan" | "light_cyan" => { Ok(Color(Box::new(color::LightCyan))) } "light green" | "light_green" => { Ok(Color(Box::new(color::LightGreen))) } "light magenta" | "light_magenta" => { Ok(Color(Box::new(color::LightMagenta))) } "light red" | "light_red" => Ok(Color(Box::new(color::LightRed))), "light white" | "light_white" => { Ok(Color(Box::new(color::LightWhite))) } "light yellow" | "light_yellow" => { Ok(Color(Box::new(color::LightYellow))) } "magenta" => Ok(Color(Box::new(color::Magenta))), "red" => Ok(Color(Box::new(color::Red))), "white" => Ok(Color(Box::new(color::White))), "yellow" => Ok(Color(Box::new(color::Yellow))), _ => Err(de::Error::invalid_value( Unexpected::Str(v), &"a valid color", )), } } fn visit_map(self, mut map: A) -> Result where A: de::MapAccess<'de>, { let mut red = None; let mut green = None; let mut blue = None; while let Some((k, v)) = map.next_entry()? { match k { "red" => { red = Some(v); } "green" => { green = Some(v); } "blue" => { blue = Some(v); } _ => { return Err(de::Error::unknown_field( k, &["red", "green", "blue"], )); } } } match (red, green, blue) { (Some(r), Some(g), Some(b)) => { Ok(Color(Box::new(color::Rgb(r, g, b)))) } (None, _, _) => Err(de::Error::missing_field("red")), (_, None, _) => Err(de::Error::missing_field("green")), (_, _, None) => Err(de::Error::missing_field("blue")), } } fn visit_u8(self, v: u8) -> Result { Ok(Color(Box::new(color::AnsiValue(v)))) } } impl<'de> serde::Deserialize<'de> for Color { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_any(ColorVisitor::new()) } }