Skip to main content

hara_native/lang/data/
vector.rs

1use std::cell::Cell;
2use std::rc::Rc;
3
4use crate::lang::hash::JavaHash;
5use crate::lang::protocol::ihash::HashType;
6use crate::lang::protocol::{
7    IAssoc, IColl, IConj, ICount, IDisplay, IEmpty, IEquality, IHash, IMetadata, IMutable, INth,
8    IObjType, IPeekFirst, IPeekLast, IPersistent, IPopLast, IPushLast, IToMutable, IToPersistent,
9    ObjType,
10};
11
12const NODE_SHIFT: usize = 5;
13const NODE_WIDTH: usize = 1 << NODE_SHIFT;
14const NODE_MASK: usize = NODE_WIDTH - 1;
15
16/// Token stamped on persistent (non-editable) nodes, the counterpart of
17/// Java's `Node.NOEDIT`. Transient nodes carry the owning `Mutable`'s token
18/// instead; see `next_token`.
19const NOEDIT: u64 = 0;
20
21thread_local! {
22    static NEXT_TOKEN: Cell<u64> = Cell::new(1);
23}
24
25/// Java uses an `AtomicReference<Thread>` as the edit token; the Rust runtime
26/// is single-threaded per vector (Rc-based), so a thread-local monotonic u64
27/// plays the same role. Each `Mutable` session gets a fresh token.
28fn next_token() -> u64 {
29    NEXT_TOKEN.with(|next| {
30        let token = next.get();
31        next.set(token + 1);
32        token
33    })
34}
35
36fn tail_offset(size: usize) -> usize {
37    if size < NODE_WIDTH {
38        0
39    } else {
40        ((size - 1) >> NODE_SHIFT) << NODE_SHIFT
41    }
42}
43
44#[derive(Debug, Clone)]
45enum Node<E> {
46    Branch(Branch<E>),
47    Leaf(Leaf<E>),
48}
49
50#[derive(Debug, Clone)]
51struct Branch<E> {
52    token: u64,
53    children: Vec<Option<Rc<Node<E>>>>,
54}
55
56#[derive(Debug, Clone)]
57struct Leaf<E> {
58    token: u64,
59    values: Vec<E>,
60}
61
62impl<E: Clone> Node<E> {
63    fn empty_branch() -> Rc<Self> {
64        Rc::new(Self::Branch(Branch {
65            token: NOEDIT,
66            children: vec![None; NODE_WIDTH],
67        }))
68    }
69
70    fn editable_empty_branch(token: u64) -> Rc<Self> {
71        Rc::new(Self::Branch(Branch {
72            token,
73            children: vec![None; NODE_WIDTH],
74        }))
75    }
76
77    fn token(&self) -> u64 {
78        match self {
79            Node::Branch(branch) => branch.token,
80            Node::Leaf(leaf) => leaf.token,
81        }
82    }
83
84    fn with_token(&self, token: u64) -> Self {
85        let mut node = self.clone();
86        match &mut node {
87            Node::Branch(branch) => branch.token = token,
88            Node::Leaf(leaf) => leaf.token = token,
89        }
90        node
91    }
92}
93
94fn children_mut<'a, E>(node: &'a mut Node<E>) -> &'a mut Vec<Option<Rc<Node<E>>>> {
95    let Node::Branch(branch) = node else {
96        unreachable!("editable vector path must be a branch")
97    };
98    &mut branch.children
99}
100
101/// Java `S.editableNode`: hand back the same node when it already belongs to
102/// this transient (token match) and is uniquely owned, otherwise path-copy it
103/// and stamp the copy with the transient's token.
104fn ensure_editable<E: Clone>(node: Rc<Node<E>>, token: u64) -> Rc<Node<E>> {
105    if node.token() == token && Rc::strong_count(&node) == 1 {
106        node
107    } else {
108        Rc::new(node.with_token(token))
109    }
110}
111
112fn new_path<E: Clone>(token: u64, level: usize, node: Rc<Node<E>>) -> Rc<Node<E>> {
113    if level == 0 {
114        return node;
115    }
116    let mut children = vec![None; NODE_WIDTH];
117    children[0] = Some(new_path(token, level - NODE_SHIFT, node));
118    Rc::new(Node::Branch(Branch { token, children }))
119}
120
121/// Persistent `S.pushTail` (editable=false): unconditional path-copy, new
122/// nodes carry NOEDIT like Java's persistent nodes.
123fn push_tail<E: Clone>(
124    parent: &Rc<Node<E>>,
125    level: usize,
126    size: usize,
127    tail: Rc<Node<E>>,
128) -> Rc<Node<E>> {
129    let Node::Branch(branch) = parent.as_ref() else {
130        unreachable!("vector tree parent must be a branch")
131    };
132    let mut children = branch.children.clone();
133    let index = ((size - 1) >> level) & NODE_MASK;
134    children[index] = Some(if level == NODE_SHIFT {
135        tail
136    } else if let Some(child) = &children[index] {
137        push_tail(child, level - NODE_SHIFT, size, tail)
138    } else {
139        new_path(NOEDIT, level - NODE_SHIFT, tail)
140    });
141    Rc::new(Node::Branch(Branch {
142        token: NOEDIT,
143        children,
144    }))
145}
146
147/// Transient `S.pushTail` (editable=true): mutate in place when the parent is
148/// uniquely owned by this transient, else path-copy with the transient token.
149fn push_tail_editable<E: Clone>(
150    token: u64,
151    parent: Rc<Node<E>>,
152    level: usize,
153    size: usize,
154    tail: Rc<Node<E>>,
155) -> Rc<Node<E>> {
156    let mut parent = ensure_editable(parent, token);
157    let index = ((size - 1) >> level) & NODE_MASK;
158    let slot = &mut children_mut(Rc::get_mut(&mut parent).expect("editable vector node"))[index];
159    let child = if level == NODE_SHIFT {
160        tail
161    } else {
162        match slot.take() {
163            Some(existing) => push_tail_editable(token, existing, level - NODE_SHIFT, size, tail),
164            None => new_path(token, level - NODE_SHIFT, tail),
165        }
166    };
167    *slot = Some(child);
168    parent
169}
170
171/// Persistent `S.assoc`: copy-on-write down the path.
172fn assoc_node<E: Clone>(node: &Rc<Node<E>>, level: usize, index: usize, value: E) -> Rc<Node<E>> {
173    if level == 0 {
174        let Node::Leaf(leaf) = node.as_ref() else {
175            unreachable!("vector terminal node must be a leaf")
176        };
177        let mut values = leaf.values.clone();
178        values[index & NODE_MASK] = value;
179        return Rc::new(Node::Leaf(Leaf {
180            token: NOEDIT,
181            values,
182        }));
183    }
184    let Node::Branch(branch) = node.as_ref() else {
185        unreachable!("vector path must contain branches")
186    };
187    let mut children = branch.children.clone();
188    let child_index = (index >> level) & NODE_MASK;
189    children[child_index] = Some(assoc_node(
190        children[child_index]
191            .as_ref()
192            .expect("existing vector path"),
193        level - NODE_SHIFT,
194        index,
195        value,
196    ));
197    Rc::new(Node::Branch(Branch {
198        token: NOEDIT,
199        children,
200    }))
201}
202
203/// Transient assoc: descend with write-back, mutating nodes that belong to
204/// this transient in place and path-copying shared/persistent ones.
205///
206/// DEVIATION from Java: `S.getNodeArrayFor(editable=true)` (Vector.java:34-50)
207/// wraps non-matching children with `editableNode` but never writes the copy
208/// back into the parent, so a transient assoc through a not-yet-editable path
209/// would silently lose the write. The port links copies back like Clojure's
210/// `editableNodeFor`.
211fn assoc_editable<E: Clone>(
212    token: u64,
213    node: Rc<Node<E>>,
214    level: usize,
215    index: usize,
216    value: E,
217) -> Rc<Node<E>> {
218    let mut node = ensure_editable(node, token);
219    let inner = Rc::get_mut(&mut node).expect("editable vector node");
220    if level == 0 {
221        let Node::Leaf(leaf) = inner else {
222            unreachable!("vector terminal node must be a leaf")
223        };
224        leaf.values[index & NODE_MASK] = value;
225        return node;
226    }
227    let slot = &mut children_mut(inner)[(index >> level) & NODE_MASK];
228    let child = slot.take().expect("existing vector path");
229    *slot = Some(assoc_editable(
230        token,
231        child,
232        level - NODE_SHIFT,
233        index,
234        value,
235    ));
236    node
237}
238
239/// Persistent `S.popTail`.
240///
241/// DEVIATION from Java (known bug, deliberately not replicated): Java's
242/// `S.popTail` (Vector.java:104-120) mutates `node.array[subidx]` in place
243/// even when `editable == false`, corrupting every persistent vector that
244/// shares those nodes. The port is unconditional copy-on-write.
245fn pop_tail<E: Clone>(node: &Rc<Node<E>>, level: usize, size: usize) -> Option<Rc<Node<E>>> {
246    let Node::Branch(branch) = node.as_ref() else {
247        unreachable!("vector path must contain branches")
248    };
249    let index = ((size - 2) >> level) & NODE_MASK;
250    if level > NODE_SHIFT {
251        let child = pop_tail(
252            branch.children[index]
253                .as_ref()
254                .expect("existing vector path"),
255            level - NODE_SHIFT,
256            size,
257        );
258        if child.is_none() && index == 0 {
259            return None;
260        }
261        let mut children = branch.children.clone();
262        children[index] = child;
263        Some(Rc::new(Node::Branch(Branch {
264            token: NOEDIT,
265            children,
266        })))
267    } else if index == 0 {
268        None
269    } else {
270        let mut children = branch.children.clone();
271        children[index] = None;
272        Some(Rc::new(Node::Branch(Branch {
273            token: NOEDIT,
274            children,
275        })))
276    }
277}
278
279/// Transient `S.popTail` (editable=true): mutate in place when the node
280/// belongs to this transient, else copy with the transient token.
281fn pop_tail_editable<E: Clone>(
282    token: u64,
283    node: Rc<Node<E>>,
284    level: usize,
285    size: usize,
286) -> Option<Rc<Node<E>>> {
287    let index = ((size - 2) >> level) & NODE_MASK;
288    if level == NODE_SHIFT && index == 0 {
289        return None;
290    }
291    let mut node = ensure_editable(node, token);
292    let slot = &mut children_mut(Rc::get_mut(&mut node).expect("editable vector node"))[index];
293    if level > NODE_SHIFT {
294        let child = pop_tail_editable(
295            token,
296            slot.take().expect("existing vector path"),
297            level - NODE_SHIFT,
298            size,
299        );
300        if child.is_none() && index == 0 {
301            return None;
302        }
303        *slot = child;
304    } else {
305        *slot = None;
306    }
307    Some(node)
308}
309
310#[derive(Debug, Clone)]
311pub struct Standard<E> {
312    metadata: Option<Rc<crate::lang::data::Metadata>>,
313    size: usize,
314    shift: usize,
315    root: Rc<Node<E>>,
316    tail: Rc<Vec<E>>,
317}
318
319impl<E: Clone> Default for Standard<E> {
320    fn default() -> Self {
321        Self {
322            metadata: None,
323            size: 0,
324            shift: NODE_SHIFT,
325            root: Node::empty_branch(),
326            tail: Rc::new(Vec::new()),
327        }
328    }
329}
330
331impl<E: Clone> Standard<E> {
332    pub fn new() -> Self {
333        Self::default()
334    }
335
336    /// Java `Standard.into`: bulk-build through the transient and freeze.
337    pub fn from_iter(values: impl IntoIterator<Item = E>) -> Self {
338        let mut mutable = Mutable::from_iter(values);
339        mutable.to_persistent()
340    }
341
342    pub fn len(&self) -> usize {
343        self.size
344    }
345
346    pub fn is_empty(&self) -> bool {
347        self.size == 0
348    }
349
350    fn tail_offset(&self) -> usize {
351        tail_offset(self.size)
352    }
353
354    pub fn get(&self, index: usize) -> Option<&E> {
355        self.array_for(index)?.get(index & NODE_MASK)
356    }
357
358    pub fn assoc_value(&self, index: usize, value: E) -> Option<Self> {
359        if index == self.size {
360            return Some(self.push_last(value));
361        }
362        if index >= self.size {
363            return None;
364        }
365        if index >= self.tail_offset() {
366            let mut tail = (*self.tail).clone();
367            tail[index & NODE_MASK] = value;
368            return Some(Self {
369                tail: Rc::new(tail),
370                ..self.clone()
371            });
372        }
373        Some(Self {
374            root: assoc_node(&self.root, self.shift, index, value),
375            ..self.clone()
376        })
377    }
378
379    pub fn assoc_value_owned(mut self, index: usize, value: E) -> Option<Self> {
380        if index == self.size {
381            return Some(self.push_last_owned(value));
382        }
383        if index >= self.size {
384            return None;
385        }
386        if index >= self.tail_offset() {
387            Rc::make_mut(&mut self.tail)[index & NODE_MASK] = value;
388        } else {
389            self.root = assoc_editable(NOEDIT, self.root, self.shift, index, value);
390        }
391        Some(self)
392    }
393
394    pub fn push_last(&self, value: E) -> Self {
395        if self.size - self.tail_offset() < NODE_WIDTH {
396            let mut tail = (*self.tail).clone();
397            tail.push(value);
398            return Self {
399                size: self.size + 1,
400                tail: Rc::new(tail),
401                ..self.clone()
402            };
403        }
404
405        let tail_node = Rc::new(Node::Leaf(Leaf {
406            token: NOEDIT,
407            values: (*self.tail).clone(),
408        }));
409        let overflow = (self.size >> NODE_SHIFT) > (1usize << self.shift);
410        let (root, shift) = if overflow {
411            let mut children = vec![None; NODE_WIDTH];
412            children[0] = Some(self.root.clone());
413            children[1] = Some(new_path(NOEDIT, self.shift, tail_node));
414            (
415                Rc::new(Node::Branch(Branch {
416                    token: NOEDIT,
417                    children,
418                })),
419                self.shift + NODE_SHIFT,
420            )
421        } else {
422            (
423                push_tail(&self.root, self.shift, self.size, tail_node),
424                self.shift,
425            )
426        };
427
428        Self {
429            metadata: self.metadata.clone(),
430            size: self.size + 1,
431            shift,
432            root,
433            tail: Rc::new(vec![value]),
434        }
435    }
436
437    pub fn push_last_owned(mut self, value: E) -> Self {
438        if self.size - self.tail_offset() < NODE_WIDTH {
439            Rc::make_mut(&mut self.tail).push(value);
440            self.size += 1;
441            return self;
442        }
443
444        let tail_node = Rc::new(Node::Leaf(Leaf {
445            token: NOEDIT,
446            values: std::mem::take(Rc::make_mut(&mut self.tail)),
447        }));
448        self.tail = Rc::new(vec![value]);
449        if (self.size >> NODE_SHIFT) > (1usize << self.shift) {
450            let mut children = vec![None; NODE_WIDTH];
451            children[0] = Some(self.root);
452            children[1] = Some(new_path(NOEDIT, self.shift, tail_node));
453            self.root = Rc::new(Node::Branch(Branch {
454                token: NOEDIT,
455                children,
456            }));
457            self.shift += NODE_SHIFT;
458        } else {
459            self.root = push_tail_editable(NOEDIT, self.root, self.shift, self.size, tail_node);
460        }
461        self.size += 1;
462        self
463    }
464
465    pub fn pop_last_value(&self) -> Option<Self> {
466        if self.size == 0 {
467            return None;
468        }
469        if self.size == 1 {
470            return Some(Self {
471                metadata: self.metadata.clone(),
472                ..Self::new()
473            });
474        }
475        if self.size - self.tail_offset() > 1 {
476            let mut tail = (*self.tail).clone();
477            tail.pop();
478            return Some(Self {
479                size: self.size - 1,
480                tail: Rc::new(tail),
481                ..self.clone()
482            });
483        }
484
485        let new_tail = self
486            .array_for(self.size - 2)
487            .expect("previous vector leaf")
488            .clone();
489        let mut root =
490            pop_tail(&self.root, self.shift, self.size).unwrap_or_else(Node::empty_branch);
491        let mut shift = self.shift;
492        if shift > NODE_SHIFT {
493            let collapse =
494                matches!(root.as_ref(), Node::Branch(branch) if branch.children[1].is_none());
495            if collapse {
496                let Node::Branch(branch) = root.as_ref() else {
497                    unreachable!("collapsed vector root must be a branch")
498                };
499                root = branch.children[0].clone().expect("collapsed vector root");
500                shift -= NODE_SHIFT;
501            }
502        }
503        Some(Self {
504            metadata: self.metadata.clone(),
505            size: self.size - 1,
506            shift,
507            root,
508            tail: Rc::new(new_tail),
509        })
510    }
511
512    fn array_for(&self, index: usize) -> Option<&Vec<E>> {
513        if index >= self.size {
514            return None;
515        }
516        if index >= self.tail_offset() {
517            return Some(&self.tail);
518        }
519        let mut node = self.root.as_ref();
520        let mut level = self.shift;
521        while level > 0 {
522            let Node::Branch(branch) = node else {
523                return None;
524            };
525            node = branch.children[(index >> level) & NODE_MASK].as_deref()?;
526            level -= NODE_SHIFT;
527        }
528        match node {
529            Node::Leaf(leaf) => Some(&leaf.values),
530            Node::Branch(_) => None,
531        }
532    }
533
534    pub fn iter(&self) -> Iter<'_, E> {
535        Iter::new(self, 0, self.size)
536    }
537
538    /// Java `Base.rangedIterator`, exposed for `SubView`.
539    fn ranged_iter(&self, start: usize, end: usize) -> Iter<'_, E> {
540        Iter::new(self, start, end)
541    }
542
543    /// DEVIATION from Java bounds: Java rejects `end > size - 1`, which makes
544    /// it impossible to view the last element (`subview(0, size)` throws).
545    /// The port accepts the Rust-idiomatic `start <= end <= size`.
546    pub fn subview(&self, start: usize, end: usize) -> Option<SubView<E>> {
547        if start > end || end > self.size {
548            return None;
549        }
550        Some(SubView {
551            vector: self.clone(),
552            start,
553            end,
554        })
555    }
556
557    #[cfg(test)]
558    fn shares_root_with(&self, other: &Self) -> bool {
559        Rc::ptr_eq(&self.root, &other.root)
560    }
561}
562
563/// Java `Base.rangedIterator`: walks the tree one 32-element chunk at a time
564/// instead of re-descending per element.
565pub struct Iter<'a, E> {
566    vector: &'a Standard<E>,
567    index: usize,
568    end: usize,
569    base: usize,
570    chunk: Option<&'a [E]>,
571}
572
573impl<'a, E: Clone> Iter<'a, E> {
574    fn new(vector: &'a Standard<E>, start: usize, end: usize) -> Self {
575        let chunk = if start < vector.size {
576            vector.array_for(start).map(|values| values.as_slice())
577        } else {
578            None
579        };
580        Self {
581            vector,
582            index: start,
583            end,
584            base: start - (start % NODE_WIDTH),
585            chunk,
586        }
587    }
588}
589
590impl<'a, E: Clone> Iterator for Iter<'a, E> {
591    type Item = &'a E;
592
593    fn next(&mut self) -> Option<Self::Item> {
594        if self.index >= self.end {
595            return None;
596        }
597        if self.index - self.base == NODE_WIDTH {
598            self.chunk = self
599                .vector
600                .array_for(self.index)
601                .map(|values| values.as_slice());
602            self.base += NODE_WIDTH;
603        }
604        let value = &self.chunk?[self.index & NODE_MASK];
605        self.index += 1;
606        Some(value)
607    }
608}
609
610impl<E: Clone> FromIterator<E> for Standard<E> {
611    fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self {
612        Self::from_iter(iter)
613    }
614}
615
616impl<E: Clone> From<Vec<E>> for Standard<E> {
617    fn from(values: Vec<E>) -> Self {
618        Self::from_iter(values)
619    }
620}
621
622impl<E: Clone> IntoIterator for Standard<E> {
623    type Item = E;
624    type IntoIter = std::vec::IntoIter<E>;
625    fn into_iter(self) -> Self::IntoIter {
626        self.iter().cloned().collect::<Vec<_>>().into_iter()
627    }
628}
629
630impl<E: Clone> std::ops::Index<usize> for Standard<E> {
631    type Output = E;
632
633    fn index(&self, index: usize) -> &Self::Output {
634        self.get(index).expect("vector index out of bounds")
635    }
636}
637
638impl<E: Clone + PartialEq> PartialEq for Standard<E> {
639    fn eq(&self, other: &Self) -> bool {
640        self.size == other.size && self.iter().eq(other.iter())
641    }
642}
643
644impl<E: Clone + PartialEq> IEquality for Standard<E> {
645    fn equality(&self, other: &Self) -> bool {
646        self == other
647    }
648}
649
650impl<E: Clone> ICount for Standard<E> {
651    fn count(&self) -> usize {
652        self.size
653    }
654}
655
656impl<E: Clone> INth<E> for Standard<E> {
657    fn nth(&self, index: usize) -> Option<&E> {
658        self.get(index)
659    }
660}
661
662impl<E: Clone> IAssoc<usize, E> for Standard<E> {
663    type Output = Self;
664    fn assoc(&self, index: usize, value: E) -> Self {
665        self.assoc_value(index, value)
666            .expect("vector index out of bounds")
667    }
668}
669
670impl<E: Clone> IPeekFirst<E> for Standard<E> {
671    fn peek_first(&self) -> Option<E> {
672        self.get(0).cloned()
673    }
674}
675impl<E: Clone> IPeekLast<E> for Standard<E> {
676    fn peek_last(&self) -> Option<E> {
677        self.size
678            .checked_sub(1)
679            .and_then(|index| self.get(index))
680            .cloned()
681    }
682}
683impl<E: Clone> IPushLast<E> for Standard<E> {
684    type Output = Self;
685    fn push_last(&self, value: E) -> Self {
686        Standard::push_last(self, value)
687    }
688}
689
690impl<E: Clone> IPopLast for Standard<E> {
691    type Output = Self;
692    fn pop_last(&self) -> Self {
693        self.pop_last_value().expect("cannot pop empty vector")
694    }
695}
696
697impl<E: Clone> IConj<E> for Standard<E> {
698    type Output = Self;
699    fn conj(&self, value: E) -> Self {
700        self.push_last(value)
701    }
702}
703
704impl<E: Clone> IEmpty for Standard<E> {
705    type Output = Self;
706    fn empty(&self) -> Self {
707        Self {
708            metadata: self.metadata.clone(),
709            ..Self::new()
710        }
711    }
712}
713
714impl<E: Clone> IMetadata for Standard<E> {
715    type Metadata = Rc<crate::lang::data::Metadata>;
716
717    fn meta(&self) -> Option<&Self::Metadata> {
718        self.metadata.as_ref()
719    }
720
721    fn with_meta(&self, metadata: Option<Self::Metadata>) -> Self {
722        Self {
723            metadata,
724            ..self.clone()
725        }
726    }
727}
728
729impl<E: Clone> IPersistent for Standard<E> {}
730
731impl<E: Clone> IToMutable for Standard<E> {
732    type Mutable = Mutable<E>;
733
734    fn to_mutable(&self) -> Self::Mutable {
735        Mutable::from_standard(self)
736    }
737}
738
739impl<E: Clone + std::fmt::Debug> IDisplay for Standard<E> {
740    fn display(&self) -> String {
741        format!(
742            "[{}]",
743            self.iter()
744                .map(|value| format!("{value:?}"))
745                .collect::<Vec<_>>()
746                .join(" ")
747        )
748    }
749}
750
751impl<E: Clone + std::hash::Hash + JavaHash> IHash for Standard<E> {
752    fn hash_calc(&self, hash_type: HashType) -> u64 {
753        // Java IVectorType extends ISequential: ordered composition,
754        // "::SEQUENTIAL" seed (see lang::hash).
755        crate::lang::hash::compose_ordered(
756            "SEQUENTIAL",
757            self.iter().map(|value| value.java_hash(hash_type)),
758        ) as u64
759    }
760}
761
762impl<E: Clone + std::fmt::Debug> IObjType for Standard<E> {
763    fn obj_type(&self) -> ObjType {
764        ObjType::Sequential
765    }
766}
767impl<E> IColl<E> for Standard<E>
768where
769    E: Clone + PartialEq + std::fmt::Debug + std::hash::Hash + JavaHash,
770{
771    fn start_string(&self) -> &'static str {
772        "["
773    }
774    fn end_string(&self) -> &'static str {
775        "]"
776    }
777}
778
779/// Transient vector. Unlike Java's 32-slot scratch tail with null padding,
780/// the Rust tail is a `Vec<E>` whose length is always exactly
781/// `size - tailoff(size)`; the "scratch" behaviour comes from in-place
782/// `push`/`pop` on that Vec. All tree nodes touched by the transient are
783/// stamped with its `token` and mutated in place only while uniquely owned
784/// (`Rc::strong_count == 1`), matching Java's edit-token discipline.
785#[derive(Debug, Clone)]
786pub struct Mutable<E> {
787    editable: Rc<Cell<bool>>,
788    token: u64,
789    size: usize,
790    shift: usize,
791    root: Rc<Node<E>>,
792    tail: Vec<E>,
793    metadata: Option<Rc<crate::lang::data::Metadata>>,
794}
795
796impl<E: Clone> Mutable<E> {
797    pub fn new() -> Self {
798        let token = next_token();
799        Self {
800            editable: Rc::new(Cell::new(true)),
801            token,
802            size: 0,
803            shift: NODE_SHIFT,
804            root: Node::editable_empty_branch(token),
805            tail: Vec::new(),
806            metadata: None,
807        }
808    }
809
810    pub fn from_iter(values: impl IntoIterator<Item = E>) -> Self {
811        let mut mutable = Self::new();
812        for value in values {
813            mutable.push_last(value);
814        }
815        mutable
816    }
817
818    /// Java `new Mutable(Base)`: editable copy of the root, copy of the tail.
819    fn from_standard(vector: &Standard<E>) -> Self {
820        let token = next_token();
821        Self {
822            editable: Rc::new(Cell::new(true)),
823            token,
824            size: vector.size,
825            shift: vector.shift,
826            root: Rc::new(vector.root.with_token(token)),
827            tail: (*vector.tail).clone(),
828            metadata: vector.metadata.clone(),
829        }
830    }
831
832    fn check_editable(&self) {
833        assert!(
834            self.editable.get(),
835            "mutable vector used after to_persistent"
836        );
837    }
838
839    pub fn len(&self) -> usize {
840        self.check_editable();
841        self.size
842    }
843
844    pub fn is_empty(&self) -> bool {
845        self.len() == 0
846    }
847
848    pub fn get(&self, index: usize) -> Option<&E> {
849        self.check_editable();
850        self.nth_ref(index)
851    }
852
853    fn nth_ref(&self, index: usize) -> Option<&E> {
854        if index >= self.size {
855            return None;
856        }
857        if index >= tail_offset(self.size) {
858            return self.tail.get(index & NODE_MASK);
859        }
860        self.leaf_values(index)?.get(index & NODE_MASK)
861    }
862
863    /// Read the tree leaf holding `index` (index must be below the tail).
864    fn leaf_values(&self, index: usize) -> Option<&Vec<E>> {
865        let mut node = self.root.as_ref();
866        let mut level = self.shift;
867        while level > 0 {
868            let Node::Branch(branch) = node else {
869                return None;
870            };
871            node = branch.children[(index >> level) & NODE_MASK].as_deref()?;
872            level -= NODE_SHIFT;
873        }
874        match node {
875            Node::Leaf(leaf) => Some(&leaf.values),
876            Node::Branch(_) => None,
877        }
878    }
879
880    pub fn iter(&self) -> impl Iterator<Item = &E> {
881        self.check_editable();
882        (0..self.size).map(move |index| self.nth_ref(index).expect("vector index in range"))
883    }
884
885    pub fn push_last(&mut self, value: E) -> &mut Self {
886        self.check_editable();
887        // room in the tail?
888        if self.size - tail_offset(self.size) < NODE_WIDTH {
889            self.tail.push(value);
890            self.size += 1;
891            return self;
892        }
893        // full tail, wrap it as a tree node
894        let tail_node = Rc::new(Node::Leaf(Leaf {
895            token: self.token,
896            values: std::mem::take(&mut self.tail),
897        }));
898        self.tail = vec![value];
899        let mut new_shift = self.shift;
900        // overflow root?
901        let new_root = if (self.size >> NODE_SHIFT) > (1usize << self.shift) {
902            let mut children = vec![None; NODE_WIDTH];
903            children[0] = Some(std::mem::replace(&mut self.root, Node::empty_branch()));
904            children[1] = Some(new_path(self.token, self.shift, tail_node));
905            new_shift += NODE_SHIFT;
906            Rc::new(Node::Branch(Branch {
907                token: self.token,
908                children,
909            }))
910        } else {
911            let old_root = std::mem::replace(&mut self.root, Node::empty_branch());
912            push_tail_editable(self.token, old_root, self.shift, self.size, tail_node)
913        };
914        self.root = new_root;
915        self.shift = new_shift;
916        self.size += 1;
917        self
918    }
919
920    pub fn assoc(&mut self, index: usize, value: E) -> &mut Self {
921        self.check_editable();
922        if index == self.size {
923            return self.push_last(value);
924        }
925        assert!(index < self.size, "vector index out of bounds");
926        if index >= tail_offset(self.size) {
927            self.tail[index & NODE_MASK] = value;
928            return self;
929        }
930        let old_root = std::mem::replace(&mut self.root, Node::empty_branch());
931        self.root = assoc_editable(self.token, old_root, self.shift, index, value);
932        self
933    }
934
935    pub fn pop_last(&mut self) -> Option<E> {
936        self.check_editable();
937        if self.size == 0 {
938            return None;
939        }
940        // The last element always lives in the tail.
941        let popped = self.tail.pop().expect("non-empty vector has a tail");
942        if self.size == 1 {
943            self.size = 0;
944            return Some(popped);
945        }
946        if ((self.size - 1) & NODE_MASK) > 0 {
947            self.size -= 1;
948            return Some(popped);
949        }
950        // tail boundary: pull the last tree leaf down as the new tail
951        let new_tail = self
952            .leaf_values(self.size - 2)
953            .expect("previous vector leaf")
954            .clone();
955        let old_root = std::mem::replace(&mut self.root, Node::empty_branch());
956        let mut new_root = pop_tail_editable(self.token, old_root, self.shift, self.size)
957            .unwrap_or_else(|| Node::editable_empty_branch(self.token));
958        let mut new_shift = self.shift;
959        if new_shift > NODE_SHIFT {
960            let collapse =
961                matches!(new_root.as_ref(), Node::Branch(branch) if branch.children[1].is_none());
962            if collapse {
963                let child = children_mut(Rc::get_mut(&mut new_root).expect("editable vector root"))
964                    [0]
965                .take()
966                .expect("collapsed vector root");
967                new_root = ensure_editable(child, self.token);
968                new_shift -= NODE_SHIFT;
969            }
970        }
971        self.root = new_root;
972        self.shift = new_shift;
973        self.size -= 1;
974        self.tail = new_tail;
975        Some(popped)
976    }
977
978    pub fn empty(&mut self) -> &mut Self {
979        self.check_editable();
980        self.size = 0;
981        self.shift = NODE_SHIFT;
982        self.root = Node::editable_empty_branch(self.token);
983        self.tail = Vec::new();
984        self
985    }
986}
987
988impl<E: Clone> Default for Mutable<E> {
989    fn default() -> Self {
990        Self::new()
991    }
992}
993
994impl<E: Clone> FromIterator<E> for Mutable<E> {
995    fn from_iter<T: IntoIterator<Item = E>>(iter: T) -> Self {
996        Self::from_iter(iter)
997    }
998}
999
1000impl<E: Clone> IMutable for Mutable<E> {}
1001
1002impl<E: Clone> IToPersistent for Mutable<E> {
1003    type Persistent = Standard<E>;
1004
1005    fn to_persistent(&mut self) -> Self::Persistent {
1006        self.check_editable();
1007        // Java `_root.edit.set(null)`: invalidate the transient session.
1008        self.editable.set(false);
1009        // Java `S.trimTail` trims the 32-slot scratch tail to
1010        // `size - tailoff(size)`. The Rust tail Vec is already exact-length,
1011        // so only spare capacity is released.
1012        self.tail.shrink_to_fit();
1013        Standard {
1014            metadata: self.metadata.clone(),
1015            size: self.size,
1016            shift: self.shift,
1017            root: self.root.clone(),
1018            tail: Rc::new(std::mem::take(&mut self.tail)),
1019        }
1020    }
1021}
1022
1023#[derive(Debug, Clone)]
1024pub struct SubView<E> {
1025    vector: Standard<E>,
1026    start: usize,
1027    end: usize,
1028}
1029
1030impl<E: Clone> SubView<E> {
1031    pub fn len(&self) -> usize {
1032        self.end - self.start
1033    }
1034
1035    pub fn is_empty(&self) -> bool {
1036        self.len() == 0
1037    }
1038
1039    pub fn get(&self, index: usize) -> Option<&E> {
1040        if index >= self.len() {
1041            None
1042        } else {
1043            self.vector.get(self.start + index)
1044        }
1045    }
1046
1047    /// Java `SubView.iterator`: ranged iterator over the backing vector.
1048    pub fn iter(&self) -> Iter<'_, E> {
1049        self.vector.ranged_iter(self.start, self.end)
1050    }
1051
1052    /// Java `SubView.pushLast`: assoc at `_end` on the backing vector
1053    /// (write-through when `_end < v.count`, append when equal) and extend.
1054    pub fn push_last(&self, value: E) -> Self {
1055        Self {
1056            vector: self
1057                .vector
1058                .assoc_value(self.end, value)
1059                .expect("subview push within bounds"),
1060            start: self.start,
1061            end: self.end + 1,
1062        }
1063    }
1064
1065    /// Java `SubView.popLast` returns the view unchanged when empty; the port
1066    /// surfaces that as `None`.
1067    pub fn pop_last_value(&self) -> Option<Self> {
1068        if self.end == self.start {
1069            return None;
1070        }
1071        Some(Self {
1072            vector: self.vector.clone(),
1073            start: self.start,
1074            end: self.end - 1,
1075        })
1076    }
1077
1078    /// Java `SubView.assoc`: write-through into the backing vector; assoc at
1079    /// `len()` extends the view like `push_last`.
1080    pub fn assoc_value(&self, index: usize, value: E) -> Option<Self> {
1081        if index > self.len() {
1082            return None;
1083        }
1084        if index == self.len() {
1085            return Some(self.push_last(value));
1086        }
1087        Some(Self {
1088            vector: self.vector.assoc_value(self.start + index, value)?,
1089            start: self.start,
1090            end: self.end,
1091        })
1092    }
1093
1094    /// DEVIATION from Java bounds: same off-by-one as `Standard::subview`;
1095    /// the port accepts `start <= end <= len()`.
1096    pub fn subview(&self, start: usize, end: usize) -> Option<Self> {
1097        if start > end || end > self.len() {
1098            return None;
1099        }
1100        Some(Self {
1101            vector: self.vector.clone(),
1102            start: self.start + start,
1103            end: self.start + end,
1104        })
1105    }
1106}
1107
1108#[cfg(test)]
1109mod tests {
1110    use super::{Mutable, Standard};
1111    use crate::lang::protocol::{IAssoc, IToMutable, IToPersistent};
1112
1113    fn contents(vector: &Standard<i64>) -> Vec<i64> {
1114        vector.iter().copied().collect()
1115    }
1116
1117    #[test]
1118    fn preserves_values_across_java_tree_boundaries() {
1119        let vector = (0..1057).collect::<Standard<_>>();
1120        let appended = vector.push_last(1057);
1121        let updated = appended.assoc(32, -1);
1122
1123        assert_eq!(vector.len(), 1057);
1124        assert_eq!(vector[32], 32);
1125        assert_eq!(appended[1057], 1057);
1126        assert_eq!(updated[32], -1);
1127        assert_eq!(updated[1057], 1057);
1128    }
1129
1130    #[test]
1131    fn tail_updates_share_the_tree() {
1132        let vector = (0..33).collect::<Standard<_>>();
1133        let appended = vector.push_last(33);
1134
1135        assert!(vector.shares_root_with(&appended));
1136    }
1137
1138    #[test]
1139    fn push_across_32_1024_32768_boundaries() {
1140        // Persistent pushes across the first root-growth boundaries.
1141        let mut vector = Standard::new();
1142        for value in 0..2100i64 {
1143            vector = vector.push_last(value);
1144            assert_eq!(vector.len() as i64, value + 1);
1145            assert_eq!(vector.get(value as usize), Some(&value));
1146        }
1147        for value in 0..2100i64 {
1148            assert_eq!(vector.get(value as usize), Some(&value));
1149        }
1150
1151        // Bulk build across the 32768 (second root-level) boundary.
1152        let big = Standard::from_iter(0..33000i64);
1153        assert_eq!(big.len(), 33000);
1154        for value in 0..33000i64 {
1155            assert_eq!(big.get(value as usize), Some(&value));
1156        }
1157        assert_eq!(contents(&big), (0..33000).collect::<Vec<_>>());
1158        // Pushing past a full 32768-element tree grows a new root level.
1159        let grown = (0..32768i64).fold(Standard::new(), |v, i| v.push_last(i));
1160        assert_eq!(grown.len(), 32768);
1161        let grown = grown.push_last(32768);
1162        assert_eq!(grown.len(), 32769);
1163        assert_eq!(grown.get(32768), Some(&32768));
1164        assert_eq!(grown.get(0), Some(&0));
1165    }
1166
1167    #[test]
1168    fn pop_to_empty() {
1169        let mut vector = Standard::from_iter(0..2000i64);
1170        for expected in (0..2000i64).rev() {
1171            assert_eq!(vector.len() as i64, expected + 1);
1172            assert_eq!(vector.get(expected as usize), Some(&expected));
1173            vector = vector.pop_last_value().expect("pop non-empty vector");
1174        }
1175        assert!(vector.is_empty());
1176        assert_eq!(vector.pop_last_value(), None);
1177        // Reuse after popping to empty.
1178        let refilled = (0..40).fold(vector, |v, i| v.push_last(i));
1179        assert_eq!(contents(&refilled), (0..40).collect::<Vec<_>>());
1180    }
1181
1182    #[test]
1183    fn assoc_at_all_tree_levels() {
1184        let vector = Standard::from_iter(0..40000i64);
1185        for index in [0usize, 1, 31, 32, 33, 1000, 1024, 1056, 32767, 32768, 39999] {
1186            let updated = vector.assoc_value(index, -(index as i64)).unwrap();
1187            assert_eq!(updated.get(index), Some(&(-(index as i64))));
1188            assert_eq!(
1189                vector.get(index),
1190                Some(&(index as i64)),
1191                "persistent source mutated"
1192            );
1193            assert_eq!(updated.len(), vector.len());
1194        }
1195        // assoc at len appends; past len is out of bounds.
1196        let appended = vector.assoc_value(40000, -1).unwrap();
1197        assert_eq!(appended.len(), 40001);
1198        assert_eq!(appended.get(40000), Some(&-1));
1199        assert!(vector.assoc_value(40001, -1).is_none());
1200    }
1201
1202    #[test]
1203    fn subview_semantics() {
1204        let vector = Standard::from_iter(0..100i64);
1205        let view = vector.subview(10, 50).unwrap();
1206        assert_eq!(view.len(), 40);
1207        assert_eq!(view.get(0), Some(&10));
1208        assert_eq!(view.get(39), Some(&49));
1209        assert_eq!(view.get(40), None);
1210        assert_eq!(
1211            view.iter().copied().collect::<Vec<_>>(),
1212            (10..50).collect::<Vec<_>>()
1213        );
1214
1215        // push through the view writes through to index `end` of the backing
1216        // vector and extends the view; the original vector is untouched.
1217        let pushed = view.push_last(1000);
1218        assert_eq!(pushed.len(), 41);
1219        assert_eq!(pushed.get(40), Some(&1000));
1220        assert_eq!(vector.get(50), Some(&50));
1221
1222        // pop shrinks the view only.
1223        let popped = view.pop_last_value().unwrap();
1224        assert_eq!(popped.len(), 39);
1225        assert_eq!(popped.get(38), Some(&48));
1226        assert_eq!(view.len(), 40);
1227
1228        // assoc writes through; assoc at len extends like push_last.
1229        let updated = view.assoc_value(0, -1).unwrap();
1230        assert_eq!(updated.get(0), Some(&-1));
1231        assert_eq!(updated.len(), 40);
1232        assert_eq!(vector.get(10), Some(&10));
1233        let extended = view.assoc_value(40, 777).unwrap();
1234        assert_eq!(extended.len(), 41);
1235        assert_eq!(extended.get(40), Some(&777));
1236        assert!(view.assoc_value(41, 0).is_none());
1237
1238        // nested subview composes offsets.
1239        let nested = view.subview(5, 10).unwrap();
1240        assert_eq!(nested.len(), 5);
1241        assert_eq!(nested.get(0), Some(&15));
1242        assert_eq!(
1243            nested.iter().copied().collect::<Vec<_>>(),
1244            (15..20).collect::<Vec<_>>()
1245        );
1246
1247        // empty view: pop yields None.
1248        let empty = vector.subview(5, 5).unwrap();
1249        assert!(empty.is_empty());
1250        assert!(empty.pop_last_value().is_none());
1251        // out-of-range views rejected.
1252        assert!(vector.subview(0, 101).is_none());
1253        assert!(vector.subview(6, 5).is_none());
1254    }
1255
1256    #[test]
1257    fn transient_round_trip_matches_persistent() {
1258        // Bulk build through the transient.
1259        let mut transient = Mutable::from_iter(0..5000i64);
1260        let frozen = transient.to_persistent();
1261        let persistent = Standard::from_iter(0..5000i64);
1262        assert_eq!(contents(&frozen), (0..5000).collect::<Vec<_>>());
1263        assert_eq!(frozen, persistent);
1264
1265        // Thaw, mutate at every level, push and pop across boundaries, freeze.
1266        let mut model: Vec<i64> = (0..5000).collect();
1267        let mut mutable = frozen.to_mutable();
1268        for index in [0usize, 31, 32, 1024, 4095, 4999] {
1269            mutable.assoc(index, -(index as i64));
1270            model[index] = -(index as i64);
1271        }
1272        for value in 5000..6000i64 {
1273            mutable.push_last(value);
1274            model.push(value);
1275        }
1276        for _ in 0..1500 {
1277            assert_eq!(mutable.pop_last(), model.pop());
1278        }
1279        let refrozen = mutable.to_persistent();
1280        assert_eq!(contents(&refrozen), model);
1281    }
1282
1283    #[test]
1284    fn transient_freeze_trims_tail() {
1285        // Pop into a partial tail, freeze, then keep using the persistent
1286        // vector: the tail must be right-sized (no stale scratch slots).
1287        let mut mutable = Mutable::from_iter(0..100i64);
1288        for _ in 0..40 {
1289            let _ = mutable.pop_last();
1290        }
1291        let frozen = mutable.to_persistent();
1292        assert_eq!(frozen.len(), 60);
1293        assert_eq!(contents(&frozen), (0..60).collect::<Vec<_>>());
1294        let appended = frozen.push_last(100);
1295        assert_eq!(
1296            contents(&appended),
1297            (0..60).chain(std::iter::once(100)).collect::<Vec<_>>()
1298        );
1299        // Freeze on exact tail boundaries too.
1300        let mut boundary = Mutable::from_iter(0..64i64);
1301        let frozen = boundary.to_persistent();
1302        assert_eq!(frozen.len(), 64);
1303        let appended = frozen.push_last(64);
1304        assert_eq!(appended.len(), 65);
1305        assert_eq!(appended.get(64), Some(&64));
1306    }
1307
1308    #[test]
1309    fn mutable_vector_matches_java_update_surface() {
1310        let mut vector = Mutable::from_iter([1, 2, 3]);
1311        assert_eq!(vector.len(), 3);
1312        assert_eq!(vector.get(1), Some(&2));
1313        vector.assoc(1, 5).assoc(3, 4);
1314        assert_eq!(vector.iter().copied().collect::<Vec<_>>(), vec![1, 5, 3, 4]);
1315        assert_eq!(vector.pop_last(), Some(4));
1316        vector.empty();
1317        assert!(vector.is_empty());
1318        assert_eq!(vector.pop_last(), None);
1319        // empty() resets to a usable transient.
1320        vector.push_last(9);
1321        assert_eq!(vector.iter().copied().collect::<Vec<_>>(), vec![9]);
1322    }
1323
1324    #[test]
1325    #[should_panic(expected = "index out of bounds")]
1326    fn mutable_vector_rejects_assoc_past_count() {
1327        let mut vector = Mutable::from_iter([1, 2, 3]);
1328        vector.assoc(4, 5);
1329    }
1330
1331    #[test]
1332    #[should_panic(expected = "mutable vector used after to_persistent")]
1333    fn mutable_vector_is_invalid_after_persisting() {
1334        let vector = (0..4).collect::<Standard<_>>();
1335        let mut mutable = vector.to_mutable();
1336        let _persistent = mutable.to_persistent();
1337        mutable.push_last(5);
1338    }
1339
1340    struct Lcg(u64);
1341
1342    impl Lcg {
1343        fn next(&mut self) -> u64 {
1344            self.0 = self
1345                .0
1346                .wrapping_mul(6364136223846793005)
1347                .wrapping_add(1442695040888963407);
1348            self.0 >> 11
1349        }
1350
1351        fn below(&mut self, n: usize) -> usize {
1352            (self.next() % n as u64) as usize
1353        }
1354    }
1355
1356    #[test]
1357    fn fuzz_matches_vec_model() {
1358        let mut rng = Lcg(0x9E3779B97F4A7C15);
1359        let mut model: Vec<i64> = Vec::new();
1360        let mut persistent: Standard<i64> = Standard::new();
1361        let mut transient: Mutable<i64> = Mutable::new();
1362        for step in 0..6000 {
1363            match rng.below(10) {
1364                0..=4 => {
1365                    let value = rng.next() as i64;
1366                    model.push(value);
1367                    persistent = persistent.push_last(value);
1368                    transient.push_last(value);
1369                }
1370                5..=6 => {
1371                    if !model.is_empty() {
1372                        model.pop();
1373                        persistent = persistent.pop_last_value().unwrap();
1374                        let _ = transient.pop_last();
1375                    }
1376                }
1377                _ => {
1378                    if !model.is_empty() {
1379                        let index = rng.below(model.len());
1380                        let value = rng.next() as i64;
1381                        model[index] = value;
1382                        persistent = persistent.assoc_value(index, value).unwrap();
1383                        transient.assoc(index, value);
1384                    }
1385                }
1386            }
1387            if step % 97 == 0 {
1388                assert_eq!(
1389                    persistent.iter().copied().collect::<Vec<_>>(),
1390                    model,
1391                    "persistent diverged at step {step}"
1392                );
1393                assert_eq!(
1394                    transient.iter().copied().collect::<Vec<_>>(),
1395                    model,
1396                    "transient diverged at step {step}"
1397                );
1398            }
1399            if step % 501 == 0 {
1400                // Freeze the transient and thaw a fresh one from the result.
1401                let frozen = transient.to_persistent();
1402                assert_eq!(frozen.iter().copied().collect::<Vec<_>>(), model);
1403                assert_eq!(frozen, persistent);
1404                transient = frozen.to_mutable();
1405                persistent = frozen;
1406            }
1407        }
1408    }
1409}