use std::borrow::Cow; use std::collections::BTreeSet; /// Type that holds a number of variables of type `T` pub trait VariableHolder { fn get_variables(&self) -> BTreeSet; } /// Type that holds a number of style variables of type `T` pub trait StyleVariableHolder { fn get_style_variables(&self) -> BTreeSet; } #[derive(Clone)] pub struct TextGroup<'a> { pub format: Vec>, pub style: Vec>, } #[derive(Clone)] pub enum FormatElement<'a> { Text(Cow<'a, str>), Variable(Cow<'a, str>), TextGroup(TextGroup<'a>), Conditional(Vec>), } #[derive(Clone)] pub enum StyleElement<'a> { Text(Cow<'a, str>), Variable(Cow<'a, str>), } impl<'a> VariableHolder> for FormatElement<'a> { fn get_variables(&self) -> BTreeSet> { match self { FormatElement::Variable(var) => { let mut variables = BTreeSet::new(); variables.insert(var.clone()); variables } FormatElement::TextGroup(textgroup) => textgroup.format.get_variables(), FormatElement::Conditional(format) => format.get_variables(), _ => Default::default(), } } } impl<'a> VariableHolder> for Vec> { fn get_variables(&self) -> BTreeSet> { self.iter().fold(BTreeSet::new(), |mut acc, el| { acc.extend(el.get_variables()); acc }) } } impl<'a> VariableHolder> for &[FormatElement<'a>] { fn get_variables(&self) -> BTreeSet> { self.iter().fold(BTreeSet::new(), |mut acc, el| { acc.extend(el.get_variables()); acc }) } } impl<'a> StyleVariableHolder> for StyleElement<'a> { fn get_style_variables(&self) -> BTreeSet> { match self { StyleElement::Variable(var) => { let mut variables = BTreeSet::new(); variables.insert(var.clone()); variables } _ => Default::default(), } } } impl<'a> StyleVariableHolder> for Vec> { fn get_style_variables(&self) -> BTreeSet> { self.iter().fold(BTreeSet::new(), |mut acc, el| { acc.extend(el.get_style_variables()); acc }) } } impl<'a> StyleVariableHolder> for Vec> { fn get_style_variables(&self) -> BTreeSet> { self.iter().fold(BTreeSet::new(), |mut acc, el| match el { FormatElement::TextGroup(textgroup) => { acc.extend(textgroup.style.get_style_variables()); acc } FormatElement::Conditional(format) => { acc.extend(format.get_style_variables()); acc } _ => acc, }) } }