Skip to main content

oxilean_std/persistent_data_structures/
functions.rs

1//! Persistent (immutable) data structures — implementations and tests.
2
3use std::collections::hash_map::DefaultHasher;
4use std::hash::{Hash, Hasher};
5use std::sync::Arc;
6
7use super::types::{
8    MapNode, PersistentMap, PersistentQueue, PersistentSet, PersistentStack, PersistentVec,
9    StackNode, VecNode, BRANCHING, BRANCHING_BITS,
10};
11
12// ── helpers ───────────────────────────────────────────────────────────────────
13
14pub(super) fn hash_one<K: Hash>(k: &K) -> u64 {
15    let mut h = DefaultHasher::new();
16    k.hash(&mut h);
17    h.finish()
18}
19
20/// Maximum number of elements a tree of the given `shift` depth can hold.
21///
22/// At `shift = BRANCHING_BITS` (single level) the root is an Internal with
23/// up to BRANCHING leaf children → capacity = BRANCHING * BRANCHING.
24/// More generally: capacity = BRANCHING^(shift/BRANCHING_BITS + 1).
25fn capacity_for_shift(shift: usize) -> usize {
26    let levels = shift / BRANCHING_BITS + 1; // number of tree levels (leaves count as 1)
27    BRANCHING.pow(levels as u32)
28}
29
30/// Insert `val` as the element at position `elem_count` (0-indexed) into `node`.
31///
32/// Precondition: the subtree has room for one more element.
33fn push_into<T: Clone>(
34    node: &Arc<VecNode<T>>,
35    shift: usize,
36    elem_count: usize,
37    val: T,
38) -> VecNode<T> {
39    match node.as_ref() {
40        VecNode::Leaf { values } => {
41            // The leaf has room (precondition ensures this).
42            let mut new_vals = values.clone();
43            new_vals.push(val);
44            VecNode::Leaf { values: new_vals }
45        }
46        VecNode::Internal { children, size } => {
47            // Determine which child the new element belongs to.
48            let child_idx = (elem_count >> shift) & (BRANCHING - 1);
49            let child_capacity = capacity_for_shift(shift - BRANCHING_BITS);
50            let child_elem_count = elem_count % child_capacity;
51
52            if child_idx < children.len() {
53                // Recurse into the existing child.
54                let new_child = push_into(
55                    &children[child_idx],
56                    shift - BRANCHING_BITS,
57                    child_elem_count,
58                    val,
59                );
60                let mut new_children = children.clone();
61                new_children[child_idx] = Arc::new(new_child);
62                VecNode::Internal {
63                    children: new_children,
64                    size: size + 1,
65                }
66            } else {
67                // Need a new child (a singleton spine).
68                let new_child = build_singleton_spine(val, shift - BRANCHING_BITS);
69                let mut new_children = children.clone();
70                new_children.push(Arc::new(new_child));
71                VecNode::Internal {
72                    children: new_children,
73                    size: size + 1,
74                }
75            }
76        }
77    }
78}
79
80/// Build a spine of Internal nodes down to a single-element Leaf containing `val`.
81///
82/// `shift` is the shift of the node to build (not the parent's shift).
83/// - shift == 0 (leaf level): returns Leaf([val])
84/// - shift > 0 (internal level): returns Internal(\[build_singleton_spine(val, shift - BRANCHING_BITS)\])
85fn build_singleton_spine<T: Clone>(val: T, shift: usize) -> VecNode<T> {
86    if shift == 0 || shift < BRANCHING_BITS {
87        VecNode::Leaf { values: vec![val] }
88    } else {
89        let child = build_singleton_spine(val, shift - BRANCHING_BITS);
90        VecNode::Internal {
91            children: vec![Arc::new(child)],
92            size: 1,
93        }
94    }
95}
96
97// ── VecNode helpers ───────────────────────────────────────────────────────────
98
99impl<T: Clone> VecNode<T> {
100    pub(super) fn size(&self) -> usize {
101        match self {
102            VecNode::Internal { size, .. } => *size,
103            VecNode::Leaf { values } => values.len(),
104        }
105    }
106
107    pub(super) fn get(&self, idx: usize, shift: usize) -> Option<&T> {
108        match self {
109            VecNode::Leaf { values } => values.get(idx),
110            VecNode::Internal { children, .. } => {
111                let child_idx = (idx >> shift) & (BRANCHING - 1);
112                children.get(child_idx).and_then(|child| {
113                    let lower = idx & ((1 << shift) - 1);
114                    if shift >= BRANCHING_BITS {
115                        child.get(lower, shift - BRANCHING_BITS)
116                    } else {
117                        child.get(lower, 0)
118                    }
119                })
120            }
121        }
122    }
123
124    pub(super) fn set(&self, idx: usize, val: T, shift: usize) -> Self {
125        match self {
126            VecNode::Leaf { values } => {
127                let mut new_vals = values.clone();
128                if idx < new_vals.len() {
129                    new_vals[idx] = val;
130                }
131                VecNode::Leaf { values: new_vals }
132            }
133            VecNode::Internal { children, size } => {
134                let child_idx = (idx >> shift) & (BRANCHING - 1);
135                let mut new_children = children.clone();
136                if child_idx < new_children.len() {
137                    let lower = idx & ((1 << shift) - 1);
138                    let new_child = if shift >= BRANCHING_BITS {
139                        new_children[child_idx].set(lower, val, shift - BRANCHING_BITS)
140                    } else {
141                        new_children[child_idx].set(lower, val, 0)
142                    };
143                    new_children[child_idx] = Arc::new(new_child);
144                }
145                VecNode::Internal {
146                    children: new_children,
147                    size: *size,
148                }
149            }
150        }
151    }
152
153    /// Push `val` into the tree.
154    ///
155    /// `elem_count` is the total number of elements currently in the subtree.
156    /// `shift` is the current level's bit-shift.
157    /// Returns the updated node, or `None` if this subtree is completely full.
158    pub(super) fn push_leaf(&self, val: T, shift: usize, elem_count: usize) -> Option<Self> {
159        match self {
160            VecNode::Leaf { values } => {
161                if values.len() < BRANCHING {
162                    let mut new_vals = values.clone();
163                    new_vals.push(val);
164                    Some(VecNode::Leaf { values: new_vals })
165                } else {
166                    None // leaf is full
167                }
168            }
169            VecNode::Internal { children, size } => {
170                // Capacity of a single child subtree at the next level down.
171                // At shift=BRANCHING_BITS, the child is a leaf: capacity = BRANCHING.
172                // At shift>BRANCHING_BITS, child is internal: capacity = BRANCHING^(shift/BRANCHING_BITS).
173                let child_capacity: usize = if shift > BRANCHING_BITS {
174                    1usize << shift // each child covers 2^shift elements
175                } else {
176                    BRANCHING // each child is a leaf
177                };
178
179                let last_child_elem_count = elem_count % child_capacity;
180                // If last_child_elem_count == 0 the last child is either full or absent.
181                let last_full = last_child_elem_count == 0 && !children.is_empty();
182
183                if !last_full {
184                    // Try to append into the last child.
185                    if let Some(last) = children.last() {
186                        let child_shift = if shift > BRANCHING_BITS {
187                            shift - BRANCHING_BITS
188                        } else {
189                            0
190                        };
191                        let result =
192                            last.push_leaf(val.clone(), child_shift, last_child_elem_count);
193                        if let Some(new_last) = result {
194                            let mut new_children = children.clone();
195                            let last_idx = new_children.len() - 1;
196                            new_children[last_idx] = Arc::new(new_last);
197                            return Some(VecNode::Internal {
198                                children: new_children,
199                                size: size + 1,
200                            });
201                        }
202                    }
203                }
204
205                // Last child is full (or absent) — add a new child if there is room.
206                if children.len() < BRANCHING {
207                    let new_leaf = Arc::new(VecNode::Leaf { values: vec![val] });
208                    let mut new_children = children.clone();
209                    new_children.push(new_leaf);
210                    Some(VecNode::Internal {
211                        children: new_children,
212                        size: size + 1,
213                    })
214                } else {
215                    None // this internal node is also full
216                }
217            }
218        }
219    }
220
221    /// Collect all values in order.
222    pub(super) fn collect_values<'a>(&'a self, out: &mut Vec<&'a T>) {
223        match self {
224            VecNode::Leaf { values } => {
225                for v in values {
226                    out.push(v);
227                }
228            }
229            VecNode::Internal { children, .. } => {
230                for child in children {
231                    child.collect_values(out);
232                }
233            }
234        }
235    }
236}
237
238// ── PersistentVec ─────────────────────────────────────────────────────────────
239
240impl<T: Clone> PersistentVec<T> {
241    /// Create an empty persistent vector.
242    pub fn new() -> Self {
243        PersistentVec {
244            root: None,
245            len: 0,
246            shift: BRANCHING_BITS,
247        }
248    }
249
250    /// Return the number of elements.
251    pub fn len(&self) -> usize {
252        self.len
253    }
254
255    /// Return true if empty.
256    pub fn is_empty(&self) -> bool {
257        self.len == 0
258    }
259
260    /// Return the element at `idx`, or `None` if out of bounds.
261    pub fn get(&self, idx: usize) -> Option<&T> {
262        if idx >= self.len {
263            return None;
264        }
265        self.root.as_ref().and_then(|r| r.get(idx, self.shift))
266    }
267
268    /// Return a new vector with `val` appended.
269    pub fn push(&self, val: T) -> Self {
270        let new_len = self.len + 1;
271        match &self.root {
272            None => {
273                let leaf = VecNode::Leaf { values: vec![val] };
274                PersistentVec {
275                    root: Some(Arc::new(leaf)),
276                    len: new_len,
277                    shift: BRANCHING_BITS,
278                }
279            }
280            Some(root) => {
281                // Check if the current tree (of depth determined by `shift`) has room.
282                // Capacity at the current shift = BRANCHING^(shift/BRANCHING_BITS + 1).
283                let capacity = capacity_for_shift(self.shift);
284                if self.len < capacity {
285                    // There is room; descend and add.
286                    let new_root = push_into(root, self.shift, self.len, val);
287                    PersistentVec {
288                        root: Some(Arc::new(new_root)),
289                        len: new_len,
290                        shift: self.shift,
291                    }
292                } else {
293                    // Root is full — grow the tree by one level.
294                    let new_shift = self.shift + BRANCHING_BITS;
295                    // The new element will be the first element under the second child.
296                    // We need a spine of Internal nodes from the new root's child level
297                    // down to a Leaf containing just `val`.
298                    let spine = build_singleton_spine(val, self.shift);
299                    let new_root = VecNode::Internal {
300                        children: vec![root.clone(), Arc::new(spine)],
301                        size: new_len,
302                    };
303                    PersistentVec {
304                        root: Some(Arc::new(new_root)),
305                        len: new_len,
306                        shift: new_shift,
307                    }
308                }
309            }
310        }
311    }
312
313    /// Return a new vector with the element at `idx` replaced by `val`.
314    ///
315    /// Returns the original vector unchanged if `idx` is out of bounds.
316    pub fn set(&self, idx: usize, val: T) -> Self {
317        if idx >= self.len {
318            return self.clone();
319        }
320        match &self.root {
321            None => self.clone(),
322            Some(root) => {
323                let new_root = root.set(idx, val, self.shift);
324                PersistentVec {
325                    root: Some(Arc::new(new_root)),
326                    len: self.len,
327                    shift: self.shift,
328                }
329            }
330        }
331    }
332
333    /// Iterate over all elements in order.
334    pub fn iter(&self) -> impl Iterator<Item = &T> {
335        let mut collected: Vec<&T> = Vec::with_capacity(self.len);
336        if let Some(root) = &self.root {
337            root.collect_values(&mut collected);
338        }
339        collected.into_iter()
340    }
341}
342
343// ── MapNode helpers ───────────────────────────────────────────────────────────
344
345/// Number of bits used per HAMT level.
346const HAMT_BITS: u32 = 5;
347/// Mask for one HAMT level.
348const HAMT_MASK: u64 = 0x1f;
349
350fn hamt_index(hash: u64, depth: u32) -> usize {
351    ((hash >> (depth * HAMT_BITS)) & HAMT_MASK) as usize
352}
353
354fn popcount_below(bitmap: u32, bit: usize) -> usize {
355    (bitmap & ((1u32 << bit) - 1)).count_ones() as usize
356}
357
358impl<K: Clone + Eq + Hash, V: Clone> MapNode<K, V> {
359    fn lookup<'a>(&'a self, key: &K, hash: u64, depth: u32) -> Option<&'a V> {
360        match self {
361            MapNode::Empty => None,
362            MapNode::Leaf {
363                key: k,
364                value,
365                hash: h,
366            } => {
367                if *h == hash && k == key {
368                    Some(value)
369                } else {
370                    None
371                }
372            }
373            MapNode::Inner { bitmap, children } => {
374                let bit = hamt_index(hash, depth);
375                if *bitmap & (1u32 << bit) == 0 {
376                    return None;
377                }
378                let pos = popcount_below(*bitmap, bit);
379                children[pos].lookup(key, hash, depth + 1)
380            }
381        }
382    }
383
384    fn insert_node(self: &Arc<Self>, key: K, value: V, hash: u64, depth: u32) -> Arc<Self> {
385        match self.as_ref() {
386            MapNode::Empty => Arc::new(MapNode::Leaf { key, value, hash }),
387            MapNode::Leaf {
388                key: k,
389                value: v,
390                hash: h,
391            } => {
392                if *h == hash && *k == key {
393                    // Replace
394                    return Arc::new(MapNode::Leaf { key, value, hash });
395                }
396                // Collision — expand into Inner
397                let existing = Arc::new(MapNode::Leaf {
398                    key: k.clone(),
399                    value: v.clone(),
400                    hash: *h,
401                });
402                let existing_bit = hamt_index(*h, depth);
403                let new_bit = hamt_index(hash, depth);
404                if existing_bit == new_bit {
405                    // Same slot — recurse deeper
406                    let child = existing.insert_node(key, value, hash, depth + 1);
407                    let bitmap = 1u32 << existing_bit;
408                    Arc::new(MapNode::Inner {
409                        bitmap,
410                        children: vec![child],
411                    })
412                } else {
413                    let new_leaf = Arc::new(MapNode::Leaf { key, value, hash });
414                    let (bit_a, node_a, bit_b, node_b) = if existing_bit < new_bit {
415                        (existing_bit, existing, new_bit, new_leaf)
416                    } else {
417                        (new_bit, new_leaf, existing_bit, existing)
418                    };
419                    let bitmap = (1u32 << bit_a) | (1u32 << bit_b);
420                    Arc::new(MapNode::Inner {
421                        bitmap,
422                        children: vec![node_a, node_b],
423                    })
424                }
425            }
426            MapNode::Inner { bitmap, children } => {
427                let bit = hamt_index(hash, depth);
428                let flag = 1u32 << bit;
429                let pos = popcount_below(*bitmap, bit);
430                let mut new_children = children.clone();
431                if *bitmap & flag == 0 {
432                    // New slot
433                    let leaf = Arc::new(MapNode::Leaf { key, value, hash });
434                    new_children.insert(pos, leaf);
435                    Arc::new(MapNode::Inner {
436                        bitmap: bitmap | flag,
437                        children: new_children,
438                    })
439                } else {
440                    // Existing slot
441                    new_children[pos] = new_children[pos].insert_node(key, value, hash, depth + 1);
442                    Arc::new(MapNode::Inner {
443                        bitmap: *bitmap,
444                        children: new_children,
445                    })
446                }
447            }
448        }
449    }
450
451    fn remove_node(self: &Arc<Self>, key: &K, hash: u64, depth: u32) -> Option<Arc<Self>> {
452        match self.as_ref() {
453            MapNode::Empty => Some(self.clone()),
454            MapNode::Leaf {
455                key: k, hash: h, ..
456            } => {
457                if *h == hash && k == key {
458                    None
459                } else {
460                    Some(self.clone())
461                }
462            }
463            MapNode::Inner { bitmap, children } => {
464                let bit = hamt_index(hash, depth);
465                let flag = 1u32 << bit;
466                if *bitmap & flag == 0 {
467                    return Some(self.clone());
468                }
469                let pos = popcount_below(*bitmap, bit);
470                let updated = children[pos].remove_node(key, hash, depth + 1);
471                let mut new_children = children.clone();
472                let new_bitmap;
473                match updated {
474                    None => {
475                        new_children.remove(pos);
476                        new_bitmap = bitmap & !flag;
477                    }
478                    Some(node) => {
479                        new_children[pos] = node;
480                        new_bitmap = *bitmap;
481                    }
482                }
483                if new_children.is_empty() {
484                    None
485                } else {
486                    Some(Arc::new(MapNode::Inner {
487                        bitmap: new_bitmap,
488                        children: new_children,
489                    }))
490                }
491            }
492        }
493    }
494
495    fn count(&self) -> usize {
496        match self {
497            MapNode::Empty => 0,
498            MapNode::Leaf { .. } => 1,
499            MapNode::Inner { children, .. } => children.iter().map(|c| c.count()).sum(),
500        }
501    }
502
503    fn collect_keys<'a>(&'a self, out: &mut Vec<&'a K>) {
504        match self {
505            MapNode::Empty => {}
506            MapNode::Leaf { key, .. } => out.push(key),
507            MapNode::Inner { children, .. } => {
508                for c in children {
509                    c.collect_keys(out);
510                }
511            }
512        }
513    }
514}
515
516// ── PersistentMap ─────────────────────────────────────────────────────────────
517
518impl<K: Clone + Eq + Hash, V: Clone> PersistentMap<K, V> {
519    /// Create an empty map.
520    pub fn new() -> Self {
521        PersistentMap { root: None, len: 0 }
522    }
523
524    /// Number of entries.
525    pub fn len(&self) -> usize {
526        self.len
527    }
528
529    /// True if empty.
530    pub fn is_empty(&self) -> bool {
531        self.len == 0
532    }
533
534    /// Look up a key.
535    pub fn get(&self, key: &K) -> Option<&V> {
536        let hash = hash_one(key);
537        self.root.as_ref().and_then(|r| r.lookup(key, hash, 0))
538    }
539
540    /// Return true if the map contains `key`.
541    pub fn contains_key(&self, key: &K) -> bool {
542        self.get(key).is_some()
543    }
544
545    /// Return a new map with `(key, value)` inserted (or updated).
546    pub fn insert(&self, key: K, value: V) -> Self {
547        let hash = hash_one(&key);
548        let had_key = self.contains_key(&key);
549        let new_root = match &self.root {
550            None => Arc::new(MapNode::Leaf { key, value, hash }),
551            Some(root) => root.insert_node(key, value, hash, 0),
552        };
553        let new_len = if had_key { self.len } else { self.len + 1 };
554        PersistentMap {
555            root: Some(new_root),
556            len: new_len,
557        }
558    }
559
560    /// Return a new map with `key` removed.
561    pub fn remove(&self, key: &K) -> Self {
562        if !self.contains_key(key) {
563            return self.clone();
564        }
565        let hash = hash_one(key);
566        let new_root = self.root.as_ref().and_then(|r| r.remove_node(key, hash, 0));
567        PersistentMap {
568            root: new_root,
569            len: self.len - 1,
570        }
571    }
572
573    /// Iterate over keys.
574    pub fn keys(&self) -> Vec<&K> {
575        let mut out = Vec::with_capacity(self.len);
576        if let Some(root) = &self.root {
577            root.collect_keys(&mut out);
578        }
579        out
580    }
581}
582
583// ── PersistentSet ─────────────────────────────────────────────────────────────
584
585impl<T: Clone + Eq + Hash> PersistentSet<T> {
586    /// Create an empty set.
587    pub fn new() -> Self {
588        PersistentSet {
589            map: PersistentMap::new(),
590        }
591    }
592
593    /// Number of elements.
594    pub fn len(&self) -> usize {
595        self.map.len()
596    }
597
598    /// True if empty.
599    pub fn is_empty(&self) -> bool {
600        self.map.is_empty()
601    }
602
603    /// Return a new set with `val` inserted.
604    pub fn insert(&self, val: T) -> Self {
605        PersistentSet {
606            map: self.map.insert(val, ()),
607        }
608    }
609
610    /// Return true if `val` is in the set.
611    pub fn contains(&self, val: &T) -> bool {
612        self.map.contains_key(val)
613    }
614
615    /// Return a new set with `val` removed.
616    pub fn remove(&self, val: &T) -> Self {
617        PersistentSet {
618            map: self.map.remove(val),
619        }
620    }
621
622    /// Return the union of `self` and `other`.
623    pub fn union(&self, other: &Self) -> Self {
624        let mut result = self.clone();
625        for k in other.map.keys() {
626            result = result.insert(k.clone());
627        }
628        result
629    }
630
631    /// Return the intersection of `self` and `other`.
632    pub fn intersection(&self, other: &Self) -> Self {
633        let mut result = PersistentSet::new();
634        for k in self.map.keys() {
635            if other.contains(k) {
636                result = result.insert(k.clone());
637            }
638        }
639        result
640    }
641}
642
643// ── PersistentQueue ───────────────────────────────────────────────────────────
644
645impl<T: Clone> PersistentQueue<T> {
646    /// Create an empty queue.
647    pub fn new() -> Self {
648        PersistentQueue {
649            front: Vec::new(),
650            back: Vec::new(),
651        }
652    }
653
654    /// Number of elements.
655    pub fn len(&self) -> usize {
656        self.front.len() + self.back.len()
657    }
658
659    /// True if empty.
660    pub fn is_empty(&self) -> bool {
661        self.front.is_empty() && self.back.is_empty()
662    }
663
664    /// Peek at the front element without removing it.
665    pub fn peek(&self) -> Option<&T> {
666        self.front.first()
667    }
668
669    /// Return a new queue with `val` added at the back.
670    pub fn push_back(&self, val: T) -> Self {
671        let mut new_back = self.back.clone();
672        new_back.push(val);
673        Self::rebalance(self.front.clone(), new_back)
674    }
675
676    /// Remove and return the front element together with the resulting queue.
677    ///
678    /// Returns `None` if the queue is empty.
679    pub fn pop_front(&self) -> Option<(T, Self)> {
680        if self.front.is_empty() {
681            return None;
682        }
683        let val = self.front[0].clone();
684        let new_front = self.front[1..].to_vec();
685        let new_queue = Self::rebalance(new_front, self.back.clone());
686        Some((val, new_queue))
687    }
688
689    /// Maintain the invariant: if front is empty but back is not, move back into front.
690    ///
691    /// `back` stores elements in insertion order (oldest first at index 0).
692    /// When front is exhausted, we move back directly into front (no reversal).
693    fn rebalance(front: Vec<T>, back: Vec<T>) -> Self {
694        if front.is_empty() && !back.is_empty() {
695            PersistentQueue {
696                front: back,
697                back: Vec::new(),
698            }
699        } else {
700            PersistentQueue { front, back }
701        }
702    }
703}
704
705// ── PersistentStack ───────────────────────────────────────────────────────────
706
707impl<T: Clone> PersistentStack<T> {
708    /// Create an empty stack.
709    pub fn new() -> Self {
710        PersistentStack { head: None, len: 0 }
711    }
712
713    /// Number of elements.
714    pub fn len(&self) -> usize {
715        self.len
716    }
717
718    /// True if empty.
719    pub fn is_empty(&self) -> bool {
720        self.len == 0
721    }
722
723    /// Peek at the top element.
724    pub fn peek(&self) -> Option<&T> {
725        self.head.as_ref().map(|n| &n.value)
726    }
727
728    /// Return a new stack with `val` pushed on top.
729    pub fn push(&self, val: T) -> Self {
730        let node = StackNode {
731            value: val,
732            tail: self.head.clone(),
733        };
734        PersistentStack {
735            head: Some(Arc::new(node)),
736            len: self.len + 1,
737        }
738    }
739
740    /// Pop the top element, returning it and the resulting stack.
741    ///
742    /// Returns `None` if the stack is empty.
743    pub fn pop(&self) -> Option<(T, Self)> {
744        self.head.as_ref().map(|n| {
745            let val = n.value.clone();
746            let new_stack = PersistentStack {
747                head: n.tail.clone(),
748                len: self.len - 1,
749            };
750            (val, new_stack)
751        })
752    }
753}
754
755// ── Tests ─────────────────────────────────────────────────────────────────────
756
757#[cfg(test)]
758mod tests {
759    use super::*;
760
761    // ── PersistentVec tests ───────────────────────────────────────────────────
762
763    #[test]
764    fn vec_new_is_empty() {
765        let v: PersistentVec<i32> = PersistentVec::new();
766        assert_eq!(v.len(), 0);
767        assert!(v.is_empty());
768    }
769
770    #[test]
771    fn vec_push_and_get() {
772        let v = PersistentVec::new().push(10).push(20).push(30);
773        assert_eq!(v.len(), 3);
774        assert_eq!(v.get(0), Some(&10));
775        assert_eq!(v.get(1), Some(&20));
776        assert_eq!(v.get(2), Some(&30));
777        assert_eq!(v.get(3), None);
778    }
779
780    #[test]
781    fn vec_persistence_after_push() {
782        let v0 = PersistentVec::new().push(1).push(2);
783        let v1 = v0.push(3);
784        // v0 is unaffected
785        assert_eq!(v0.len(), 2);
786        assert_eq!(v0.get(0), Some(&1));
787        assert_eq!(v1.len(), 3);
788        assert_eq!(v1.get(2), Some(&3));
789    }
790
791    #[test]
792    fn vec_set_persistence() {
793        let v = PersistentVec::new().push(1).push(2).push(3);
794        let v2 = v.set(1, 99);
795        // Original unchanged
796        assert_eq!(v.get(1), Some(&2));
797        // New version updated
798        assert_eq!(v2.get(1), Some(&99));
799        assert_eq!(v2.get(0), Some(&1));
800        assert_eq!(v2.get(2), Some(&3));
801    }
802
803    #[test]
804    fn vec_set_out_of_bounds() {
805        let v = PersistentVec::new().push(1);
806        let v2 = v.set(100, 42);
807        assert_eq!(v2.len(), 1); // unchanged
808    }
809
810    #[test]
811    fn vec_iter_order() {
812        let v = (0..10i32).fold(PersistentVec::new(), |acc, x| acc.push(x));
813        let collected: Vec<i32> = v.iter().copied().collect();
814        assert_eq!(collected, (0..10).collect::<Vec<i32>>());
815    }
816
817    #[test]
818    fn vec_large_push() {
819        let count = 100usize;
820        let v = (0..count).fold(PersistentVec::new(), |acc, x| acc.push(x));
821        assert_eq!(v.len(), count);
822        for i in 0..count {
823            assert_eq!(v.get(i), Some(&i));
824        }
825    }
826
827    #[test]
828    fn vec_multiple_versions_coexist() {
829        let v0: PersistentVec<u32> = PersistentVec::new();
830        let v1 = v0.push(1);
831        let v2 = v1.push(2);
832        let v3 = v2.push(3);
833        // All versions independent
834        assert_eq!(v0.len(), 0);
835        assert_eq!(v1.len(), 1);
836        assert_eq!(v2.len(), 2);
837        assert_eq!(v3.len(), 3);
838    }
839
840    // ── PersistentMap tests ───────────────────────────────────────────────────
841
842    #[test]
843    fn map_new_is_empty() {
844        let m: PersistentMap<String, i32> = PersistentMap::new();
845        assert_eq!(m.len(), 0);
846        assert!(m.is_empty());
847    }
848
849    #[test]
850    fn map_insert_and_get() {
851        let m = PersistentMap::new()
852            .insert("a".to_string(), 1)
853            .insert("b".to_string(), 2)
854            .insert("c".to_string(), 3);
855        assert_eq!(m.get(&"a".to_string()), Some(&1));
856        assert_eq!(m.get(&"b".to_string()), Some(&2));
857        assert_eq!(m.get(&"c".to_string()), Some(&3));
858        assert_eq!(m.get(&"d".to_string()), None);
859    }
860
861    #[test]
862    fn map_persistence_after_insert() {
863        let m0 = PersistentMap::new().insert(1u32, "one".to_string());
864        let m1 = m0.insert(2u32, "two".to_string());
865        // m0 unchanged
866        assert_eq!(m0.len(), 1);
867        assert_eq!(m0.get(&2), None);
868        // m1 has both
869        assert_eq!(m1.len(), 2);
870        assert_eq!(m1.get(&1), Some(&"one".to_string()));
871    }
872
873    #[test]
874    fn map_update_existing_key() {
875        let m0 = PersistentMap::new().insert("x".to_string(), 10i32);
876        let m1 = m0.insert("x".to_string(), 20);
877        assert_eq!(m1.len(), 1);
878        assert_eq!(m1.get(&"x".to_string()), Some(&20));
879        // m0 still has original value
880        assert_eq!(m0.get(&"x".to_string()), Some(&10));
881    }
882
883    #[test]
884    fn map_remove() {
885        let m = PersistentMap::new()
886            .insert(1u32, "a".to_string())
887            .insert(2u32, "b".to_string());
888        let m2 = m.remove(&1);
889        assert_eq!(m2.len(), 1);
890        assert_eq!(m2.get(&1), None);
891        assert_eq!(m2.get(&2), Some(&"b".to_string()));
892        // Original unchanged
893        assert_eq!(m.get(&1), Some(&"a".to_string()));
894    }
895
896    #[test]
897    fn map_contains_key() {
898        let m = PersistentMap::new().insert(42u32, true);
899        assert!(m.contains_key(&42));
900        assert!(!m.contains_key(&0));
901    }
902
903    #[test]
904    fn map_large_insert() {
905        let m = (0u32..50).fold(PersistentMap::new(), |acc, i| acc.insert(i, i * i));
906        assert_eq!(m.len(), 50);
907        for i in 0u32..50 {
908            assert_eq!(m.get(&i), Some(&(i * i)));
909        }
910    }
911
912    // ── PersistentSet tests ───────────────────────────────────────────────────
913
914    #[test]
915    fn set_new_is_empty() {
916        let s: PersistentSet<i32> = PersistentSet::new();
917        assert!(s.is_empty());
918    }
919
920    #[test]
921    fn set_insert_and_contains() {
922        let s = PersistentSet::new().insert(1i32).insert(2).insert(3);
923        assert!(s.contains(&1));
924        assert!(s.contains(&2));
925        assert!(!s.contains(&4));
926    }
927
928    #[test]
929    fn set_persistence_after_insert() {
930        let s0 = PersistentSet::new().insert(10i32);
931        let s1 = s0.insert(20);
932        assert!(!s0.contains(&20));
933        assert!(s1.contains(&10));
934        assert!(s1.contains(&20));
935    }
936
937    #[test]
938    fn set_remove() {
939        let s = PersistentSet::new().insert(1i32).insert(2).insert(3);
940        let s2 = s.remove(&2);
941        assert!(!s2.contains(&2));
942        assert!(s2.contains(&1));
943        assert!(s2.contains(&3));
944        // Original unchanged
945        assert!(s.contains(&2));
946    }
947
948    #[test]
949    fn set_union() {
950        let s1 = PersistentSet::new().insert(1i32).insert(2);
951        let s2 = PersistentSet::new().insert(2i32).insert(3);
952        let u = s1.union(&s2);
953        assert!(u.contains(&1));
954        assert!(u.contains(&2));
955        assert!(u.contains(&3));
956        assert_eq!(u.len(), 3);
957    }
958
959    #[test]
960    fn set_intersection() {
961        let s1 = PersistentSet::new().insert(1i32).insert(2).insert(3);
962        let s2 = PersistentSet::new().insert(2i32).insert(3).insert(4);
963        let inter = s1.intersection(&s2);
964        assert!(!inter.contains(&1));
965        assert!(inter.contains(&2));
966        assert!(inter.contains(&3));
967        assert!(!inter.contains(&4));
968        assert_eq!(inter.len(), 2);
969    }
970
971    // ── PersistentQueue tests ─────────────────────────────────────────────────
972
973    #[test]
974    fn queue_new_is_empty() {
975        let q: PersistentQueue<i32> = PersistentQueue::new();
976        assert!(q.is_empty());
977        assert_eq!(q.peek(), None);
978    }
979
980    #[test]
981    fn queue_push_and_pop() {
982        let q = PersistentQueue::new()
983            .push_back(1i32)
984            .push_back(2)
985            .push_back(3);
986        let (v, q2) = q.pop_front().expect("non-empty");
987        assert_eq!(v, 1);
988        let (v2, q3) = q2.pop_front().expect("non-empty");
989        assert_eq!(v2, 2);
990        let (v3, q4) = q3.pop_front().expect("non-empty");
991        assert_eq!(v3, 3);
992        assert!(q4.is_empty());
993    }
994
995    #[test]
996    fn queue_persistence() {
997        let q0 = PersistentQueue::new().push_back(10i32).push_back(20);
998        let (_, q1) = q0.pop_front().expect("non-empty");
999        // q0 still has 2 elements
1000        assert_eq!(q0.len(), 2);
1001        assert_eq!(q0.peek(), Some(&10));
1002        // q1 has 1 element
1003        assert_eq!(q1.len(), 1);
1004        assert_eq!(q1.peek(), Some(&20));
1005    }
1006
1007    #[test]
1008    fn queue_pop_empty() {
1009        let q: PersistentQueue<i32> = PersistentQueue::new();
1010        assert!(q.pop_front().is_none());
1011    }
1012
1013    #[test]
1014    fn queue_fifo_order() {
1015        let q = (0..5i32).fold(PersistentQueue::new(), |acc, x| acc.push_back(x));
1016        let mut current = q;
1017        for expected in 0..5i32 {
1018            let (val, next) = current.pop_front().expect("non-empty");
1019            assert_eq!(val, expected);
1020            current = next;
1021        }
1022        assert!(current.is_empty());
1023    }
1024
1025    // ── PersistentStack tests ─────────────────────────────────────────────────
1026
1027    #[test]
1028    fn stack_new_is_empty() {
1029        let s: PersistentStack<i32> = PersistentStack::new();
1030        assert!(s.is_empty());
1031        assert_eq!(s.peek(), None);
1032    }
1033
1034    #[test]
1035    fn stack_push_and_pop() {
1036        let s = PersistentStack::new().push(1i32).push(2).push(3);
1037        assert_eq!(s.peek(), Some(&3));
1038        let (v, s2) = s.pop().expect("non-empty");
1039        assert_eq!(v, 3);
1040        let (v2, s3) = s2.pop().expect("non-empty");
1041        assert_eq!(v2, 2);
1042        let (v3, s4) = s3.pop().expect("non-empty");
1043        assert_eq!(v3, 1);
1044        assert!(s4.is_empty());
1045    }
1046
1047    #[test]
1048    fn stack_persistence() {
1049        let s0 = PersistentStack::new().push(10i32).push(20);
1050        let (_, s1) = s0.pop().expect("non-empty");
1051        // s0 still intact
1052        assert_eq!(s0.len(), 2);
1053        assert_eq!(s0.peek(), Some(&20));
1054        // s1 has one element
1055        assert_eq!(s1.len(), 1);
1056        assert_eq!(s1.peek(), Some(&10));
1057    }
1058
1059    #[test]
1060    fn stack_pop_empty() {
1061        let s: PersistentStack<i32> = PersistentStack::new();
1062        assert!(s.pop().is_none());
1063    }
1064
1065    #[test]
1066    fn stack_lifo_order() {
1067        let s = (0..5i32).fold(PersistentStack::new(), |acc, x| acc.push(x));
1068        let mut current = s;
1069        for expected in (0..5i32).rev() {
1070            let (val, next) = current.pop().expect("non-empty");
1071            assert_eq!(val, expected);
1072            current = next;
1073        }
1074        assert!(current.is_empty());
1075    }
1076
1077    #[test]
1078    fn stack_multiple_branches_from_same_base() {
1079        let base = PersistentStack::new().push(1i32).push(2);
1080        let branch_a = base.push(10);
1081        let branch_b = base.push(20);
1082        assert_eq!(branch_a.peek(), Some(&10));
1083        assert_eq!(branch_b.peek(), Some(&20));
1084        // base unchanged
1085        assert_eq!(base.peek(), Some(&2));
1086    }
1087}