diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/ena/tests | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ena/tests')
-rw-r--r-- | vendor/ena/tests/external_undo_log.rs | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/vendor/ena/tests/external_undo_log.rs b/vendor/ena/tests/external_undo_log.rs new file mode 100644 index 000000000..2537826c9 --- /dev/null +++ b/vendor/ena/tests/external_undo_log.rs @@ -0,0 +1,202 @@ +#[macro_use] +extern crate log; +extern crate ena; + +use ena::{ + snapshot_vec as sv, + undo_log::{Rollback, Snapshots, UndoLogs}, + unify::{self as ut, EqUnifyValue, UnifyKey}, +}; + +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +struct IntKey(u32); + +impl UnifyKey for IntKey { + type Value = Option<IntKey>; + fn index(&self) -> u32 { + self.0 + } + fn from_index(u: u32) -> IntKey { + IntKey(u) + } + fn tag() -> &'static str { + "IntKey" + } +} + +impl EqUnifyValue for IntKey {} + +enum UndoLog { + EqRelation(sv::UndoLog<ut::Delegate<IntKey>>), + Values(sv::UndoLog<i32>), +} + +impl From<sv::UndoLog<ut::Delegate<IntKey>>> for UndoLog { + fn from(l: sv::UndoLog<ut::Delegate<IntKey>>) -> Self { + UndoLog::EqRelation(l) + } +} + +impl From<sv::UndoLog<i32>> for UndoLog { + fn from(l: sv::UndoLog<i32>) -> Self { + UndoLog::Values(l) + } +} + +impl Rollback<UndoLog> for TypeVariableStorage { + fn reverse(&mut self, undo: UndoLog) { + match undo { + UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo), + UndoLog::Values(undo) => self.values.reverse(undo), + } + } +} + +#[derive(Default)] +struct TypeVariableStorage { + values: sv::SnapshotVecStorage<i32>, + + eq_relations: ut::UnificationTableStorage<IntKey>, +} + +impl TypeVariableStorage { + fn with_log<'a>(&'a mut self, undo_log: &'a mut TypeVariableUndoLogs) -> TypeVariableTable<'a> { + TypeVariableTable { + storage: self, + undo_log, + } + } + + fn len(&mut self) -> usize { + assert_eq!(self.values.len(), self.eq_relations.len()); + self.values.len() + } +} + +struct TypeVariableTable<'a> { + storage: &'a mut TypeVariableStorage, + + undo_log: &'a mut TypeVariableUndoLogs, +} + +impl TypeVariableTable<'_> { + fn new(&mut self, i: i32) -> IntKey { + self.storage.values.with_log(&mut self.undo_log).push(i); + self.storage + .eq_relations + .with_log(&mut self.undo_log) + .new_key(None) + } +} + +struct Snapshot { + undo_len: usize, +} + +struct TypeVariableUndoLogs { + logs: Vec<UndoLog>, + num_open_snapshots: usize, +} + +impl Default for TypeVariableUndoLogs { + fn default() -> Self { + Self { + logs: Default::default(), + num_open_snapshots: Default::default(), + } + } +} + +impl<T> UndoLogs<T> for TypeVariableUndoLogs +where + UndoLog: From<T>, +{ + fn num_open_snapshots(&self) -> usize { + self.num_open_snapshots + } + fn push(&mut self, undo: T) { + if self.in_snapshot() { + self.logs.push(undo.into()) + } + } + fn clear(&mut self) { + self.logs.clear(); + self.num_open_snapshots = 0; + } + fn extend<J>(&mut self, undos: J) + where + Self: Sized, + J: IntoIterator<Item = T>, + { + if self.in_snapshot() { + self.logs.extend(undos.into_iter().map(UndoLog::from)) + } + } +} + +impl Snapshots<UndoLog> for TypeVariableUndoLogs { + type Snapshot = Snapshot; + fn actions_since_snapshot(&self, snapshot: &Self::Snapshot) -> &[UndoLog] { + &self.logs[snapshot.undo_len..] + } + + fn start_snapshot(&mut self) -> Self::Snapshot { + self.num_open_snapshots += 1; + Snapshot { + undo_len: self.logs.len(), + } + } + + fn rollback_to<R>(&mut self, values: impl FnOnce() -> R, snapshot: Self::Snapshot) + where + R: Rollback<UndoLog>, + { + debug!("rollback_to({})", snapshot.undo_len); + + if self.logs.len() > snapshot.undo_len { + let mut values = values(); + while self.logs.len() > snapshot.undo_len { + values.reverse(self.logs.pop().unwrap()); + } + } + + if self.num_open_snapshots == 1 { + // The root snapshot. It's safe to clear the undo log because + // there's no snapshot further out that we might need to roll back + // to. + assert!(snapshot.undo_len == 0); + self.logs.clear(); + } + + self.num_open_snapshots -= 1; + } + + fn commit(&mut self, snapshot: Self::Snapshot) { + debug!("commit({})", snapshot.undo_len); + + if self.num_open_snapshots == 1 { + // The root snapshot. It's safe to clear the undo log because + // there's no snapshot further out that we might need to roll back + // to. + assert!(snapshot.undo_len == 0); + self.logs.clear(); + } + + self.num_open_snapshots -= 1; + } +} + +/// Tests that a undo log stored externally can be used with TypeVariableTable +#[test] +fn external_undo_log() { + let mut storage = TypeVariableStorage::default(); + let mut undo_log = TypeVariableUndoLogs::default(); + + let snapshot = undo_log.start_snapshot(); + storage.with_log(&mut undo_log).new(1); + storage.with_log(&mut undo_log).new(2); + assert_eq!(storage.len(), 2); + + undo_log.rollback_to(|| &mut storage, snapshot); + assert_eq!(storage.len(), 0); +} |