use std::collections::HashMap; use std::fmt::{self, Debug, Formatter}; use std::ops::{Add, AddAssign, Deref}; use std::rc::Rc; use super::Value; use crate::exec::ExecContext; use crate::syntax::{Expr, SyntaxTree}; use crate::util::EcoString; /// A template value: `[*Hi* there]`. #[derive(Debug, Default, Clone)] pub struct Template { nodes: Rc>, } impl Template { /// Create a new template from a vector of nodes. pub fn new(nodes: Vec) -> Self { Self { nodes: Rc::new(nodes) } } /// Iterate over the contained template nodes. pub fn iter(&self) -> impl Iterator + '_ { self.nodes.iter() } } impl From for Template { fn from(tree: TemplateTree) -> Self { Self::new(vec![TemplateNode::Tree(tree)]) } } impl From for Template { fn from(func: TemplateFunc) -> Self { Self::new(vec![TemplateNode::Func(func)]) } } impl From for Template { fn from(string: EcoString) -> Self { Self::new(vec![TemplateNode::Str(string)]) } } impl PartialEq for Template { fn eq(&self, other: &Self) -> bool { Rc::ptr_eq(&self.nodes, &other.nodes) } } impl Add for Template { type Output = Self; fn add(mut self, rhs: Self) -> Self::Output { self += rhs; self } } impl AddAssign for Template { fn add_assign(&mut self, rhs: Template) { let sink = Rc::make_mut(&mut self.nodes); match Rc::try_unwrap(rhs.nodes) { Ok(source) => sink.extend(source), Err(rc) => sink.extend(rc.iter().cloned()), } } } impl Add for Template { type Output = Self; fn add(mut self, rhs: EcoString) -> Self::Output { Rc::make_mut(&mut self.nodes).push(TemplateNode::Str(rhs)); self } } impl Add