//! This module contains types and functions to support formatting specific macros. use itertools::Itertools; use std::{fmt, str}; use serde::{Deserialize, Serialize}; use serde_json as json; use thiserror::Error; /// Defines the name of a macro. #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] pub struct MacroName(String); impl MacroName { pub fn new(other: String) -> Self { Self(other) } } impl fmt::Display for MacroName { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.0.fmt(f) } } impl From for String { fn from(other: MacroName) -> Self { other.0 } } /// Defines a selector to match against a macro. #[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] pub enum MacroSelector { Name(MacroName), All, } impl fmt::Display for MacroSelector { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Name(name) => name.fmt(f), Self::All => write!(f, "*"), } } } impl str::FromStr for MacroSelector { type Err = std::convert::Infallible; fn from_str(s: &str) -> Result { Ok(match s { "*" => MacroSelector::All, name => MacroSelector::Name(MacroName(name.to_owned())), }) } } /// A set of macro selectors. #[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)] pub struct MacroSelectors(pub Vec); impl fmt::Display for MacroSelectors { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0.iter().format(", ")) } } #[derive(Error, Debug)] pub enum MacroSelectorsError { #[error("{0}")] Json(json::Error), } // This impl is needed for `Config::override_value` to work for use in tests. impl str::FromStr for MacroSelectors { type Err = MacroSelectorsError; fn from_str(s: &str) -> Result { let raw: Vec<&str> = json::from_str(s).map_err(MacroSelectorsError::Json)?; Ok(Self( raw.into_iter() .map(|raw| { MacroSelector::from_str(raw).expect("MacroSelector from_str is infallible") }) .collect(), )) } } #[cfg(test)] mod test { use super::*; use std::str::FromStr; #[test] fn macro_names_from_str() { let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap(); assert_eq!( macro_names, MacroSelectors( [ MacroSelector::Name(MacroName("foo".to_owned())), MacroSelector::All, MacroSelector::Name(MacroName("bar".to_owned())) ] .into_iter() .collect() ) ); } #[test] fn macro_names_display() { let macro_names = MacroSelectors::from_str(r#"["foo", "*", "bar"]"#).unwrap(); assert_eq!(format!("{}", macro_names), "foo, *, bar"); } }