Skip to main content

sim_lib_sequence/mutable/
ordered_table.rs

1/// Policy used to decide whether two table or set keys are equivalent.
2pub trait KeyEquivalence<K> {
3    /// Return whether `left` and `right` identify the same logical key.
4    fn equivalent(&self, left: &K, right: &K) -> bool;
5}
6impl<K, F> KeyEquivalence<K> for F
7where
8    F: Fn(&K, &K) -> bool,
9{
10    fn equivalent(&self, left: &K, right: &K) -> bool {
11        self(left, right)
12    }
13}
14
15#[derive(Clone, Debug)]
16struct OrderedEntry<K, V> {
17    key: K,
18    value: Option<V>,
19}
20
21#[derive(Debug)]
22struct OrderedState<K, V> {
23    entries: Vec<OrderedEntry<K, V>>,
24    live_len: usize,
25    active_iterators: Cell<usize>,
26}
27
28/// Result of an explicit ordered-storage compaction request.
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
30pub enum CompactionResult {
31    /// Live entries were compacted and this many tombstones were removed.
32    Compacted(usize),
33    /// There were no tombstones to remove.
34    NotNeeded,
35    /// An active iterator requires entry positions to remain stable.
36    ActiveIterator,
37    /// The caller's work budget is smaller than the current slot count.
38    BudgetExceeded {
39        /// Number of slots that compaction would inspect at most once.
40        required: usize,
41    },
42}
43
44/// Mutable insertion-ordered table with caller-defined key equivalence.
45///
46/// Replacement retains an entry's logical position. Deletion leaves a
47/// tombstone, and reinserting an equivalent key appends a new entry. Iterators
48/// are live rather than snapshots: they skip entries deleted before visitation
49/// and observe entries appended before iteration ends.
50#[derive(Debug)]
51pub struct OrderedTable<K, V, E> {
52    state: Rc<RefCell<OrderedState<K, V>>>,
53    equivalence: E,
54}
55
56impl<K, V, E> OrderedTable<K, V, E>
57where
58    E: KeyEquivalence<K>,
59{
60    /// Construct an empty table using `equivalence` for all key lookup.
61    pub fn new(equivalence: E) -> Self {
62        Self {
63            state: Rc::new(RefCell::new(OrderedState {
64                entries: Vec::new(),
65                live_len: 0,
66                active_iterators: Cell::new(0),
67            })),
68            equivalence,
69        }
70    }
71
72    /// Return the number of live entries.
73    pub fn len(&self) -> usize {
74        self.state.borrow().live_len
75    }
76
77    /// Return whether the table contains no live entries.
78    pub fn is_empty(&self) -> bool {
79        self.len() == 0
80    }
81
82    /// Return a clone of the value for the equivalent key, if present.
83    pub fn get(&self, key: &K) -> Option<V>
84    where
85        V: Clone,
86    {
87        let state = self.state.borrow();
88        state
89            .entries
90            .iter()
91            .find(|entry| entry.value.is_some() && self.equivalence.equivalent(&entry.key, key))
92            .and_then(|entry| entry.value.clone())
93    }
94
95    /// Insert a key/value pair, returning the replaced value when present.
96    ///
97    /// An equivalent live key is replaced in place. A key equivalent only to a
98    /// tombstone is a new insertion and therefore appears at the end.
99    pub fn insert(&self, key: K, value: V) -> Option<V> {
100        let mut state = self.state.borrow_mut();
101        if let Some(entry) = state
102            .entries
103            .iter_mut()
104            .find(|entry| entry.value.is_some() && self.equivalence.equivalent(&entry.key, &key))
105        {
106            return entry.value.replace(value);
107        }
108        state.entries.push(OrderedEntry {
109            key,
110            value: Some(value),
111        });
112        state.live_len += 1;
113        None
114    }
115
116    /// Delete an equivalent key, returning its value when present.
117    pub fn remove(&self, key: &K) -> Option<V> {
118        let mut state = self.state.borrow_mut();
119        let removed = state
120            .entries
121            .iter_mut()
122            .find(|entry| entry.value.is_some() && self.equivalence.equivalent(&entry.key, key))?
123            .value
124            .take();
125        state.live_len -= 1;
126        removed
127    }
128
129    /// Create a live insertion-order iterator.
130    pub fn iter(&self) -> OrderedTableIter<K, V> {
131        let state = self.state.borrow();
132        state
133            .active_iterators
134            .set(state.active_iterators.get().saturating_add(1));
135        drop(state);
136        OrderedTableIter {
137            state: Rc::clone(&self.state),
138            next_slot: 0,
139        }
140    }
141
142    /// Compact tombstones when doing so is position-safe and within `max_work`.
143    ///
144    /// Work is bounded by the current slot count. The operation is all-or-none:
145    /// it does not begin unless that count fits the supplied budget, and it
146    /// never runs while an iterator holds a position in this table.
147    pub fn compact(&self, max_work: usize) -> CompactionResult {
148        let mut state = self.state.borrow_mut();
149        if state.active_iterators.get() != 0 {
150            return CompactionResult::ActiveIterator;
151        }
152        let required = state.entries.len();
153        if required == state.live_len {
154            return CompactionResult::NotNeeded;
155        }
156        if required > max_work {
157            return CompactionResult::BudgetExceeded { required };
158        }
159        let removed = required - state.live_len;
160        state.entries.retain(|entry| entry.value.is_some());
161        CompactionResult::Compacted(removed)
162    }
163
164    #[cfg(test)]
165    fn slot_len(&self) -> usize {
166        self.state.borrow().entries.len()
167    }
168}
169
170/// Live iterator over cloned insertion-ordered table entries.
171pub struct OrderedTableIter<K, V> {
172    state: Rc<RefCell<OrderedState<K, V>>>,
173    next_slot: usize,
174}
175
176impl<K, V> Clone for OrderedTableIter<K, V> {
177    fn clone(&self) -> Self {
178        let state = self.state.borrow();
179        state
180            .active_iterators
181            .set(state.active_iterators.get().saturating_add(1));
182        drop(state);
183        Self {
184            state: Rc::clone(&self.state),
185            next_slot: self.next_slot,
186        }
187    }
188}
189
190impl<K, V> Iterator for OrderedTableIter<K, V>
191where
192    K: Clone,
193    V: Clone,
194{
195    type Item = (K, V);
196
197    fn next(&mut self) -> Option<Self::Item> {
198        let state = self.state.borrow();
199        while self.next_slot < state.entries.len() {
200            let slot = self.next_slot;
201            self.next_slot += 1;
202            let entry = &state.entries[slot];
203            if let Some(value) = &entry.value {
204                return Some((entry.key.clone(), value.clone()));
205            }
206        }
207        None
208    }
209}
210
211impl<K, V> Drop for OrderedTableIter<K, V> {
212    fn drop(&mut self) {
213        let state = self.state.borrow();
214        state
215            .active_iterators
216            .set(state.active_iterators.get().saturating_sub(1));
217    }
218}