#[cfg(debug_assertions)]
use crate::events::is_event_of;
use crate::{
events::{ev, Event},
inline::{self},
internal_utils::peekable::Peekable,
types::Stack,
};
#[allow(clippy::large_enum_variant)]
enum State<
'a,
TBlockParser: Iterator<Item = crate::Result<Event>>,
TInlineStack: Stack<inline::StackEntry>,
> {
Normal(Option<TBlockParser>),
ParsingInline {
inline_parser: inline::Parser<'a, TInlineStack>,
segment_stream: Option<Peekable<2, WhileInlineSegment<TBlockParser>>>,
},
}
pub struct BlockEventStreamInlineSegmentMapper<
'a,
TBlockParser: Iterator<Item = crate::Result<Event>>,
TInlineStack: Stack<inline::StackEntry>,
> {
input: &'a [u8],
state: State<'a, TBlockParser, TInlineStack>,
}
impl<
'a,
TBlockParser: Iterator<Item = crate::Result<Event>>,
TInlineStack: Stack<inline::StackEntry>,
> BlockEventStreamInlineSegmentMapper<'a, TBlockParser, TInlineStack>
{
pub fn new(input: &'a [u8], block_parser: TBlockParser) -> Self {
Self {
input,
state: State::Normal(Some(block_parser)),
}
}
#[inline(always)]
fn next(&mut self) -> Option<crate::Result<Event>> {
let ret = loop {
match self.state {
State::Normal(ref mut block_parser) => {
let next = match unsafe { block_parser.as_mut().unwrap_unchecked() }.next() {
Some(Ok(x)) => x,
Some(Err(err)) => return Some(Err(err)),
None => return None,
};
if next.is_block_event_that_opens_inline_phase() {
let block_parser = unsafe { block_parser.take().unwrap_unchecked() };
let segment_stream = WhileInlineSegment::new(block_parser);
let inline_parser = inline::Parser::new(self.input);
self.state = State::ParsingInline {
inline_parser,
segment_stream: Some(Peekable::new(segment_stream)),
};
}
debug_assert!(!matches!(next, ev!(Block, __Unparsed(_))));
#[cfg(debug_assertions)]
debug_assert!(is_event_of!(Blend, next));
break Ok(next);
}
State::ParsingInline {
ref mut inline_parser,
ref mut segment_stream,
} => {
match inline_parser.next(unsafe { segment_stream.as_mut().unwrap_unchecked() })
{
Some(Ok(next)) => {
#[cfg(debug_assertions)]
debug_assert!(is_event_of!(Blend, next));
break Ok(next);
}
Some(Err(err)) => break Err(err),
None => {
let segment_stream =
unsafe { segment_stream.take().unwrap_unchecked() };
let (block_parser, leftover, err) = segment_stream.take_inner().drop();
if let Some(err) = err {
break Err(err);
}
self.state = State::Normal(Some(block_parser));
if let Some(ev) = leftover {
#[cfg(debug_assertions)]
debug_assert!(is_event_of!(Blend, ev));
break Ok(ev);
}
}
}
}
};
};
Some(ret)
}
}
impl<
TBlockParser: Iterator<Item = crate::Result<Event>>,
TInlineStack: Stack<inline::StackEntry>,
> Iterator for BlockEventStreamInlineSegmentMapper<'_, TBlockParser, TInlineStack>
{
type Item = crate::Result<Event>;
fn next(&mut self) -> Option<Self::Item> {
self.next()
}
}
pub struct WhileInlineSegment<
TBlockParser: Iterator<Item = crate::Result<Event>>,
> {
block_parser: TBlockParser,
leftover: Option<Event>,
error: Option<crate::Error>,
}
impl<
TBlockParser: Iterator<Item = crate::Result<Event>>,
> WhileInlineSegment<TBlockParser>
{
fn new(block_parser: TBlockParser) -> Self {
Self {
block_parser,
leftover: None,
error: None,
}
}
fn drop(self) -> (TBlockParser, Option<Event>, Option<crate::Error>) {
(self.block_parser, self.leftover, self.error)
}
#[inline(always)]
fn next(&mut self) -> Option<Event> {
match self.block_parser.next() {
Some(Ok(ev)) => {
if ev.is_block_event_that_closes_inline_phase() {
self.leftover = Some(ev);
None
} else {
#[cfg(debug_assertions)]
debug_assert!(is_event_of!(InlineInput, ev));
Some(ev)
}
}
Some(Err(err)) => {
self.error = Some(err);
None
}
None => None,
}
}
}
impl<
TBlockParser: Iterator<Item = crate::Result<Event>>,
> Iterator for WhileInlineSegment<TBlockParser>
{
type Item = Event;
fn next(&mut self) -> Option<Self::Item> {
self.next()
}
}