#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::vec::Vec;
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::{
scanner::{Scanner, State as ScannerState},
token::borrowed,
};
#[cfg(any(feature = "std", feature = "alloc"))]
use core::{convert::TryFrom, fmt};
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
#[cfg(any(feature = "std", feature = "alloc"))]
enum State {
Reset,
Evaluating,
EvaluatedStartTag,
EvaluatedEmptyElementTag,
EvaluatedEndTag,
EvaluatedProcessingInstruction,
EvaluatedDeclaration,
EvaluatedTextContent,
EvaluatedComment,
EvaluatedCdata,
Eof,
Done,
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg(any(feature = "std", feature = "alloc"))]
#[non_exhaustive]
pub enum RecvError {
NeedToRecvMoreBytes,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl fmt::Display for RecvError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RecvError::NeedToRecvMoreBytes => write!(f, "need to receive more bytes"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for RecvError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
None
}
}
#[derive(Clone, Debug)]
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct RecvEvaluator {
buf: Vec<u8>,
scanner: Scanner,
position: u64,
state: State,
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl RecvEvaluator {
pub fn new() -> Self {
Self {
buf: Vec::new(),
scanner: Scanner::new(),
position: 0,
state: State::Evaluating,
}
}
pub fn position(&self) -> u64 {
self.position
}
pub fn recv(&mut self, bytes: &[u8]) -> usize {
match self.state {
State::Evaluating => {}
State::Reset
| State::EvaluatedStartTag
| State::EvaluatedEmptyElementTag
| State::EvaluatedEndTag
| State::EvaluatedProcessingInstruction
| State::EvaluatedDeclaration
| State::EvaluatedComment
| State::EvaluatedCdata
| State::EvaluatedTextContent => self.buf.clear(),
State::Eof => {
self.state = State::Done;
return 0;
}
State::Done => {
return 0;
}
}
let state = self.scanner.scan(bytes);
match state {
None => {
self.state = State::Eof;
0
}
Some(ScannerState::ScanningMarkup) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningStartOrEmptyElementTag) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningCharacters) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningEndTag) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningProcessingInstruction) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningDeclarationCommentOrCdata) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningDeclaration) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningComment) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScanningCdata) => {
self.buf.extend_from_slice(bytes);
let bytes_len = bytes.len();
self.position += u64::try_from(bytes_len)
.unwrap_or_else(|_| panic!("{} to be <= u64::MAX", bytes_len));
self.state = State::Evaluating;
bytes_len
}
Some(ScannerState::ScannedStartTag(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedStartTag;
read
}
Some(ScannerState::ScannedEmptyElementTag(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedEmptyElementTag;
read
}
Some(ScannerState::ScannedEndTag(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedEndTag;
read
}
Some(ScannerState::ScannedCharacters(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedTextContent;
read
}
Some(ScannerState::ScannedProcessingInstruction(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedProcessingInstruction;
read
}
Some(ScannerState::ScannedDeclaration(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedDeclaration;
read
}
Some(ScannerState::ScannedComment(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedComment;
read
}
Some(ScannerState::ScannedCdata(read)) => {
self.buf.extend_from_slice(&bytes[..read]);
self.position +=
u64::try_from(read).unwrap_or_else(|_| panic!("{} to be <= u64::MAX", read));
self.state = State::EvaluatedCdata;
read
}
}
}
pub fn next_token(&mut self) -> Result<Option<borrowed::Token>, RecvError> {
use borrowed::{
BytesNotEvaluated, Cdata, Characters, Comment, Declaration, EmptyElementTag, EndTag,
ProcessingInstruction, StartTag, Token,
};
let token = match self.state {
State::Reset | State::Evaluating => return Err(RecvError::NeedToRecvMoreBytes),
State::EvaluatedStartTag => {
self.state = State::Reset;
Some(Token::StartTag(StartTag::from(&self.buf)))
}
State::EvaluatedEndTag => {
self.state = State::Reset;
Some(Token::EndTag(EndTag::from(&self.buf)))
}
State::EvaluatedEmptyElementTag => {
self.state = State::Reset;
Some(Token::EmptyElementTag(EmptyElementTag::from(&self.buf)))
}
State::EvaluatedTextContent => {
self.state = State::Reset;
Some(Token::Characters(Characters::from(&self.buf)))
}
State::EvaluatedProcessingInstruction => {
self.state = State::Reset;
Some(Token::ProcessingInstruction(ProcessingInstruction::from(
&self.buf,
)))
}
State::EvaluatedDeclaration => {
self.state = State::Reset;
Some(Token::Declaration(Declaration::from(&self.buf)))
}
State::EvaluatedComment => {
self.state = State::Reset;
Some(Token::Comment(Comment::from(&self.buf)))
}
State::EvaluatedCdata => {
self.state = State::Reset;
Some(Token::Cdata(Cdata::from(&self.buf)))
}
State::Eof => {
self.state = State::Done;
if self.buf.is_empty() {
Some(Token::Eof)
} else {
Some(Token::EofWithBytesNotEvaluated(BytesNotEvaluated::from(
&self.buf,
)))
}
}
State::Done => None,
};
Ok(token)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl Default for RecvEvaluator {
fn default() -> Self {
Self::new()
}
}
#[cfg(all(test, any(feature = "std", feature = "alloc")))]
mod tests {
use super::*;
use crate::token::borrowed::{
BytesNotEvaluated, Cdata, Characters, Comment, Declaration, EmptyElementTag, EndTag,
ProcessingInstruction, StartTag, Token,
};
use rand::{thread_rng, Rng};
type Result<T> = core::result::Result<T, RecvError>;
struct TestRecv {
bytes: Vec<u8>,
index: usize,
}
impl TestRecv {
fn with_bytes<B: AsRef<[u8]>>(bytes: B) -> Self {
Self {
bytes: bytes.as_ref().to_vec(),
index: 0,
}
}
fn assert_next_token(
&mut self,
eval: &mut RecvEvaluator,
expected_token: Option<Token>,
) -> bool {
let mut rng = thread_rng();
let mut fill_size = rng.gen_range(1, self.bytes.len() - self.index + 2);
loop {
let end = usize::min(self.index + fill_size, self.bytes.len());
let bytes = &self.bytes[self.index..end];
let read = eval.recv(bytes);
self.index += read;
let next_token = eval.next_token();
if let Ok(token) = next_token {
assert_eq!(token, expected_token);
return true;
} else {
assert_eq!(next_token, Err(RecvError::NeedToRecvMoreBytes));
if self.index == self.bytes.len() {
if expected_token.is_some() {
let read = eval.recv(&[]);
assert_eq!(read, 0);
let next_token = eval.next_token();
assert_eq!(next_token, Ok(expected_token));
return true;
}
return expected_token.is_none();
}
}
if self.index + fill_size < self.bytes.len() {
fill_size += rng.gen_range(1, self.bytes.len() - self.index - fill_size + 2);
}
}
}
}
#[test]
fn empty() -> Result<()> {
let xml = r"";
let mut eval = RecvEvaluator::new();
assert_eq!(eval.recv(xml.as_bytes()), 0);
assert_eq!(eval.next_token()?, Some(Token::Eof));
assert_eq!(eval.position(), 0);
assert_eq!(eval.recv(xml.as_bytes()), 0);
assert_eq!(eval.next_token()?, None);
assert_eq!(eval.position(), 0);
Ok(())
}
#[test]
fn characters_content() -> Result<()> {
let xml = r"hello world";
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let text_content = Characters::from(b"hello world".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 11);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 11);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 11);
Ok(())
}
#[test]
fn start_tag() -> Result<()> {
let xml = r"<hello>";
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let start_tag = StartTag::from(b"<hello>".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 7);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 7);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 7);
Ok(())
}
#[test]
fn start_tag_with_double_quote_attribute() -> Result<()> {
let xml = r#"<hello name="rust">"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let start_tag = StartTag::from(r#"<hello name="rust">"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 19);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 19);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 19);
Ok(())
}
#[test]
fn start_tag_with_double_quote_attribute_with_angle_bracket() -> Result<()> {
let xml = r#"<hello name="ru>st">"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let start_tag = StartTag::from(r#"<hello name="ru>st">"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 20);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 20);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 20);
Ok(())
}
#[test]
fn start_tag_with_single_quote_attribute() -> Result<()> {
let xml = r#"<hello name='rust'>"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let start_tag = StartTag::from(r#"<hello name='rust'>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 19);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 19);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 19);
Ok(())
}
#[test]
fn start_tag_with_single_quote_attribute_with_angle_bracket() -> Result<()> {
let xml = r#"<hello name='ru>st'>"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let start_tag = StartTag::from(r#"<hello name='ru>st'>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 20);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 20);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 20);
Ok(())
}
#[test]
fn end_tag() -> Result<()> {
let xml = r"</goodbye>";
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let end_tag = EndTag::from(r#"</goodbye>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EndTag(end_tag))),
true
);
assert_eq!(eval.position(), 10);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 10);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 10);
Ok(())
}
#[test]
fn empty_end_tag() -> Result<()> {
let xml = r"</>";
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let end_tag = EndTag::from(r#"</>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EndTag(end_tag))),
true
);
assert_eq!(eval.position(), 3);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 3);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 3);
Ok(())
}
#[test]
fn empty_element_tag() -> Result<()> {
let xml = r"<standalone/>";
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let empty_element_tag = EmptyElementTag::from(r#"<standalone/>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EmptyElementTag(empty_element_tag))),
true
);
assert_eq!(eval.position(), 13);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 13);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 13);
Ok(())
}
#[test]
fn processing_instruction() -> Result<()> {
let xml = r#"<?xml-stylesheet type="text/css" href="example.css"?>"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let processing_instruction = ProcessingInstruction::from(
r#"<?xml-stylesheet type="text/css" href="example.css"?>"#.as_bytes(),
);
assert_eq!(
tester.assert_next_token(
&mut eval,
Some(Token::ProcessingInstruction(processing_instruction))
),
true
);
assert_eq!(eval.position(), 53);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 53);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 53);
Ok(())
}
#[test]
fn declaration() -> Result<()> {
let xml = r#"<!DOCTYPE example>"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let declaration = Declaration::from(r#"<!DOCTYPE example>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Declaration(declaration))),
true
);
assert_eq!(eval.position(), 18);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 18);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 18);
Ok(())
}
#[test]
fn comment() -> Result<()> {
let xml = r#"<!-- Example -->"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let comment = Comment::from(r#"<!-- Example -->"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Comment(comment))),
true
);
assert_eq!(eval.position(), 16);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 16);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 16);
Ok(())
}
#[test]
fn cdata() -> Result<()> {
let xml = r#"<![CDATA[ <Example> ]]>"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let cdata = Cdata::from(r#"<![CDATA[ <Example> ]]>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Cdata(cdata))),
true
);
assert_eq!(eval.position(), 23);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 23);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 23);
Ok(())
}
#[test]
fn bytes_not_evaluated() -> Result<()> {
let xml = r#"<unfinished name="xml""#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let bytes_not_evaluated = BytesNotEvaluated::from(r#"<unfinished name="xml""#.as_bytes());
assert_eq!(
tester.assert_next_token(
&mut eval,
Some(Token::EofWithBytesNotEvaluated(bytes_not_evaluated))
),
true
);
assert_eq!(eval.position(), 22);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 22);
Ok(())
}
#[test]
fn simple_xml_read() -> Result<()> {
let xml = r#"<hello name="rust">Welcome!<goodbye/></hello><abcd></abcd>"#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let start_tag = StartTag::from(r#"<hello name="rust">"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 19);
let text_content = Characters::from(r#"Welcome!"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 27);
let empty_element_tag = EmptyElementTag::from(r#"<goodbye/>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EmptyElementTag(empty_element_tag))),
true
);
assert_eq!(eval.position(), 37);
let end_tag = EndTag::from(r#"</hello>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EndTag(end_tag))),
true
);
assert_eq!(eval.position(), 45);
let start_tag = StartTag::from(r#"<abcd>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 51);
let end_tag = EndTag::from(r#"</abcd>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EndTag(end_tag))),
true
);
assert_eq!(eval.position(), 58);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 58);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 58);
Ok(())
}
#[test]
fn simple_xml_read_with_space() -> Result<()> {
let xml = r#" <hello name="rust"> Welcome! <goodbye /> </hello> <abcd> </abcd> "#;
let mut tester = TestRecv::with_bytes(xml);
let mut eval = RecvEvaluator::new();
let text_content = Characters::from(b" ".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 3);
let start_tag = StartTag::from(r#"<hello name="rust">"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 22);
let text_content = Characters::from(b" Welcome! ".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 32);
let empty_element_tag = EmptyElementTag::from(r#"<goodbye />"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EmptyElementTag(empty_element_tag))),
true
);
assert_eq!(eval.position(), 44);
let text_content = Characters::from(b" ".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 46);
let end_tag = EndTag::from(r#"</hello>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EndTag(end_tag))),
true
);
assert_eq!(eval.position(), 54);
let text_content = Characters::from(b" ".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 56);
let start_tag = StartTag::from(r#"<abcd>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::StartTag(start_tag))),
true
);
assert_eq!(eval.position(), 62);
let text_content = Characters::from(b" ".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 63);
let end_tag = EndTag::from(r#"</abcd>"#.as_bytes());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::EndTag(end_tag))),
true
);
assert_eq!(eval.position(), 70);
let text_content = Characters::from(b" ".as_ref());
assert_eq!(
tester.assert_next_token(&mut eval, Some(Token::Characters(text_content))),
true
);
assert_eq!(eval.position(), 71);
assert_eq!(tester.assert_next_token(&mut eval, Some(Token::Eof)), true);
assert_eq!(eval.position(), 71);
assert_eq!(tester.assert_next_token(&mut eval, None), true);
assert_eq!(eval.position(), 71);
Ok(())
}
}