use crate::{Attribute, State, Token, Tokenizer};
pub struct Reader<'a> {
tokenizer: Tokenizer<'a>,
}
impl<'a> Reader<'a> {
pub fn new(source: &'a str) -> Self {
Self {
tokenizer: Tokenizer::new(source),
}
}
pub fn position(&self) -> usize {
self.tokenizer.position()
}
#[inline(always)]
pub(crate) fn next_with_attribute_buffer(
&mut self,
attribute_buffer: &mut Vec<Attribute<'a>>,
) -> Option<Token<'a>> {
let token = self.tokenizer.next_with_attribute_buffer(attribute_buffer);
if let Some(Token::StartTag(tag)) = &token {
let context = match tag.name.as_ref() {
"title" => Some((State::Rcdata, "title")),
"textarea" => Some((State::Rcdata, "textarea")),
"style" => Some((State::Rawtext, "style")),
"xmp" => Some((State::Rawtext, "xmp")),
"iframe" => Some((State::Rawtext, "iframe")),
"noembed" => Some((State::Rawtext, "noembed")),
"noframes" => Some((State::Rawtext, "noframes")),
"script" => Some((State::ScriptData, "script")),
"plaintext" => Some((State::Plaintext, "plaintext")),
_ => None,
};
if let Some((state, name)) = context {
self.tokenizer.set_static_text_state(state, name);
}
}
token
}
}
impl<'a> Iterator for Reader<'a> {
type Item = Token<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.next_with_attribute_buffer(&mut Vec::new())
}
}
impl std::iter::FusedIterator for Reader<'_> {}