From 4e72bd1c7e4081ecb9d739653f583cea58882383 Mon Sep 17 00:00:00 2001 From: Timon Date: Mon, 11 Oct 2021 21:58:14 +0200 Subject: [PATCH] Remove deserialize_any and fix inconsitent serialize format. (#604) --- src/style/types/color.rs | 137 +++++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 55 deletions(-) diff --git a/src/style/types/color.rs b/src/style/types/color.rs index c45c42161..be0bce22a 100644 --- a/src/style/types/color.rs +++ b/src/style/types/color.rs @@ -1,8 +1,5 @@ use std::{convert::AsRef, convert::TryFrom, result::Result, str::FromStr}; -#[cfg(feature = "serde")] -use serde::Serialize; - #[cfg(feature = "serde")] use std::fmt; @@ -27,7 +24,6 @@ use crate::style::parse_next_u8; /// /// Most UNIX terminals and Windows 10 consoles support additional colors. /// See [`Color::Rgb`] or [`Color::AnsiValue`] for more info. -#[cfg_attr(feature = "serde", derive(Serialize))] #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] pub enum Color { /// Resets the terminal color. @@ -217,6 +213,51 @@ impl From<(u8, u8, u8)> for Color { } } +#[cfg(feature = "serde")] +impl serde::ser::Serialize for Color { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + let str = match *self { + Color::Black => "black", + Color::DarkGrey => "dark_grey", + Color::Red => "red", + Color::DarkRed => "dark_red", + Color::Green => "green", + Color::DarkGreen => "dark_green", + Color::Yellow => "yellow", + Color::DarkYellow => "dark_yellow", + Color::Blue => "blue", + Color::DarkBlue => "dark_blue", + Color::Magenta => "magenta", + Color::DarkMagenta => "dark_magenta", + Color::Cyan => "cyan", + Color::DarkCyan => "dark_cyan", + Color::White => "white", + Color::Grey => "grey", + _ => "", + }; + + if str == "" { + println!("color: {:?}", self); + match *self { + Color::AnsiValue(value) => { + return serializer.serialize_str(&format!("ansi_({})", value)); + } + Color::Rgb { r, g, b } => { + return serializer.serialize_str(&format!("rgb_({},{},{})", r, g, b)); + } + _ => { + return Err(serde::ser::Error::custom("Could not serialize enum type")); + } + } + } else { + return serializer.serialize_str(str); + } + } +} + #[cfg(feature = "serde")] impl<'de> serde::de::Deserialize<'de> for Color { fn deserialize(deserializer: D) -> Result @@ -228,7 +269,7 @@ impl<'de> serde::de::Deserialize<'de> for Color { type Value = Color; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str( - "`black`, `blue`, `dark_blue`, `cyan`, `dark_cyan`, `green`, `dark_green`, `grey`, `dark_grey`, `magenta`, `dark_magenta`, `red`, `dark_red`, `white`, `yellow`, `dark_yellow`, `u8`, or `3 u8 array`", + "`black`, `blue`, `dark_blue`, `cyan`, `dark_cyan`, `green`, `dark_green`, `grey`, `dark_grey`, `magenta`, `dark_magenta`, `red`, `dark_red`, `white`, `yellow`, `dark_yellow`, `ansi_(value)`, or `rgb_(r,g,b)`", ) } fn visit_str(self, value: &str) -> Result @@ -238,59 +279,45 @@ impl<'de> serde::de::Deserialize<'de> for Color { if let Ok(c) = Color::try_from(value) { Ok(c) } else { - Err(E::invalid_value(serde::de::Unexpected::Str(value), &self)) - } - } + if value.contains("ansi") { + // strip away `ansi_(..)' and get the inner value between parenthesis. + let results = value.replace("ansi_(", "").replace(")", ""); - fn visit_u64(self, value: u64) -> Result - where - E: serde::de::Error, - { - if value > 255 { - return Err(E::invalid_value( - serde::de::Unexpected::Unsigned(value), - &self, - )); - } - Ok(Color::AnsiValue(value as u8)) - } + let ansi_val = results.parse::(); - fn visit_seq(self, mut seq: M) -> Result - where - M: serde::de::SeqAccess<'de>, - { - let mut values = Vec::new(); - if let Some(size) = seq.size_hint() { - if size != 3 { - return Err(serde::de::Error::invalid_length( - size, - &"a list of size 3(RGB)", - )); - } - } - loop { - match seq.next_element::() { - Ok(Some(x)) => { - values.push(x); + if let Ok(ansi) = ansi_val { + return Ok(Color::AnsiValue(ansi)); } - Ok(None) => break, - Err(e) => { - return Err(e); + } else if value.contains("rgb") { + // strip away `rgb_(..)' and get the inner values between parenthesis. + let results = value + .replace("rgb_(", "") + .replace(")", "") + .split(',') + .map(|x| x.to_string()) + .collect::>(); + + if results.len() == 3 { + let r = results[0].parse::(); + let g = results[1].parse::(); + let b = results[2].parse::(); + + if r.is_ok() && g.is_ok() && b.is_ok() { + return Ok(Color::Rgb { + r: r.unwrap(), + g: g.unwrap(), + b: b.unwrap(), + }); + } } } + + Err(E::invalid_value(serde::de::Unexpected::Str(value), &self)) } - // recheck as size_hint sometimes not working - if values.len() != 3 { - return Err(serde::de::Error::invalid_length( - values.len(), - &"a list of size 3(RGB)", - )); - } - Ok(Color::from((values[0], values[1], values[2]))) } } - deserializer.deserialize_any(ColorVisitor) + deserializer.deserialize_str(ColorVisitor) } } @@ -423,28 +450,28 @@ mod serde_tests { #[test] fn test_deserial_ansi_value() { assert_eq!( - serde_json::from_str::("255").unwrap(), + serde_json::from_str::("\"ansi_(255)\"").unwrap(), Color::AnsiValue(255) ); } #[test] fn test_deserial_unvalid_ansi_value() { - assert!(serde_json::from_str::("256").is_err()); - assert!(serde_json::from_str::("-1").is_err()); + assert!(serde_json::from_str::("\"ansi_(256)\"").is_err()); + assert!(serde_json::from_str::("\"ansi_(-1)\"").is_err()); } #[test] fn test_deserial_rgb() { assert_eq!( - serde_json::from_str::("[255,255,255]").unwrap(), + serde_json::from_str::("\"rgb_(255,255,255)\"").unwrap(), Color::from((255, 255, 255)) ); } #[test] fn test_deserial_unvalid_rgb() { - assert!(serde_json::from_str::("[255,255,255,255]").is_err()); - assert!(serde_json::from_str::("[256,255,255]").is_err()); + assert!(serde_json::from_str::("\"rgb_(255,255,255,255)\"").is_err()); + assert!(serde_json::from_str::("\"rgb_(256,255,255)\"").is_err()); } }