pochoir_parser/
node.rs

1//! Defines types used when parsing data.
2//!
3//! If you are not writing a new parser, you shouldn't care about these structures and should see
4//! [`TreeRef`] instead.
5//!
6//! [`TreeRef`]: crate::TreeRef
7use pochoir_common::Spanned;
8use pochoir_template_engine::TemplateBlock;
9use std::{borrow::Cow, slice};
10
11pub type AttrKey<'a> = Cow<'a, str>;
12pub type AttrVal<'a> = Vec<Spanned<TemplateBlock<'a>>>;
13pub type Attr<'a> = (Spanned<AttrKey<'a>>, Spanned<AttrVal<'a>>);
14
15/// The attributes belonging to a [`Node::Element`].
16#[derive(Debug, Default, Clone, PartialEq)]
17pub struct Attrs<'a>(Vec<Attr<'a>>);
18
19impl<'a> Attrs<'a> {
20    pub fn new() -> Self {
21        Self(vec![])
22    }
23
24    pub fn contains_key<'b, K: Into<AttrKey<'b>>>(&self, key: K) -> bool {
25        let key = key.into();
26        self.0.iter().any(|a| *a.0 == key)
27    }
28
29    pub fn get<'b, K: Into<AttrKey<'b>>>(&self, key: K) -> Option<&AttrVal<'a>> {
30        let key = key.into();
31        self.0.iter().find(|a| *a.0 == key).map(|a| &*a.1)
32    }
33
34    pub fn get_key_value<'b, K: Into<AttrKey<'b>>>(&self, key: K) -> Option<&Attr<'a>> {
35        let key = key.into();
36        self.0.iter().find(|a| *a.0 == key)
37    }
38
39    pub fn get_mut<'b, K: Into<AttrKey<'b>>>(&mut self, key: K) -> Option<&mut AttrVal<'a>> {
40        let key = key.into();
41        self.0.iter_mut().find(|a| *a.0 == key).map(|a| &mut *a.1)
42    }
43
44    pub fn insert<K: Into<AttrKey<'a>>, V: Into<AttrVal<'a>>>(&mut self, key: K, val: V) {
45        let key = key.into();
46        let val = val.into();
47
48        if let Some(attribute) = self.0.iter_mut().find(|a| *a.0 == key) {
49            attribute.0 = Spanned::new(key);
50            attribute.1 = Spanned::new(val);
51        } else {
52            self.0.push((Spanned::new(key), Spanned::new(val)));
53        }
54    }
55
56    pub fn insert_spanned<K: Into<AttrKey<'a>>, V: Into<AttrVal<'a>>>(
57        &mut self,
58        key: Spanned<K>,
59        val: Spanned<V>,
60    ) {
61        let key = key.map_spanned(Into::into);
62        let val = val.map_spanned(Into::into);
63
64        if let Some(attribute) = self.0.iter_mut().find(|a| a.0 == key) {
65            attribute.0 = key;
66            attribute.1 = val;
67        } else {
68            self.0.push((key, val));
69        }
70    }
71
72    pub fn remove<'b, K: Into<AttrKey<'b>>>(&mut self, key: K) -> Option<Attr<'a>> {
73        let key = key.into();
74
75        if let Some(index) = self.0.iter().enumerate().find(|(_, a)| *a.0 == key) {
76            Some(self.0.remove(index.0))
77        } else {
78            None
79        }
80    }
81
82    #[inline]
83    pub fn iter(&self) -> slice::Iter<'_, Attr<'a>> {
84        self.0.iter()
85    }
86
87    #[inline]
88    pub fn iter_mut(&'a mut self) -> slice::IterMut<'a, Attr<'a>> {
89        self.0.iter_mut()
90    }
91
92    pub fn deep_clone<'b>(self) -> Attrs<'b> {
93        self.0
94            .into_iter()
95            .map(|a| {
96                (
97                    a.0.map_spanned(|k| Cow::Owned(k.into_owned())),
98                    a.1.map_spanned(|v| {
99                        v.into_iter()
100                            .map(|v| v.map_spanned(TemplateBlock::deep_clone))
101                            .collect()
102                    }),
103                )
104            })
105            .collect()
106    }
107}
108
109impl<'a> FromIterator<Attr<'a>> for Attrs<'a> {
110    fn from_iter<T: IntoIterator<Item = Attr<'a>>>(iter: T) -> Self {
111        Self(iter.into_iter().collect())
112    }
113}
114impl<'a> FromIterator<(AttrKey<'a>, AttrVal<'a>)> for Attrs<'a> {
115    fn from_iter<T: IntoIterator<Item = (AttrKey<'a>, AttrVal<'a>)>>(iter: T) -> Self {
116        Self(
117            iter.into_iter()
118                .map(|(k, v)| (Spanned::new(k), Spanned::new(v)))
119                .collect(),
120        )
121    }
122}
123
124impl<'a, 'b> IntoIterator for &'a Attrs<'b> {
125    type Item = &'a Attr<'b>;
126    type IntoIter = slice::Iter<'a, Attr<'b>>;
127
128    fn into_iter(self) -> Self::IntoIter {
129        self.0.iter()
130    }
131}
132
133impl<'a, 'b> IntoIterator for &'a mut Attrs<'b> {
134    type Item = &'a mut Attr<'b>;
135    type IntoIter = slice::IterMut<'a, Attr<'b>>;
136
137    fn into_iter(self) -> Self::IntoIter {
138        self.0.iter_mut()
139    }
140}
141
142impl<'a> From<Vec<Attr<'a>>> for Attrs<'a> {
143    fn from(v: Vec<Attr<'a>>) -> Self {
144        Self(v)
145    }
146}
147
148impl<'a> From<&[Attr<'a>]> for Attrs<'a> {
149    fn from(v: &[Attr<'a>]) -> Self {
150        Self(v.to_vec())
151    }
152}
153
154impl<'a, const N: usize> From<[Attr<'a>; N]> for Attrs<'a> {
155    fn from(v: [Attr<'a>; N]) -> Self {
156        Self(v.to_vec())
157    }
158}
159
160/// A node returned by a parser and later stored in a tree.
161#[derive(Debug, Clone, PartialEq)]
162pub enum Node<'a> {
163    Element(Cow<'a, str>, Attrs<'a>),
164    Comment(Cow<'a, str>),
165    Doctype(Cow<'a, str>),
166    TemplateBlock(TemplateBlock<'a>),
167    Root,
168}
169
170impl<'a> Node<'a> {
171    pub(crate) fn node_type(&self) -> &'static str {
172        match self {
173            Node::Element(_, _) => "Element",
174            Node::Comment(_) => "Comment",
175            Node::Doctype(_) => "Doctype",
176            Node::TemplateBlock(_) => "TemplateBlock",
177            Node::Root => "Root",
178        }
179    }
180
181    /// Make a new "simple" element from its name and a list of plain string key/value pairs.
182    ///
183    /// This method does not support using interpreted expressions or statements inside attributes.
184    pub fn new_simple_element<
185        S1: Into<Cow<'a, str>>,
186        S2: Into<Cow<'a, str>>,
187        S3: Into<Cow<'a, str>>,
188        I: IntoIterator<Item = (S2, S3)>,
189    >(
190        element_name: S1,
191        attrs: I,
192    ) -> Self {
193        Self::Element(
194            element_name.into(),
195            attrs
196                .into_iter()
197                .map(|(k, v)| {
198                    (
199                        k.into(),
200                        vec![Spanned::new(TemplateBlock::RawText(v.into()))],
201                    )
202                })
203                .collect::<Attrs>(),
204        )
205    }
206
207    // Make a new element without any attributes.
208    pub fn new_element_without_attrs<S: Into<Cow<'a, str>>>(element_name: S) -> Self {
209        Self::Element(element_name.into(), Attrs::new())
210    }
211
212    pub fn new_comment<S: Into<Cow<'a, str>>>(comment_value: S) -> Self {
213        Self::Comment(comment_value.into())
214    }
215
216    pub fn new_doctype<S: Into<Cow<'a, str>>>(doctype_value: S) -> Self {
217        Self::Doctype(doctype_value.into())
218    }
219}
220
221impl Node<'_> {
222    pub fn deep_clone<'b>(self) -> Node<'b> {
223        match self {
224            Node::Element(a, b) => Node::Element(Cow::Owned(a.into_owned()), b.deep_clone()),
225            Node::Comment(a) => Node::Comment(Cow::Owned(a.into_owned())),
226            Node::Doctype(a) => Node::Doctype(Cow::Owned(a.into_owned())),
227            Node::TemplateBlock(a) => Node::TemplateBlock(a.deep_clone()),
228            Node::Root => Node::Root,
229        }
230    }
231}
232
233pub type ParsedNode<'a> = Spanned<Node<'a>>;