yggdrasil_rt/enhance/
stack.rs

1// pest. The Elegant Parser
2// Copyright (c) 2018 DragoČ™ Tiselice
3//
4// Licensed under the Apache License, Version 2.0
5// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
6// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. All files in the project carrying such notice may not be copied,
8// modified, or distributed except according to those terms.
9
10use alloc::{vec, vec::Vec};
11use core::ops::{Index, Range};
12
13/// Implementation of a `Stack` which maintains popped elements and length of previous states
14/// in order to rewind the stack to a previous state.
15#[derive(Debug)]
16pub struct Stack<T: Clone> {
17    /// All elements in the stack.
18    cache: Vec<T>,
19    /// All elements that are in previous snapshots but may not be in the next state.
20    /// They will be pushed back to `cache` if the snapshot is restored,
21    /// otherwise be dropped if the snapshot is cleared.
22    ///
23    /// Those elements from a sequence of snapshots are stacked in one [`Vec`], and
24    /// `popped.len() == lengths.iter().map(|(len, remained)| len - remained).sum()`
25    popped: Vec<T>,
26    /// Every element corresponds to a snapshot, and each element has two fields:
27    /// - Length of `cache` when corresponding snapshot is taken (AKA `len`).
28    /// - Count of elements that come from corresponding snapshot
29    ///   and are still in next snapshot or current state (AKA `remained`).
30    ///
31    /// And `len` is never less than `remained`.
32    ///
33    /// On restoring, the `cache` can be divided into two parts:
34    /// - `0..remained` are untouched since the snapshot is taken.
35    ///
36    ///   There's nothing to do with those elements. Just let them stay where they are.
37    ///
38    /// - `remained..cache.len()` are pushed after the snapshot is taken.
39    lengths: Vec<(usize, usize)>,
40}
41
42impl<T: Clone> Default for Stack<T> {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48impl<T: Clone> Stack<T> {
49    /// Creates a new `Stack`.
50    pub fn new() -> Self {
51        Stack { cache: vec![], popped: vec![], lengths: vec![] }
52    }
53
54    /// Returns `true` if the stack is currently empty.
55    #[allow(dead_code)]
56    pub fn is_empty(&self) -> bool {
57        self.cache.is_empty()
58    }
59
60    /// Returns the top-most `&T` in the `Stack`.
61    pub fn peek(&self) -> Option<&T> {
62        self.cache.last()
63    }
64
65    /// Pushes a `T` onto the `Stack`.
66    pub fn push(&mut self, elem: T) {
67        self.cache.push(elem);
68    }
69
70    /// Pops the top-most `T` from the `Stack`.
71    pub fn pop(&mut self) -> Option<T> {
72        let len = self.cache.len();
73        let popped = self.cache.pop();
74        if let Some(popped) = &popped {
75            if let Some((_, remained_count)) = self.lengths.last_mut() {
76                // `len >= *unpopped_count`
77                if len == *remained_count {
78                    *remained_count -= 1;
79                    self.popped.push(popped.clone());
80                }
81            }
82        }
83        popped
84    }
85
86    /// Returns the size of the stack
87    pub fn len(&self) -> usize {
88        self.cache.len()
89    }
90
91    /// Takes a snapshot of the current `Stack`.
92    pub fn snapshot(&mut self) {
93        self.lengths.push((self.cache.len(), self.cache.len()))
94    }
95
96    /// The parsing after the last snapshot was successful so clearing it.
97    pub fn clear_snapshot(&mut self) {
98        if let Some((len, unpopped)) = self.lengths.pop() {
99            // Popped elements from previous state are no longer needed.
100            self.popped.truncate(self.popped.len() - (len - unpopped));
101        }
102    }
103
104    /// Rewinds the `Stack` to the most recent `snapshot()`. If no `snapshot()` has been taken, this
105    /// function return the stack to its initial state.
106    pub fn restore(&mut self) {
107        match self.lengths.pop() {
108            Some((len_stack, remained)) => {
109                if remained < self.cache.len() {
110                    // Remove those elements that are pushed after the snapshot.
111                    self.cache.truncate(remained);
112                }
113                if len_stack > remained {
114                    let rewind_count = len_stack - remained;
115                    let new_len = self.popped.len() - rewind_count;
116                    let recovered_elements = self.popped.drain(new_len..);
117                    self.cache.extend(recovered_elements.rev());
118                    debug_assert_eq!(self.popped.len(), new_len);
119                }
120            }
121            None => {
122                self.cache.clear();
123                // As `self.popped` and `self.lengths` should already be empty,
124                // there is no need to clear it.
125                debug_assert!(self.popped.is_empty());
126                debug_assert!(self.lengths.is_empty());
127            }
128        }
129    }
130}
131
132impl<T: Clone> Index<Range<usize>> for Stack<T> {
133    type Output = [T];
134
135    fn index(&self, range: Range<usize>) -> &[T] {
136        self.cache.index(range)
137    }
138}