use crate::format_element::tag::TagKind;
use crate::prelude::Tag;
use crate::printer::stack::{Stack, StackedStack};
use crate::printer::{invalid_end_tag, invalid_start_tag};
use crate::{FormatElement, PrintResult};
use std::fmt::Debug;
use std::iter::FusedIterator;
use std::marker::PhantomData;
pub(super) trait Queue<'a> {
type Stack: Stack<&'a [FormatElement]>;
fn stack(&self) -> &Self::Stack;
fn stack_mut(&mut self) -> &mut Self::Stack;
fn next_index(&self) -> usize;
fn set_next_index(&mut self, index: usize);
fn pop(&mut self) -> Option<&'a FormatElement> {
match self.stack().top() {
Some(top_slice) => {
let next_index = self.next_index();
let element = &top_slice[next_index];
if next_index + 1 == top_slice.len() {
self.stack_mut().pop().unwrap();
self.set_next_index(0);
} else {
self.set_next_index(next_index + 1);
}
Some(element)
}
None => None,
}
}
fn top_with_interned(&self) -> Option<&'a FormatElement> {
self.stack()
.top()
.map(|top_slice| &top_slice[self.next_index()])
}
fn top(&self) -> Option<&'a FormatElement> {
let mut top = self.top_with_interned();
while let Some(FormatElement::Interned(interned)) = top {
top = interned.first()
}
top
}
fn push(&mut self, element: &'a FormatElement) {
self.extend_back(std::slice::from_ref(element))
}
fn extend_back(&mut self, elements: &'a [FormatElement]) {
match elements {
[] => {
}
slice => {
let next_index = self.next_index();
let stack = self.stack_mut();
if let Some(top) = stack.pop() {
stack.push(&top[next_index..])
}
stack.push(slice);
self.set_next_index(0);
}
}
}
fn pop_slice(&mut self) -> Option<&'a [FormatElement]> {
self.set_next_index(0);
self.stack_mut().pop()
}
fn skip_content(&mut self, kind: TagKind)
where
Self: Sized,
{
let iter = self.iter_content(kind);
for _ in iter {
}
}
fn iter_content<'q>(&'q mut self, kind: TagKind) -> QueueContentIterator<'a, 'q, Self>
where
Self: Sized,
{
QueueContentIterator::new(self, kind)
}
}
#[derive(Debug, Default, Clone)]
pub(super) struct PrintQueue<'a> {
slices: Vec<&'a [FormatElement]>,
next_index: usize,
}
impl<'a> PrintQueue<'a> {
pub(super) fn new(slice: &'a [FormatElement]) -> Self {
let slices = match slice {
[] => Vec::default(),
slice => vec![slice],
};
Self {
slices,
next_index: 0,
}
}
pub(super) fn is_empty(&self) -> bool {
self.slices.is_empty()
}
}
impl<'a> Queue<'a> for PrintQueue<'a> {
type Stack = Vec<&'a [FormatElement]>;
fn stack(&self) -> &Self::Stack {
&self.slices
}
fn stack_mut(&mut self) -> &mut Self::Stack {
&mut self.slices
}
fn next_index(&self) -> usize {
self.next_index
}
fn set_next_index(&mut self, index: usize) {
self.next_index = index
}
}
#[must_use]
#[derive(Debug)]
pub(super) struct FitsQueue<'a, 'print> {
stack: StackedStack<'print, &'a [FormatElement]>,
next_index: usize,
}
impl<'a, 'print> FitsQueue<'a, 'print> {
pub(super) fn new(
print_queue: &'print PrintQueue<'a>,
saved: Vec<&'a [FormatElement]>,
) -> Self {
let stack = StackedStack::with_vec(&print_queue.slices, saved);
Self {
stack,
next_index: print_queue.next_index,
}
}
pub(super) fn finish(self) -> Vec<&'a [FormatElement]> {
self.stack.into_vec()
}
}
impl<'a, 'print> Queue<'a> for FitsQueue<'a, 'print> {
type Stack = StackedStack<'print, &'a [FormatElement]>;
fn stack(&self) -> &Self::Stack {
&self.stack
}
fn stack_mut(&mut self) -> &mut Self::Stack {
&mut self.stack
}
fn next_index(&self) -> usize {
self.next_index
}
fn set_next_index(&mut self, index: usize) {
self.next_index = index;
}
}
pub(super) struct QueueIterator<'a, 'q, Q: Queue<'a>> {
queue: &'q mut Q,
lifetime: PhantomData<&'a ()>,
}
impl<'a, Q> Iterator for QueueIterator<'a, '_, Q>
where
Q: Queue<'a>,
{
type Item = &'a FormatElement;
fn next(&mut self) -> Option<Self::Item> {
self.queue.pop()
}
}
impl<'a, Q> FusedIterator for QueueIterator<'a, '_, Q> where Q: Queue<'a> {}
pub(super) struct QueueContentIterator<'a, 'q, Q: Queue<'a>> {
queue: &'q mut Q,
kind: TagKind,
depth: usize,
lifetime: PhantomData<&'a ()>,
}
impl<'a, 'q, Q> QueueContentIterator<'a, 'q, Q>
where
Q: Queue<'a>,
{
fn new(queue: &'q mut Q, kind: TagKind) -> Self {
Self {
queue,
kind,
depth: 1,
lifetime: PhantomData,
}
}
}
impl<'a, Q> Iterator for QueueContentIterator<'a, '_, Q>
where
Q: Queue<'a>,
{
type Item = &'a FormatElement;
fn next(&mut self) -> Option<Self::Item> {
match self.depth {
0 => None,
_ => {
let mut top = self.queue.pop();
while let Some(FormatElement::Interned(interned)) = top {
self.queue.extend_back(interned);
top = self.queue.pop();
}
match top.expect("Missing end signal.") {
element @ FormatElement::Tag(tag) if tag.kind() == self.kind => {
if tag.is_start() {
self.depth += 1;
} else {
self.depth -= 1;
if self.depth == 0 {
return None;
}
}
Some(element)
}
element => Some(element),
}
}
}
}
}
impl<'a, Q> FusedIterator for QueueContentIterator<'a, '_, Q> where Q: Queue<'a> {}
pub(super) trait FitsEndPredicate {
fn is_end(&mut self, element: &FormatElement) -> PrintResult<bool>;
}
pub(super) struct AllPredicate;
impl FitsEndPredicate for AllPredicate {
fn is_end(&mut self, _element: &FormatElement) -> PrintResult<bool> {
Ok(false)
}
}
#[derive(Debug)]
pub(super) enum SingleEntryPredicate {
Entry { depth: usize },
Done,
}
impl SingleEntryPredicate {
pub(super) const fn is_done(&self) -> bool {
matches!(self, SingleEntryPredicate::Done)
}
}
impl Default for SingleEntryPredicate {
fn default() -> Self {
SingleEntryPredicate::Entry { depth: 0 }
}
}
impl FitsEndPredicate for SingleEntryPredicate {
fn is_end(&mut self, element: &FormatElement) -> PrintResult<bool> {
let result = match self {
SingleEntryPredicate::Done => true,
SingleEntryPredicate::Entry { depth } => match element {
FormatElement::Tag(Tag::StartEntry) => {
*depth += 1;
false
}
FormatElement::Tag(Tag::EndEntry) => {
if *depth == 0 {
return invalid_end_tag(TagKind::Entry, None);
}
*depth -= 1;
let is_end = *depth == 0;
if is_end {
*self = SingleEntryPredicate::Done;
}
is_end
}
FormatElement::Interned(_) => false,
element if *depth == 0 => {
return invalid_start_tag(TagKind::Entry, Some(element));
}
_ => false,
},
};
Ok(result)
}
}
#[cfg(test)]
mod tests {
use crate::format_element::LineMode;
use crate::prelude::Tag;
use crate::printer::queue::{PrintQueue, Queue};
use crate::FormatElement;
#[test]
fn extend_back_pop_last() {
let mut queue =
PrintQueue::new(&[FormatElement::Tag(Tag::StartEntry), FormatElement::Space]);
assert_eq!(queue.pop(), Some(&FormatElement::Tag(Tag::StartEntry)));
queue.extend_back(&[FormatElement::Line(LineMode::SoftOrSpace)]);
assert_eq!(
queue.pop(),
Some(&FormatElement::Line(LineMode::SoftOrSpace))
);
assert_eq!(queue.pop(), Some(&FormatElement::Space));
assert_eq!(queue.pop(), None);
}
#[test]
fn extend_back_empty_queue() {
let mut queue =
PrintQueue::new(&[FormatElement::Tag(Tag::StartEntry), FormatElement::Space]);
assert_eq!(queue.pop(), Some(&FormatElement::Tag(Tag::StartEntry)));
assert_eq!(queue.pop(), Some(&FormatElement::Space));
queue.extend_back(&[FormatElement::Line(LineMode::SoftOrSpace)]);
assert_eq!(
queue.pop(),
Some(&FormatElement::Line(LineMode::SoftOrSpace))
);
assert_eq!(queue.pop(), None);
}
}