facet_dom/
parser_ext.rs

1//! Extension trait for DomParser with expect_* convenience methods.
2
3use std::borrow::Cow;
4
5use crate::trace;
6use crate::{DomDeserializeError, DomEvent, DomParser};
7
8/// Extension trait adding convenience methods to any `DomParser`.
9pub trait DomParserExt<'de>: DomParser<'de> {
10    /// Get the next event, returning an error if EOF.
11    fn next_event_or_eof(
12        &mut self,
13        expected: &'static str,
14    ) -> Result<DomEvent<'de>, DomDeserializeError<Self::Error>> {
15        let event = self
16            .next_event()
17            .map_err(DomDeserializeError::Parser)?
18            .ok_or(DomDeserializeError::UnexpectedEof { expected })?;
19        trace!(event = %event.trace(), kind = %"next");
20        Ok(event)
21    }
22
23    /// Peek at the next event, returning an error if EOF.
24    fn peek_event_or_eof(
25        &mut self,
26        expected: &'static str,
27    ) -> Result<&DomEvent<'de>, DomDeserializeError<Self::Error>> {
28        let event = self
29            .peek_event()
30            .map_err(DomDeserializeError::Parser)?
31            .ok_or(DomDeserializeError::UnexpectedEof { expected })?;
32        trace!(event = %event.trace(), kind = %"peek");
33        Ok(event)
34    }
35
36    /// Expect and consume a NodeStart event, returning the tag name.
37    fn expect_node_start(&mut self) -> Result<Cow<'de, str>, DomDeserializeError<Self::Error>> {
38        match self.next_event_or_eof("NodeStart")? {
39            DomEvent::NodeStart { tag, .. } => Ok(tag),
40            other => Err(DomDeserializeError::TypeMismatch {
41                expected: "NodeStart",
42                got: format!("{other:?}"),
43            }),
44        }
45    }
46
47    /// Expect and consume a ChildrenStart event.
48    fn expect_children_start(&mut self) -> Result<(), DomDeserializeError<Self::Error>> {
49        match self.next_event_or_eof("ChildrenStart")? {
50            DomEvent::ChildrenStart => Ok(()),
51            other => Err(DomDeserializeError::TypeMismatch {
52                expected: "ChildrenStart",
53                got: format!("{other:?}"),
54            }),
55        }
56    }
57
58    /// Expect and consume a ChildrenEnd event.
59    fn expect_children_end(&mut self) -> Result<(), DomDeserializeError<Self::Error>> {
60        match self.next_event_or_eof("ChildrenEnd")? {
61            DomEvent::ChildrenEnd => Ok(()),
62            other => Err(DomDeserializeError::TypeMismatch {
63                expected: "ChildrenEnd",
64                got: format!("{other:?}"),
65            }),
66        }
67    }
68
69    /// Expect and consume a NodeEnd event.
70    fn expect_node_end(&mut self) -> Result<(), DomDeserializeError<Self::Error>> {
71        match self.next_event_or_eof("NodeEnd")? {
72            DomEvent::NodeEnd => Ok(()),
73            other => Err(DomDeserializeError::TypeMismatch {
74                expected: "NodeEnd",
75                got: format!("{other:?}"),
76            }),
77        }
78    }
79
80    /// Expect and consume a Text event, returning the text content.
81    fn expect_text(&mut self) -> Result<Cow<'de, str>, DomDeserializeError<Self::Error>> {
82        match self.next_event_or_eof("Text")? {
83            DomEvent::Text(text) => Ok(text),
84            other => Err(DomDeserializeError::TypeMismatch {
85                expected: "Text",
86                got: format!("{other:?}"),
87            }),
88        }
89    }
90
91    /// Expect and consume an Attribute event, returning (name, value, namespace).
92    fn expect_attribute(
93        &mut self,
94    ) -> Result<AttributeRecord<'de>, DomDeserializeError<Self::Error>> {
95        match self.next_event_or_eof("Attribute")? {
96            DomEvent::Attribute {
97                name,
98                value,
99                namespace,
100            } => Ok(AttributeRecord {
101                name,
102                value,
103                namespace,
104            }),
105            other => Err(DomDeserializeError::TypeMismatch {
106                expected: "Attribute",
107                got: format!("{other:?}"),
108            }),
109        }
110    }
111
112    /// Expect and consume a Comment event, returning the comment text.
113    fn expect_comment(&mut self) -> Result<Cow<'de, str>, DomDeserializeError<Self::Error>> {
114        match self.next_event_or_eof("Comment")? {
115            DomEvent::Comment(text) => Ok(text),
116            other => Err(DomDeserializeError::TypeMismatch {
117                expected: "Comment",
118                got: format!("{other:?}"),
119            }),
120        }
121    }
122}
123
124/// An attribute name-value-namespace triple from a DOM event.
125pub struct AttributeRecord<'de> {
126    /// The attribute name.
127    pub name: Cow<'de, str>,
128    /// The attribute value.
129    pub value: Cow<'de, str>,
130    /// The attribute namespace URI, if any.
131    pub namespace: Option<Cow<'de, str>>,
132}
133
134impl<'de, P: DomParser<'de>> DomParserExt<'de> for P {}