//! A space separated set of unique values. //! //! This type represents a set of unique values represented as a string of //! values separated by spaces in HTML attributes. use std::collections::BTreeSet; use std::fmt::{Debug, Display, Error, Formatter}; use std::iter::FromIterator; use std::ops::{Deref, DerefMut}; use std::str::FromStr; /// A space separated set of unique values. /// /// This type represents a set of unique values represented as a string of /// values separated by spaces in HTML attributes. #[derive(Clone, PartialEq, Eq, Hash)] pub struct SpacedSet(pub BTreeSet); impl SpacedSet { /// Construct an empty `SpacedSet`. pub fn new() -> Self { SpacedSet(BTreeSet::new()) } /// Add a value to the `SpacedSet`. pub fn add>(&mut self, value: T) -> bool { self.0.insert(value.into()) } } impl Default for SpacedSet { fn default() -> Self { Self::new() } } impl FromIterator for SpacedSet { fn from_iter(iter: I) -> Self where I: IntoIterator, { SpacedSet(iter.into_iter().collect()) } } impl<'a, A: 'a + Ord + Clone> FromIterator<&'a A> for SpacedSet { fn from_iter(iter: I) -> Self where I: IntoIterator, { SpacedSet(iter.into_iter().cloned().collect()) } } impl<'a, A: Ord + FromStr> FromStr for SpacedSet where ::Err: Debug, { type Err = ::Err; fn from_str(s: &str) -> Result { let result: Result, Self::Err> = s.split_whitespace().map(|s| FromStr::from_str(s)).collect(); result.map(Self::from_iter) } } impl<'a, A: Ord + FromStr> From<&'a str> for SpacedSet where ::Err: Debug, { fn from(s: &'a str) -> Self { Self::from_iter(s.split_whitespace().map(|s| FromStr::from_str(s).unwrap())) } } impl Deref for SpacedSet { type Target = BTreeSet; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for SpacedSet { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Display for SpacedSet { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { let mut it = self.0.iter().peekable(); while let Some(class) = it.next() { Display::fmt(class, f)?; if it.peek().is_some() { Display::fmt(" ", f)?; } } Ok(()) } } impl Debug for SpacedSet { fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { f.debug_list().entries(self.0.iter()).finish() } } impl<'a, A: Ord + FromStr> From> for SpacedSet where ::Err: Debug, { fn from(s: Vec<&'a str>) -> Self { let mut list = Self::new(); for key in s { list.insert(FromStr::from_str(key).unwrap()); } list } } impl<'a, A: Ord + FromStr> From<&Vec<&'a str>> for SpacedSet where ::Err: Debug, { fn from(s: &Vec<&'a str>) -> Self { let mut list = Self::new(); for key in s { list.insert(FromStr::from_str(key).unwrap()); } list } } impl<'a, 'b, A: Ord + FromStr> From<(&'a str, &'b str)> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list } } impl<'a, 'b, 'c, A: Ord + FromStr> From<(&'a str, &'b str, &'c str)> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list.insert(FromStr::from_str(s.2).unwrap()); list } } impl<'a, 'b, 'c, 'd, A: Ord + FromStr> From<(&'a str, &'b str, &'c str, &'d str)> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str, &str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list.insert(FromStr::from_str(s.2).unwrap()); list.insert(FromStr::from_str(s.3).unwrap()); list } } impl<'a, 'b, 'c, 'd, 'e, A: Ord + FromStr> From<(&'a str, &'b str, &'c str, &'d str, &'e str)> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str, &str, &str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list.insert(FromStr::from_str(s.2).unwrap()); list.insert(FromStr::from_str(s.3).unwrap()); list.insert(FromStr::from_str(s.4).unwrap()); list } } impl<'a, 'b, 'c, 'd, 'e, 'f, A: Ord + FromStr> From<(&'a str, &'b str, &'c str, &'d str, &'e str, &'f str)> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str, &str, &str, &str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list.insert(FromStr::from_str(s.2).unwrap()); list.insert(FromStr::from_str(s.3).unwrap()); list.insert(FromStr::from_str(s.4).unwrap()); list.insert(FromStr::from_str(s.5).unwrap()); list } } impl<'a, 'b, 'c, 'd, 'e, 'f, 'g, A: Ord + FromStr> From<( &'a str, &'b str, &'c str, &'d str, &'e str, &'f str, &'g str, )> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str, &str, &str, &str, &str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list.insert(FromStr::from_str(s.2).unwrap()); list.insert(FromStr::from_str(s.3).unwrap()); list.insert(FromStr::from_str(s.4).unwrap()); list.insert(FromStr::from_str(s.5).unwrap()); list.insert(FromStr::from_str(s.6).unwrap()); list } } impl<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, A: Ord + FromStr> From<( &'a str, &'b str, &'c str, &'d str, &'e str, &'f str, &'g str, &'h str, )> for SpacedSet where ::Err: Debug, { fn from(s: (&str, &str, &str, &str, &str, &str, &str, &str)) -> Self { let mut list = Self::new(); list.insert(FromStr::from_str(s.0).unwrap()); list.insert(FromStr::from_str(s.1).unwrap()); list.insert(FromStr::from_str(s.2).unwrap()); list.insert(FromStr::from_str(s.3).unwrap()); list.insert(FromStr::from_str(s.4).unwrap()); list.insert(FromStr::from_str(s.5).unwrap()); list.insert(FromStr::from_str(s.6).unwrap()); list.insert(FromStr::from_str(s.7).unwrap()); list } } macro_rules! spacedlist_from_array { ($num:tt) => { impl<'a, A: Ord + FromStr> From<[&'a str; $num]> for SpacedSet where ::Err: Debug, { fn from(s: [&str; $num]) -> Self { Self::from_iter(s.into_iter().map(|s| FromStr::from_str(*s).unwrap())) } } }; } spacedlist_from_array!(1); spacedlist_from_array!(2); spacedlist_from_array!(3); spacedlist_from_array!(4); spacedlist_from_array!(5); spacedlist_from_array!(6); spacedlist_from_array!(7); spacedlist_from_array!(8); spacedlist_from_array!(9); spacedlist_from_array!(10); spacedlist_from_array!(11); spacedlist_from_array!(12); spacedlist_from_array!(13); spacedlist_from_array!(14); spacedlist_from_array!(15); spacedlist_from_array!(16); spacedlist_from_array!(17); spacedlist_from_array!(18); spacedlist_from_array!(19); spacedlist_from_array!(20); spacedlist_from_array!(21); spacedlist_from_array!(22); spacedlist_from_array!(23); spacedlist_from_array!(24); spacedlist_from_array!(25); spacedlist_from_array!(26); spacedlist_from_array!(27); spacedlist_from_array!(28); spacedlist_from_array!(29); spacedlist_from_array!(30); spacedlist_from_array!(31); spacedlist_from_array!(32);