use crate::errors::SyntaxError;
use crate::parser::Parser;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ElementParser {
Outside,
SingleQ,
DoubleQ,
}
impl Parser for ElementParser {
#[inline]
fn feed(&mut self, bytes: &[u8]) -> Option<usize> {
for i in memchr::memchr3_iter(b'>', b'\'', b'"', bytes) {
*self = match (*self, bytes[i]) {
(Self::Outside, b'>') => return Some(i),
(Self::Outside, b'\'') => Self::SingleQ,
(Self::Outside, b'\"') => Self::DoubleQ,
(Self::SingleQ, b'\'') | (Self::DoubleQ, b'"') => Self::Outside,
_ => continue,
};
}
None
}
#[inline]
fn eof_error(self, _content: &[u8]) -> SyntaxError {
match self {
Self::Outside => SyntaxError::UnclosedTag,
Self::SingleQ => SyntaxError::UnclosedSingleQuotedAttributeValue,
Self::DoubleQ => SyntaxError::UnclosedDoubleQuotedAttributeValue,
}
}
}
impl Default for ElementParser {
#[inline]
fn default() -> Self {
Self::Outside
}
}
#[test]
fn parse() {
use pretty_assertions::assert_eq;
use ElementParser::*;
fn parse_element(bytes: &[u8], mut parser: ElementParser) -> Result<usize, ElementParser> {
match parser.feed(bytes) {
Some(i) => Ok(i),
None => Err(parser),
}
}
assert_eq!(parse_element(b"", Outside), Err(Outside));
assert_eq!(parse_element(b"", SingleQ), Err(SingleQ));
assert_eq!(parse_element(b"", DoubleQ), Err(DoubleQ));
assert_eq!(parse_element(b"'", Outside), Err(SingleQ));
assert_eq!(parse_element(b"'", SingleQ), Err(Outside));
assert_eq!(parse_element(b"'", DoubleQ), Err(DoubleQ));
assert_eq!(parse_element(b"\"", Outside), Err(DoubleQ));
assert_eq!(parse_element(b"\"", SingleQ), Err(SingleQ));
assert_eq!(parse_element(b"\"", DoubleQ), Err(Outside));
assert_eq!(parse_element(b">", Outside), Ok(0));
assert_eq!(parse_element(b">", SingleQ), Err(SingleQ));
assert_eq!(parse_element(b">", DoubleQ), Err(DoubleQ));
assert_eq!(parse_element(b"''>", Outside), Ok(2));
assert_eq!(parse_element(b"''>", SingleQ), Err(SingleQ));
assert_eq!(parse_element(b"''>", DoubleQ), Err(DoubleQ));
}