1use crate::{Attribute, State, Token, Tokenizer};
4
5pub struct Reader<'a> {
15 tokenizer: Tokenizer<'a>,
16}
17
18impl<'a> Reader<'a> {
19 pub fn new(source: &'a str) -> Self {
21 Self {
22 tokenizer: Tokenizer::new(source),
23 }
24 }
25
26 pub fn position(&self) -> usize {
30 self.tokenizer.position()
31 }
32
33 #[inline(always)]
36 pub(crate) fn next_with_attribute_buffer(
37 &mut self,
38 attribute_buffer: &mut Vec<Attribute<'a>>,
39 ) -> Option<Token<'a>> {
40 let token = self.tokenizer.next_with_attribute_buffer(attribute_buffer);
41 if let Some(Token::StartTag(tag)) = &token {
42 let context = match tag.name.as_ref() {
43 "title" => Some((State::Rcdata, "title")),
44 "textarea" => Some((State::Rcdata, "textarea")),
45 "style" => Some((State::Rawtext, "style")),
46 "xmp" => Some((State::Rawtext, "xmp")),
47 "iframe" => Some((State::Rawtext, "iframe")),
48 "noembed" => Some((State::Rawtext, "noembed")),
49 "noframes" => Some((State::Rawtext, "noframes")),
50 "script" => Some((State::ScriptData, "script")),
51 "plaintext" => Some((State::Plaintext, "plaintext")),
52 _ => None,
53 };
54 if let Some((state, name)) = context {
55 self.tokenizer.set_static_text_state(state, name);
56 }
57 }
58 token
59 }
60}
61
62impl<'a> Iterator for Reader<'a> {
63 type Item = Token<'a>;
64
65 fn next(&mut self) -> Option<Self::Item> {
66 self.next_with_attribute_buffer(&mut Vec::new())
67 }
68}
69
70impl std::iter::FusedIterator for Reader<'_> {}