use super::cursor::SkipPolicy;
#[derive(Clone, Copy, Debug)]
pub struct Checkpoint {
pub(crate) descendant_index: u32,
pub(crate) effect_watermark: usize,
pub(crate) frame_index: Option<u32>,
pub(crate) recursion_depth: u32,
pub(crate) ip: u16,
pub(crate) skip_policy: Option<SkipPolicy>,
pub(crate) suppress_depth: u16,
}
#[allow(dead_code)] impl Checkpoint {
pub fn new(
descendant_index: u32,
effect_watermark: usize,
frame_index: Option<u32>,
recursion_depth: u32,
ip: u16,
skip_policy: Option<SkipPolicy>,
suppress_depth: u16,
) -> Self {
Self {
descendant_index,
effect_watermark,
frame_index,
recursion_depth,
ip,
skip_policy,
suppress_depth,
}
}
pub fn descendant_index(&self) -> u32 {
self.descendant_index
}
pub fn effect_watermark(&self) -> usize {
self.effect_watermark
}
pub fn frame_index(&self) -> Option<u32> {
self.frame_index
}
pub fn recursion_depth(&self) -> u32 {
self.recursion_depth
}
pub fn ip(&self) -> u16 {
self.ip
}
pub fn skip_policy(&self) -> Option<SkipPolicy> {
self.skip_policy
}
pub fn suppress_depth(&self) -> u16 {
self.suppress_depth
}
}
#[derive(Debug)]
pub struct CheckpointStack {
stack: Vec<Checkpoint>,
max_frame_ref: Option<u32>,
}
impl CheckpointStack {
pub fn new() -> Self {
Self {
stack: Vec::new(),
max_frame_ref: None,
}
}
pub fn push(&mut self, checkpoint: Checkpoint) {
if let Some(frame_idx) = checkpoint.frame_index {
self.max_frame_ref = Some(match self.max_frame_ref {
Some(max) => max.max(frame_idx),
None => frame_idx,
});
}
self.stack.push(checkpoint);
}
pub fn pop(&mut self) -> Option<Checkpoint> {
let cp = self.stack.pop()?;
if cp.frame_index == self.max_frame_ref && !self.stack.is_empty() {
self.max_frame_ref = self.stack.iter().filter_map(|c| c.frame_index).max();
} else if self.stack.is_empty() {
self.max_frame_ref = None;
}
Some(cp)
}
#[inline]
pub fn max_frame_ref(&self) -> Option<u32> {
self.max_frame_ref
}
#[inline]
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.stack.is_empty()
}
#[inline]
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.stack.len()
}
}
impl Default for CheckpointStack {
fn default() -> Self {
Self::new()
}
}