use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use super::types::{
MapNode, PersistentMap, PersistentQueue, PersistentSet, PersistentStack, PersistentVec,
StackNode, VecNode, BRANCHING, BRANCHING_BITS,
};
pub(super) fn hash_one<K: Hash>(k: &K) -> u64 {
let mut h = DefaultHasher::new();
k.hash(&mut h);
h.finish()
}
fn capacity_for_shift(shift: usize) -> usize {
let levels = shift / BRANCHING_BITS + 1; BRANCHING.pow(levels as u32)
}
fn push_into<T: Clone>(
node: &Arc<VecNode<T>>,
shift: usize,
elem_count: usize,
val: T,
) -> VecNode<T> {
match node.as_ref() {
VecNode::Leaf { values } => {
let mut new_vals = values.clone();
new_vals.push(val);
VecNode::Leaf { values: new_vals }
}
VecNode::Internal { children, size } => {
let child_idx = (elem_count >> shift) & (BRANCHING - 1);
let child_capacity = capacity_for_shift(shift - BRANCHING_BITS);
let child_elem_count = elem_count % child_capacity;
if child_idx < children.len() {
let new_child = push_into(
&children[child_idx],
shift - BRANCHING_BITS,
child_elem_count,
val,
);
let mut new_children = children.clone();
new_children[child_idx] = Arc::new(new_child);
VecNode::Internal {
children: new_children,
size: size + 1,
}
} else {
let new_child = build_singleton_spine(val, shift - BRANCHING_BITS);
let mut new_children = children.clone();
new_children.push(Arc::new(new_child));
VecNode::Internal {
children: new_children,
size: size + 1,
}
}
}
}
}
fn build_singleton_spine<T: Clone>(val: T, shift: usize) -> VecNode<T> {
if shift == 0 || shift < BRANCHING_BITS {
VecNode::Leaf { values: vec![val] }
} else {
let child = build_singleton_spine(val, shift - BRANCHING_BITS);
VecNode::Internal {
children: vec![Arc::new(child)],
size: 1,
}
}
}
impl<T: Clone> VecNode<T> {
pub(super) fn size(&self) -> usize {
match self {
VecNode::Internal { size, .. } => *size,
VecNode::Leaf { values } => values.len(),
}
}
pub(super) fn get(&self, idx: usize, shift: usize) -> Option<&T> {
match self {
VecNode::Leaf { values } => values.get(idx),
VecNode::Internal { children, .. } => {
let child_idx = (idx >> shift) & (BRANCHING - 1);
children.get(child_idx).and_then(|child| {
let lower = idx & ((1 << shift) - 1);
if shift >= BRANCHING_BITS {
child.get(lower, shift - BRANCHING_BITS)
} else {
child.get(lower, 0)
}
})
}
}
}
pub(super) fn set(&self, idx: usize, val: T, shift: usize) -> Self {
match self {
VecNode::Leaf { values } => {
let mut new_vals = values.clone();
if idx < new_vals.len() {
new_vals[idx] = val;
}
VecNode::Leaf { values: new_vals }
}
VecNode::Internal { children, size } => {
let child_idx = (idx >> shift) & (BRANCHING - 1);
let mut new_children = children.clone();
if child_idx < new_children.len() {
let lower = idx & ((1 << shift) - 1);
let new_child = if shift >= BRANCHING_BITS {
new_children[child_idx].set(lower, val, shift - BRANCHING_BITS)
} else {
new_children[child_idx].set(lower, val, 0)
};
new_children[child_idx] = Arc::new(new_child);
}
VecNode::Internal {
children: new_children,
size: *size,
}
}
}
}
pub(super) fn push_leaf(&self, val: T, shift: usize, elem_count: usize) -> Option<Self> {
match self {
VecNode::Leaf { values } => {
if values.len() < BRANCHING {
let mut new_vals = values.clone();
new_vals.push(val);
Some(VecNode::Leaf { values: new_vals })
} else {
None }
}
VecNode::Internal { children, size } => {
let child_capacity: usize = if shift > BRANCHING_BITS {
1usize << shift } else {
BRANCHING };
let last_child_elem_count = elem_count % child_capacity;
let last_full = last_child_elem_count == 0 && !children.is_empty();
if !last_full {
if let Some(last) = children.last() {
let child_shift = if shift > BRANCHING_BITS {
shift - BRANCHING_BITS
} else {
0
};
let result =
last.push_leaf(val.clone(), child_shift, last_child_elem_count);
if let Some(new_last) = result {
let mut new_children = children.clone();
let last_idx = new_children.len() - 1;
new_children[last_idx] = Arc::new(new_last);
return Some(VecNode::Internal {
children: new_children,
size: size + 1,
});
}
}
}
if children.len() < BRANCHING {
let new_leaf = Arc::new(VecNode::Leaf { values: vec![val] });
let mut new_children = children.clone();
new_children.push(new_leaf);
Some(VecNode::Internal {
children: new_children,
size: size + 1,
})
} else {
None }
}
}
}
pub(super) fn collect_values<'a>(&'a self, out: &mut Vec<&'a T>) {
match self {
VecNode::Leaf { values } => {
for v in values {
out.push(v);
}
}
VecNode::Internal { children, .. } => {
for child in children {
child.collect_values(out);
}
}
}
}
}
impl<T: Clone> PersistentVec<T> {
pub fn new() -> Self {
PersistentVec {
root: None,
len: 0,
shift: BRANCHING_BITS,
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn get(&self, idx: usize) -> Option<&T> {
if idx >= self.len {
return None;
}
self.root.as_ref().and_then(|r| r.get(idx, self.shift))
}
pub fn push(&self, val: T) -> Self {
let new_len = self.len + 1;
match &self.root {
None => {
let leaf = VecNode::Leaf { values: vec![val] };
PersistentVec {
root: Some(Arc::new(leaf)),
len: new_len,
shift: BRANCHING_BITS,
}
}
Some(root) => {
let capacity = capacity_for_shift(self.shift);
if self.len < capacity {
let new_root = push_into(root, self.shift, self.len, val);
PersistentVec {
root: Some(Arc::new(new_root)),
len: new_len,
shift: self.shift,
}
} else {
let new_shift = self.shift + BRANCHING_BITS;
let spine = build_singleton_spine(val, self.shift);
let new_root = VecNode::Internal {
children: vec![root.clone(), Arc::new(spine)],
size: new_len,
};
PersistentVec {
root: Some(Arc::new(new_root)),
len: new_len,
shift: new_shift,
}
}
}
}
}
pub fn set(&self, idx: usize, val: T) -> Self {
if idx >= self.len {
return self.clone();
}
match &self.root {
None => self.clone(),
Some(root) => {
let new_root = root.set(idx, val, self.shift);
PersistentVec {
root: Some(Arc::new(new_root)),
len: self.len,
shift: self.shift,
}
}
}
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
let mut collected: Vec<&T> = Vec::with_capacity(self.len);
if let Some(root) = &self.root {
root.collect_values(&mut collected);
}
collected.into_iter()
}
}
const HAMT_BITS: u32 = 5;
const HAMT_MASK: u64 = 0x1f;
fn hamt_index(hash: u64, depth: u32) -> usize {
((hash >> (depth * HAMT_BITS)) & HAMT_MASK) as usize
}
fn popcount_below(bitmap: u32, bit: usize) -> usize {
(bitmap & ((1u32 << bit) - 1)).count_ones() as usize
}
impl<K: Clone + Eq + Hash, V: Clone> MapNode<K, V> {
fn lookup<'a>(&'a self, key: &K, hash: u64, depth: u32) -> Option<&'a V> {
match self {
MapNode::Empty => None,
MapNode::Leaf {
key: k,
value,
hash: h,
} => {
if *h == hash && k == key {
Some(value)
} else {
None
}
}
MapNode::Inner { bitmap, children } => {
let bit = hamt_index(hash, depth);
if *bitmap & (1u32 << bit) == 0 {
return None;
}
let pos = popcount_below(*bitmap, bit);
children[pos].lookup(key, hash, depth + 1)
}
}
}
fn insert_node(self: &Arc<Self>, key: K, value: V, hash: u64, depth: u32) -> Arc<Self> {
match self.as_ref() {
MapNode::Empty => Arc::new(MapNode::Leaf { key, value, hash }),
MapNode::Leaf {
key: k,
value: v,
hash: h,
} => {
if *h == hash && *k == key {
return Arc::new(MapNode::Leaf { key, value, hash });
}
let existing = Arc::new(MapNode::Leaf {
key: k.clone(),
value: v.clone(),
hash: *h,
});
let existing_bit = hamt_index(*h, depth);
let new_bit = hamt_index(hash, depth);
if existing_bit == new_bit {
let child = existing.insert_node(key, value, hash, depth + 1);
let bitmap = 1u32 << existing_bit;
Arc::new(MapNode::Inner {
bitmap,
children: vec![child],
})
} else {
let new_leaf = Arc::new(MapNode::Leaf { key, value, hash });
let (bit_a, node_a, bit_b, node_b) = if existing_bit < new_bit {
(existing_bit, existing, new_bit, new_leaf)
} else {
(new_bit, new_leaf, existing_bit, existing)
};
let bitmap = (1u32 << bit_a) | (1u32 << bit_b);
Arc::new(MapNode::Inner {
bitmap,
children: vec![node_a, node_b],
})
}
}
MapNode::Inner { bitmap, children } => {
let bit = hamt_index(hash, depth);
let flag = 1u32 << bit;
let pos = popcount_below(*bitmap, bit);
let mut new_children = children.clone();
if *bitmap & flag == 0 {
let leaf = Arc::new(MapNode::Leaf { key, value, hash });
new_children.insert(pos, leaf);
Arc::new(MapNode::Inner {
bitmap: bitmap | flag,
children: new_children,
})
} else {
new_children[pos] = new_children[pos].insert_node(key, value, hash, depth + 1);
Arc::new(MapNode::Inner {
bitmap: *bitmap,
children: new_children,
})
}
}
}
}
fn remove_node(self: &Arc<Self>, key: &K, hash: u64, depth: u32) -> Option<Arc<Self>> {
match self.as_ref() {
MapNode::Empty => Some(self.clone()),
MapNode::Leaf {
key: k, hash: h, ..
} => {
if *h == hash && k == key {
None
} else {
Some(self.clone())
}
}
MapNode::Inner { bitmap, children } => {
let bit = hamt_index(hash, depth);
let flag = 1u32 << bit;
if *bitmap & flag == 0 {
return Some(self.clone());
}
let pos = popcount_below(*bitmap, bit);
let updated = children[pos].remove_node(key, hash, depth + 1);
let mut new_children = children.clone();
let new_bitmap;
match updated {
None => {
new_children.remove(pos);
new_bitmap = bitmap & !flag;
}
Some(node) => {
new_children[pos] = node;
new_bitmap = *bitmap;
}
}
if new_children.is_empty() {
None
} else {
Some(Arc::new(MapNode::Inner {
bitmap: new_bitmap,
children: new_children,
}))
}
}
}
}
fn count(&self) -> usize {
match self {
MapNode::Empty => 0,
MapNode::Leaf { .. } => 1,
MapNode::Inner { children, .. } => children.iter().map(|c| c.count()).sum(),
}
}
fn collect_keys<'a>(&'a self, out: &mut Vec<&'a K>) {
match self {
MapNode::Empty => {}
MapNode::Leaf { key, .. } => out.push(key),
MapNode::Inner { children, .. } => {
for c in children {
c.collect_keys(out);
}
}
}
}
}
impl<K: Clone + Eq + Hash, V: Clone> PersistentMap<K, V> {
pub fn new() -> Self {
PersistentMap { root: None, len: 0 }
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn get(&self, key: &K) -> Option<&V> {
let hash = hash_one(key);
self.root.as_ref().and_then(|r| r.lookup(key, hash, 0))
}
pub fn contains_key(&self, key: &K) -> bool {
self.get(key).is_some()
}
pub fn insert(&self, key: K, value: V) -> Self {
let hash = hash_one(&key);
let had_key = self.contains_key(&key);
let new_root = match &self.root {
None => Arc::new(MapNode::Leaf { key, value, hash }),
Some(root) => root.insert_node(key, value, hash, 0),
};
let new_len = if had_key { self.len } else { self.len + 1 };
PersistentMap {
root: Some(new_root),
len: new_len,
}
}
pub fn remove(&self, key: &K) -> Self {
if !self.contains_key(key) {
return self.clone();
}
let hash = hash_one(key);
let new_root = self.root.as_ref().and_then(|r| r.remove_node(key, hash, 0));
PersistentMap {
root: new_root,
len: self.len - 1,
}
}
pub fn keys(&self) -> Vec<&K> {
let mut out = Vec::with_capacity(self.len);
if let Some(root) = &self.root {
root.collect_keys(&mut out);
}
out
}
}
impl<T: Clone + Eq + Hash> PersistentSet<T> {
pub fn new() -> Self {
PersistentSet {
map: PersistentMap::new(),
}
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn insert(&self, val: T) -> Self {
PersistentSet {
map: self.map.insert(val, ()),
}
}
pub fn contains(&self, val: &T) -> bool {
self.map.contains_key(val)
}
pub fn remove(&self, val: &T) -> Self {
PersistentSet {
map: self.map.remove(val),
}
}
pub fn union(&self, other: &Self) -> Self {
let mut result = self.clone();
for k in other.map.keys() {
result = result.insert(k.clone());
}
result
}
pub fn intersection(&self, other: &Self) -> Self {
let mut result = PersistentSet::new();
for k in self.map.keys() {
if other.contains(k) {
result = result.insert(k.clone());
}
}
result
}
}
impl<T: Clone> PersistentQueue<T> {
pub fn new() -> Self {
PersistentQueue {
front: Vec::new(),
back: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.front.len() + self.back.len()
}
pub fn is_empty(&self) -> bool {
self.front.is_empty() && self.back.is_empty()
}
pub fn peek(&self) -> Option<&T> {
self.front.first()
}
pub fn push_back(&self, val: T) -> Self {
let mut new_back = self.back.clone();
new_back.push(val);
Self::rebalance(self.front.clone(), new_back)
}
pub fn pop_front(&self) -> Option<(T, Self)> {
if self.front.is_empty() {
return None;
}
let val = self.front[0].clone();
let new_front = self.front[1..].to_vec();
let new_queue = Self::rebalance(new_front, self.back.clone());
Some((val, new_queue))
}
fn rebalance(front: Vec<T>, back: Vec<T>) -> Self {
if front.is_empty() && !back.is_empty() {
PersistentQueue {
front: back,
back: Vec::new(),
}
} else {
PersistentQueue { front, back }
}
}
}
impl<T: Clone> PersistentStack<T> {
pub fn new() -> Self {
PersistentStack { head: None, len: 0 }
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn peek(&self) -> Option<&T> {
self.head.as_ref().map(|n| &n.value)
}
pub fn push(&self, val: T) -> Self {
let node = StackNode {
value: val,
tail: self.head.clone(),
};
PersistentStack {
head: Some(Arc::new(node)),
len: self.len + 1,
}
}
pub fn pop(&self) -> Option<(T, Self)> {
self.head.as_ref().map(|n| {
let val = n.value.clone();
let new_stack = PersistentStack {
head: n.tail.clone(),
len: self.len - 1,
};
(val, new_stack)
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn vec_new_is_empty() {
let v: PersistentVec<i32> = PersistentVec::new();
assert_eq!(v.len(), 0);
assert!(v.is_empty());
}
#[test]
fn vec_push_and_get() {
let v = PersistentVec::new().push(10).push(20).push(30);
assert_eq!(v.len(), 3);
assert_eq!(v.get(0), Some(&10));
assert_eq!(v.get(1), Some(&20));
assert_eq!(v.get(2), Some(&30));
assert_eq!(v.get(3), None);
}
#[test]
fn vec_persistence_after_push() {
let v0 = PersistentVec::new().push(1).push(2);
let v1 = v0.push(3);
assert_eq!(v0.len(), 2);
assert_eq!(v0.get(0), Some(&1));
assert_eq!(v1.len(), 3);
assert_eq!(v1.get(2), Some(&3));
}
#[test]
fn vec_set_persistence() {
let v = PersistentVec::new().push(1).push(2).push(3);
let v2 = v.set(1, 99);
assert_eq!(v.get(1), Some(&2));
assert_eq!(v2.get(1), Some(&99));
assert_eq!(v2.get(0), Some(&1));
assert_eq!(v2.get(2), Some(&3));
}
#[test]
fn vec_set_out_of_bounds() {
let v = PersistentVec::new().push(1);
let v2 = v.set(100, 42);
assert_eq!(v2.len(), 1); }
#[test]
fn vec_iter_order() {
let v = (0..10i32).fold(PersistentVec::new(), |acc, x| acc.push(x));
let collected: Vec<i32> = v.iter().copied().collect();
assert_eq!(collected, (0..10).collect::<Vec<i32>>());
}
#[test]
fn vec_large_push() {
let count = 100usize;
let v = (0..count).fold(PersistentVec::new(), |acc, x| acc.push(x));
assert_eq!(v.len(), count);
for i in 0..count {
assert_eq!(v.get(i), Some(&i));
}
}
#[test]
fn vec_multiple_versions_coexist() {
let v0: PersistentVec<u32> = PersistentVec::new();
let v1 = v0.push(1);
let v2 = v1.push(2);
let v3 = v2.push(3);
assert_eq!(v0.len(), 0);
assert_eq!(v1.len(), 1);
assert_eq!(v2.len(), 2);
assert_eq!(v3.len(), 3);
}
#[test]
fn map_new_is_empty() {
let m: PersistentMap<String, i32> = PersistentMap::new();
assert_eq!(m.len(), 0);
assert!(m.is_empty());
}
#[test]
fn map_insert_and_get() {
let m = PersistentMap::new()
.insert("a".to_string(), 1)
.insert("b".to_string(), 2)
.insert("c".to_string(), 3);
assert_eq!(m.get(&"a".to_string()), Some(&1));
assert_eq!(m.get(&"b".to_string()), Some(&2));
assert_eq!(m.get(&"c".to_string()), Some(&3));
assert_eq!(m.get(&"d".to_string()), None);
}
#[test]
fn map_persistence_after_insert() {
let m0 = PersistentMap::new().insert(1u32, "one".to_string());
let m1 = m0.insert(2u32, "two".to_string());
assert_eq!(m0.len(), 1);
assert_eq!(m0.get(&2), None);
assert_eq!(m1.len(), 2);
assert_eq!(m1.get(&1), Some(&"one".to_string()));
}
#[test]
fn map_update_existing_key() {
let m0 = PersistentMap::new().insert("x".to_string(), 10i32);
let m1 = m0.insert("x".to_string(), 20);
assert_eq!(m1.len(), 1);
assert_eq!(m1.get(&"x".to_string()), Some(&20));
assert_eq!(m0.get(&"x".to_string()), Some(&10));
}
#[test]
fn map_remove() {
let m = PersistentMap::new()
.insert(1u32, "a".to_string())
.insert(2u32, "b".to_string());
let m2 = m.remove(&1);
assert_eq!(m2.len(), 1);
assert_eq!(m2.get(&1), None);
assert_eq!(m2.get(&2), Some(&"b".to_string()));
assert_eq!(m.get(&1), Some(&"a".to_string()));
}
#[test]
fn map_contains_key() {
let m = PersistentMap::new().insert(42u32, true);
assert!(m.contains_key(&42));
assert!(!m.contains_key(&0));
}
#[test]
fn map_large_insert() {
let m = (0u32..50).fold(PersistentMap::new(), |acc, i| acc.insert(i, i * i));
assert_eq!(m.len(), 50);
for i in 0u32..50 {
assert_eq!(m.get(&i), Some(&(i * i)));
}
}
#[test]
fn set_new_is_empty() {
let s: PersistentSet<i32> = PersistentSet::new();
assert!(s.is_empty());
}
#[test]
fn set_insert_and_contains() {
let s = PersistentSet::new().insert(1i32).insert(2).insert(3);
assert!(s.contains(&1));
assert!(s.contains(&2));
assert!(!s.contains(&4));
}
#[test]
fn set_persistence_after_insert() {
let s0 = PersistentSet::new().insert(10i32);
let s1 = s0.insert(20);
assert!(!s0.contains(&20));
assert!(s1.contains(&10));
assert!(s1.contains(&20));
}
#[test]
fn set_remove() {
let s = PersistentSet::new().insert(1i32).insert(2).insert(3);
let s2 = s.remove(&2);
assert!(!s2.contains(&2));
assert!(s2.contains(&1));
assert!(s2.contains(&3));
assert!(s.contains(&2));
}
#[test]
fn set_union() {
let s1 = PersistentSet::new().insert(1i32).insert(2);
let s2 = PersistentSet::new().insert(2i32).insert(3);
let u = s1.union(&s2);
assert!(u.contains(&1));
assert!(u.contains(&2));
assert!(u.contains(&3));
assert_eq!(u.len(), 3);
}
#[test]
fn set_intersection() {
let s1 = PersistentSet::new().insert(1i32).insert(2).insert(3);
let s2 = PersistentSet::new().insert(2i32).insert(3).insert(4);
let inter = s1.intersection(&s2);
assert!(!inter.contains(&1));
assert!(inter.contains(&2));
assert!(inter.contains(&3));
assert!(!inter.contains(&4));
assert_eq!(inter.len(), 2);
}
#[test]
fn queue_new_is_empty() {
let q: PersistentQueue<i32> = PersistentQueue::new();
assert!(q.is_empty());
assert_eq!(q.peek(), None);
}
#[test]
fn queue_push_and_pop() {
let q = PersistentQueue::new()
.push_back(1i32)
.push_back(2)
.push_back(3);
let (v, q2) = q.pop_front().expect("non-empty");
assert_eq!(v, 1);
let (v2, q3) = q2.pop_front().expect("non-empty");
assert_eq!(v2, 2);
let (v3, q4) = q3.pop_front().expect("non-empty");
assert_eq!(v3, 3);
assert!(q4.is_empty());
}
#[test]
fn queue_persistence() {
let q0 = PersistentQueue::new().push_back(10i32).push_back(20);
let (_, q1) = q0.pop_front().expect("non-empty");
assert_eq!(q0.len(), 2);
assert_eq!(q0.peek(), Some(&10));
assert_eq!(q1.len(), 1);
assert_eq!(q1.peek(), Some(&20));
}
#[test]
fn queue_pop_empty() {
let q: PersistentQueue<i32> = PersistentQueue::new();
assert!(q.pop_front().is_none());
}
#[test]
fn queue_fifo_order() {
let q = (0..5i32).fold(PersistentQueue::new(), |acc, x| acc.push_back(x));
let mut current = q;
for expected in 0..5i32 {
let (val, next) = current.pop_front().expect("non-empty");
assert_eq!(val, expected);
current = next;
}
assert!(current.is_empty());
}
#[test]
fn stack_new_is_empty() {
let s: PersistentStack<i32> = PersistentStack::new();
assert!(s.is_empty());
assert_eq!(s.peek(), None);
}
#[test]
fn stack_push_and_pop() {
let s = PersistentStack::new().push(1i32).push(2).push(3);
assert_eq!(s.peek(), Some(&3));
let (v, s2) = s.pop().expect("non-empty");
assert_eq!(v, 3);
let (v2, s3) = s2.pop().expect("non-empty");
assert_eq!(v2, 2);
let (v3, s4) = s3.pop().expect("non-empty");
assert_eq!(v3, 1);
assert!(s4.is_empty());
}
#[test]
fn stack_persistence() {
let s0 = PersistentStack::new().push(10i32).push(20);
let (_, s1) = s0.pop().expect("non-empty");
assert_eq!(s0.len(), 2);
assert_eq!(s0.peek(), Some(&20));
assert_eq!(s1.len(), 1);
assert_eq!(s1.peek(), Some(&10));
}
#[test]
fn stack_pop_empty() {
let s: PersistentStack<i32> = PersistentStack::new();
assert!(s.pop().is_none());
}
#[test]
fn stack_lifo_order() {
let s = (0..5i32).fold(PersistentStack::new(), |acc, x| acc.push(x));
let mut current = s;
for expected in (0..5i32).rev() {
let (val, next) = current.pop().expect("non-empty");
assert_eq!(val, expected);
current = next;
}
assert!(current.is_empty());
}
#[test]
fn stack_multiple_branches_from_same_base() {
let base = PersistentStack::new().push(1i32).push(2);
let branch_a = base.push(10);
let branch_b = base.push(20);
assert_eq!(branch_a.peek(), Some(&10));
assert_eq!(branch_b.peek(), Some(&20));
assert_eq!(base.peek(), Some(&2));
}
}