use super::types::PdfRef;
use crate::Result;
#[derive(Clone, Copy)]
pub(super) struct PageNode {
pub(super) reference: PdfRef,
pub(super) parent: Option<PdfRef>,
pub(super) inherited_media_box: bool,
}
#[derive(Clone, Copy)]
pub(super) enum PageStep {
Enter(PageNode),
Exit {
reference: PdfRef,
declared_count: u32,
first_leaf: usize,
},
}
pub(super) struct PageWalk {
stack: Vec<PageStep>,
}
impl PageWalk {
pub(super) fn new(
root: PdfRef,
mut stack: Vec<PageStep>,
push: impl FnOnce(&mut Vec<PageStep>, PageStep) -> Result<()>,
) -> Result<Self> {
push(
&mut stack,
PageStep::Enter(PageNode {
reference: root,
parent: None,
inherited_media_box: false,
}),
)?;
Ok(Self { stack })
}
pub(super) fn next(&mut self, leaves: usize) -> Option<std::result::Result<PageNode, PdfRef>> {
loop {
match self.stack.pop()? {
PageStep::Enter(node) => return Some(Ok(node)),
PageStep::Exit {
reference,
declared_count,
first_leaf,
} => {
if leaves.saturating_sub(first_leaf) != declared_count as usize {
return Some(Err(reference));
}
}
}
}
}
pub(super) fn push_kids(
&mut self,
reference: PdfRef,
declared_count: u32,
kids: &[PdfRef],
media_box: bool,
leaves: usize,
mut push: impl FnMut(&mut Vec<PageStep>, PageStep) -> Result<()>,
) -> Result<()> {
push(
&mut self.stack,
PageStep::Exit {
reference,
declared_count,
first_leaf: leaves,
},
)?;
for kid in kids.iter().rev() {
push(
&mut self.stack,
PageStep::Enter(PageNode {
reference: *kid,
parent: Some(reference),
inherited_media_box: media_box,
}),
)?;
}
Ok(())
}
}