use crate::*; use std::iter::FromIterator; use std::ops::Add; use std::rc::Rc; #[derive(Debug, Clone, PartialEq, Eq)] pub struct InterpolatedText { head: String, tail: Vec<(Rc>, String)>, } impl From<(String, Vec<(Rc>, String)>)> for InterpolatedText { fn from(x: (String, Vec<(Rc>, String)>)) -> Self { InterpolatedText { head: x.0, tail: x.1, } } } impl From for InterpolatedText { fn from(s: String) -> Self { InterpolatedText { head: s, tail: vec![], } } } #[derive(Debug, Clone, PartialEq, Eq)] pub enum InterpolatedTextContents { Text(String), Expr(SubExpr), } impl InterpolatedText { pub fn map(&self, mut f: F) -> InterpolatedText where F: FnMut(&Rc>) -> Rc>, { InterpolatedText { head: self.head.clone(), tail: self.tail.iter().map(|(e, s)| (f(e), s.clone())).collect(), } } pub fn iter<'a>( &'a self, ) -> impl Iterator> + 'a { use std::iter::once; once(InterpolatedTextContents::Text(self.head.clone())).chain( self.tail.iter().flat_map(|(e, s)| { once(InterpolatedTextContents::Expr(Rc::clone(e))) .chain(once(InterpolatedTextContents::Text(s.clone()))) }), ) } } impl<'a, N: 'a, E: 'a> FromIterator> for InterpolatedText { fn from_iter(iter: T) -> Self where T: IntoIterator>, { let mut res = InterpolatedText { head: "".to_owned(), tail: vec![], }; let mut crnt_str = &mut res.head; for x in iter.into_iter() { match x { InterpolatedTextContents::Text(s) => crnt_str.push_str(&s), InterpolatedTextContents::Expr(e) => { res.tail.push((e.clone(), "".to_owned())); crnt_str = &mut res.tail.last_mut().unwrap().1; } } } res } } impl Add for &InterpolatedText { type Output = InterpolatedText; fn add(self, rhs: &InterpolatedText) -> Self::Output { self.iter().chain(rhs.iter()).collect() } }