Skip to main content

triblespace_core/
patch.rs

1//! Persistent Adaptive Trie with Cuckoo-compression and
2//! Hash-maintenance (PATCH).
3//!
4//! See the [PATCH](../book/src/deep-dive/patch.md) chapter of the Tribles Book
5//! for the full design description and hashing scheme.
6//!
7//! Values stored in leaves are not part of hashing or equality comparisons.
8//! Two [`PATCH`](crate::patch::PATCH)es are considered equal if they contain the same set of keys,
9//! even if the associated values differ. This allows using the structure as an
10//! idempotent blobstore where a value's hash determines its key.
11//!
12#![allow(unstable_name_collisions)]
13
14mod branch;
15/// Byte-indexed lookup tables used by PATCH branch nodes.
16pub mod bytetable;
17mod entry;
18mod leaf;
19
20use arrayvec::ArrayVec;
21
22use branch::*;
23/// Re-export of [`Entry`](entry::Entry).
24pub use entry::Entry;
25use leaf::*;
26
27/// Re-export of all byte table utilities.
28pub use bytetable::*;
29use rand::thread_rng;
30use rand::RngCore;
31use std::cmp::Reverse;
32use std::convert::TryInto;
33use std::fmt;
34use std::fmt::Debug;
35use std::marker::PhantomData;
36use std::ptr::NonNull;
37use std::sync::Once;
38
39#[cfg(not(target_pointer_width = "64"))]
40compile_error!("PATCH tagged pointers require 64-bit targets");
41
42static mut SIP_KEY: [u8; 16] = [0; 16];
43static INIT: Once = Once::new();
44
45/// Initializes the SIP key used for key hashing.
46/// This function is called automatically when a new PATCH is created.
47fn init_sip_key() {
48    INIT.call_once(|| {
49        bytetable::init();
50
51        let mut rng = thread_rng();
52        unsafe {
53            rng.fill_bytes(&mut SIP_KEY[..]);
54        }
55    });
56}
57
58/// Builds a per-byte segment map from the segment lengths.
59///
60/// The returned table maps each key byte to its segment index.
61pub const fn build_segmentation<const N: usize, const M: usize>(lens: [usize; M]) -> [usize; N] {
62    let mut res = [0; N];
63    let mut seg = 0;
64    let mut off = 0;
65    while seg < M {
66        let len = lens[seg];
67        let mut i = 0;
68        while i < len {
69            res[off + i] = seg;
70            i += 1;
71        }
72        off += len;
73        seg += 1;
74    }
75    res
76}
77
78/// Builds an identity permutation table of length `N`.
79pub const fn identity_map<const N: usize>() -> [usize; N] {
80    let mut res = [0; N];
81    let mut i = 0;
82    while i < N {
83        res[i] = i;
84        i += 1;
85    }
86    res
87}
88
89/// Builds a table translating indices from key order to tree order.
90///
91/// `lens` describes the segment lengths in key order and `perm` is the
92/// permutation of those segments in tree order.
93pub const fn build_key_to_tree<const N: usize, const M: usize>(
94    lens: [usize; M],
95    perm: [usize; M],
96) -> [usize; N] {
97    let mut key_starts = [0; M];
98    let mut off = 0;
99    let mut i = 0;
100    while i < M {
101        key_starts[i] = off;
102        off += lens[i];
103        i += 1;
104    }
105
106    let mut tree_starts = [0; M];
107    off = 0;
108    i = 0;
109    while i < M {
110        let seg = perm[i];
111        tree_starts[seg] = off;
112        off += lens[seg];
113        i += 1;
114    }
115
116    let mut res = [0; N];
117    let mut seg = 0;
118    while seg < M {
119        let len = lens[seg];
120        let ks = key_starts[seg];
121        let ts = tree_starts[seg];
122        let mut j = 0;
123        while j < len {
124            res[ks + j] = ts + j;
125            j += 1;
126        }
127        seg += 1;
128    }
129    res
130}
131
132/// Inverts a permutation table.
133pub const fn invert<const N: usize>(arr: [usize; N]) -> [usize; N] {
134    let mut res = [0; N];
135    let mut i = 0;
136    while i < N {
137        res[arr[i]] = i;
138        i += 1;
139    }
140    res
141}
142
143#[doc(hidden)]
144#[macro_export]
145macro_rules! key_segmentation {
146    (@count $($e:expr),* $(,)?) => {
147        <[()]>::len(&[$($crate::key_segmentation!(@sub $e)),*])
148    };
149    (@sub $e:expr) => { () };
150    ($(#[$meta:meta])* $name:ident, $len:expr, [$($seg_len:expr),+ $(,)?]) => {
151        $(#[$meta])*
152        #[derive(Copy, Clone, Debug)]
153        pub struct $name;
154        impl $name {
155            pub const SEG_LENS: [usize; $crate::key_segmentation!(@count $($seg_len),*)] = [$($seg_len),*];
156        }
157        impl $crate::patch::KeySegmentation<$len> for $name {
158            const SEGMENTS: [usize; $len] = $crate::patch::build_segmentation::<$len, {$crate::key_segmentation!(@count $($seg_len),*)}>(Self::SEG_LENS);
159        }
160    };
161}
162
163#[doc(hidden)]
164#[macro_export]
165macro_rules! key_schema {
166    (@count $($e:expr),* $(,)?) => {
167        <[()]>::len(&[$($crate::key_schema!(@sub $e)),*])
168    };
169    (@sub $e:expr) => { () };
170    ($(#[$meta:meta])* $name:ident, $seg:ty, $len:expr, [$($perm:expr),+ $(,)?]) => {
171        $(#[$meta])*
172        #[derive(Copy, Clone, Debug)]
173        pub struct $name;
174        impl $crate::patch::KeySchema<$len> for $name {
175            type Segmentation = $seg;
176            const SEGMENT_PERM: &'static [usize] = &[$($perm),*];
177            const KEY_TO_TREE: [usize; $len] = $crate::patch::build_key_to_tree::<$len, {$crate::key_schema!(@count $($perm),*)}>(<$seg>::SEG_LENS, [$($perm),*]);
178            const TREE_TO_KEY: [usize; $len] = $crate::patch::invert(Self::KEY_TO_TREE);
179        }
180    };
181}
182
183/// A trait is used to provide a re-ordered view of the keys stored in the PATCH.
184/// This allows for different PATCH instances share the same leaf nodes,
185/// independent of the key ordering used in the tree.
186pub trait KeySchema<const KEY_LEN: usize>: Copy + Clone + Debug {
187    /// The segmentation this ordering operates over.
188    type Segmentation: KeySegmentation<KEY_LEN>;
189    /// Order of segments from key layout to tree layout.
190    const SEGMENT_PERM: &'static [usize];
191    /// Maps each key index to its position in the tree view.
192    const KEY_TO_TREE: [usize; KEY_LEN];
193    /// Maps each tree index to its position in the key view.
194    const TREE_TO_KEY: [usize; KEY_LEN];
195
196    /// Reorders the key from the shared key ordering to the tree ordering.
197    fn tree_ordered(key: &[u8; KEY_LEN]) -> [u8; KEY_LEN] {
198        let mut new_key = [0; KEY_LEN];
199        let mut i = 0;
200        while i < KEY_LEN {
201            new_key[Self::KEY_TO_TREE[i]] = key[i];
202            i += 1;
203        }
204        new_key
205    }
206
207    /// Reorders the key from the tree ordering to the shared key ordering.
208    fn key_ordered(tree_key: &[u8; KEY_LEN]) -> [u8; KEY_LEN] {
209        let mut new_key = [0; KEY_LEN];
210        let mut i = 0;
211        while i < KEY_LEN {
212            new_key[Self::TREE_TO_KEY[i]] = tree_key[i];
213            i += 1;
214        }
215        new_key
216    }
217
218    /// Return the segment index for the byte at `at_depth` in tree ordering.
219    ///
220    /// Default implementation reads the static segmentation table and the
221    /// tree->key mapping. Having this as a method makes call sites clearer and
222    /// reduces the verbosity of expressions that access the segmentation table.
223    fn segment_of_tree_depth(at_depth: usize) -> usize {
224        <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[at_depth]]
225    }
226
227    /// Return true if the tree-ordered bytes at `a` and `b` belong to the same
228    /// logical segment.
229    fn same_segment_tree(a: usize, b: usize) -> bool {
230        <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[a]]
231            == <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[b]]
232    }
233}
234
235/// This trait is used to segment keys stored in the PATCH.
236/// The segmentation is used to determine sub-fields of the key,
237/// allowing for segment based operations, like counting the number
238/// of elements in a segment with a given prefix without traversing the tree.
239///
240/// Note that the segmentation is defined on the shared key ordering,
241/// and should thus be only implemented once, independent of additional key orderings.
242///
243/// See [TribleSegmentation](crate::trible::TribleSegmentation) for an example that segments keys into entity,
244/// attribute, and value segments.
245pub trait KeySegmentation<const KEY_LEN: usize>: Copy + Clone + Debug {
246    /// Segment index for each position in the key.
247    const SEGMENTS: [usize; KEY_LEN];
248}
249
250/// A `KeySchema` that does not reorder the keys.
251/// This is useful for keys that are already ordered in the desired way.
252/// This is the default ordering.
253#[derive(Copy, Clone, Debug)]
254pub struct IdentitySchema {}
255
256/// A `KeySegmentation` that does not segment the keys.
257/// This is useful for keys that do not have a segment structure.
258/// This is the default segmentation.
259#[derive(Copy, Clone, Debug)]
260pub struct SingleSegmentation {}
261impl<const KEY_LEN: usize> KeySchema<KEY_LEN> for IdentitySchema {
262    type Segmentation = SingleSegmentation;
263    const SEGMENT_PERM: &'static [usize] = &[0];
264    const KEY_TO_TREE: [usize; KEY_LEN] = identity_map::<KEY_LEN>();
265    const TREE_TO_KEY: [usize; KEY_LEN] = identity_map::<KEY_LEN>();
266}
267
268impl<const KEY_LEN: usize> KeySegmentation<KEY_LEN> for SingleSegmentation {
269    const SEGMENTS: [usize; KEY_LEN] = [0; KEY_LEN];
270}
271
272#[allow(dead_code)]
273#[derive(Debug, PartialEq, Copy, Clone)]
274#[repr(u8)]
275pub(crate) enum HeadTag {
276    // Stored in the low 4 bits of `Head::tptr` (see Head::new).
277    //
278    // Branch values encode log2(branch_size) (i.e. `Branch2 == 1`, `Branch256
279    // == 8`). `0` is reserved for leaf nodes, which lets us compute the branch
280    // size as `1 << tag` without any offset.
281    Leaf = 0,
282    Branch2 = 1,
283    Branch4 = 2,
284    Branch8 = 3,
285    Branch16 = 4,
286    Branch32 = 5,
287    Branch64 = 6,
288    Branch128 = 7,
289    Branch256 = 8,
290}
291
292impl HeadTag {
293    #[inline]
294    fn from_raw(raw: u8) -> Self {
295        debug_assert!(raw <= HeadTag::Branch256 as u8);
296        // SAFETY: `HeadTag` is `#[repr(u8)]` with a contiguous discriminant
297        // range 0..=8. The tag bits are written by Head::new/set_body and
298        // Branch::tag, which only emit valid discriminants.
299        unsafe { std::mem::transmute(raw) }
300    }
301}
302
303pub(crate) enum BodyPtr<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
304    Leaf(NonNull<Leaf<KEY_LEN, V>>),
305    Branch(branch::BranchNN<KEY_LEN, O, V>),
306}
307
308/// Immutable borrow view of a Head body.
309/// Returned by `body_ref()` and tied to the lifetime of the `&Head`.
310pub(crate) enum BodyRef<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
311    Leaf(&'a Leaf<KEY_LEN, V>),
312    Branch(&'a Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V>>], V>),
313}
314
315/// Mutable borrow view of a Head body.
316/// Returned by `body_mut()` and tied to the lifetime of the `&mut Head`.
317pub(crate) enum BodyMut<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
318    Leaf(&'a mut Leaf<KEY_LEN, V>),
319    Branch(&'a mut Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V>>], V>),
320}
321
322pub(crate) trait Body {
323    fn tag(body: NonNull<Self>) -> HeadTag;
324}
325
326#[repr(C)]
327pub(crate) struct Head<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
328    tptr: std::ptr::NonNull<u8>,
329    key_ordering: PhantomData<O>,
330    key_segments: PhantomData<O::Segmentation>,
331    value: PhantomData<V>,
332}
333
334unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Send for Head<KEY_LEN, O, V> {}
335unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Sync for Head<KEY_LEN, O, V> {}
336
337impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Head<KEY_LEN, O, V> {
338    // Tagged pointer layout (64-bit only):
339    // - bits 0..=3:   HeadTag (requires 16-byte aligned bodies)
340    // - bits 4..=55:  body pointer bits (52 bits)
341    // - bits 56..=63: key byte for cuckoo table lookup
342    const TAG_MASK: u64 = 0x0f;
343    const BODY_MASK: u64 = 0x00_ff_ff_ff_ff_ff_ff_f0;
344    const KEY_MASK: u64 = 0xff_00_00_00_00_00_00_00;
345
346    pub(crate) fn new<T: Body + ?Sized>(key: u8, body: NonNull<T>) -> Self {
347        unsafe {
348            let tptr =
349                std::ptr::NonNull::new_unchecked((body.as_ptr() as *mut u8).map_addr(|addr| {
350                    debug_assert_eq!(addr as u64 & Self::TAG_MASK, 0);
351                    ((addr as u64 & Self::BODY_MASK)
352                        | ((key as u64) << 56)
353                        | (<T as Body>::tag(body) as u64)) as usize
354                }));
355            Self {
356                tptr,
357                key_ordering: PhantomData,
358                key_segments: PhantomData,
359                value: PhantomData,
360            }
361        }
362    }
363
364    #[inline]
365    pub(crate) fn tag(&self) -> HeadTag {
366        HeadTag::from_raw((self.tptr.as_ptr() as u64 & Self::TAG_MASK) as u8)
367    }
368
369    #[inline]
370    pub(crate) fn key(&self) -> u8 {
371        (self.tptr.as_ptr() as u64 >> 56) as u8
372    }
373
374    #[inline]
375    pub(crate) fn with_key(mut self, key: u8) -> Self {
376        self.tptr =
377            std::ptr::NonNull::new(self.tptr.as_ptr().map_addr(|addr| {
378                ((addr as u64 & !Self::KEY_MASK) | ((key as u64) << 56)) as usize
379            }))
380            .unwrap();
381        self
382    }
383
384    #[inline]
385    pub(crate) fn set_body<T: Body + ?Sized>(&mut self, body: NonNull<T>) {
386        unsafe {
387            self.tptr = NonNull::new_unchecked((body.as_ptr() as *mut u8).map_addr(|addr| {
388                debug_assert_eq!(addr as u64 & Self::TAG_MASK, 0);
389                ((addr as u64 & Self::BODY_MASK)
390                    | (self.tptr.as_ptr() as u64 & Self::KEY_MASK)
391                    | (<T as Body>::tag(body) as u64)) as usize
392            }))
393        }
394    }
395
396    pub(crate) fn with_start(self, new_start_depth: usize) -> Head<KEY_LEN, O, V> {
397        let leaf_key = self.childleaf_key();
398        let i = O::TREE_TO_KEY[new_start_depth];
399        let key = leaf_key[i];
400        self.with_key(key)
401    }
402
403    // Removed childleaf_matches_key_from in favor of composing the existing
404    // has_prefix primitives directly at call sites. Use
405    // `self.has_prefix::<KEY_LEN>(at_depth, key)` or for partial checks
406    // `self.childleaf().has_prefix::<O>(at_depth, &key[..limit])` instead.
407
408    pub(crate) fn body(&self) -> BodyPtr<KEY_LEN, O, V> {
409        unsafe {
410            let ptr = NonNull::new_unchecked(self.tptr.as_ptr().map_addr(|addr| {
411                let masked = (addr as u64) & Self::BODY_MASK;
412                masked as usize
413            }));
414            match self.tag() {
415                HeadTag::Leaf => BodyPtr::Leaf(ptr.cast()),
416                branch_tag => {
417                    let count = 1 << (branch_tag as usize);
418                    BodyPtr::Branch(NonNull::new_unchecked(std::ptr::slice_from_raw_parts(
419                        ptr.as_ptr(),
420                        count,
421                    )
422                        as *mut Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V>>], V>))
423                }
424            }
425        }
426    }
427
428    pub(crate) fn body_mut(&mut self) -> BodyMut<'_, KEY_LEN, O, V> {
429        unsafe {
430            match self.body() {
431                BodyPtr::Leaf(mut leaf) => BodyMut::Leaf(leaf.as_mut()),
432                BodyPtr::Branch(mut branch) => {
433                    // Ensure ownership: try copy-on-write and update local pointer if needed.
434                    let mut branch_nn = branch;
435                    if Branch::rc_cow(&mut branch_nn).is_some() {
436                        self.set_body(branch_nn);
437                        BodyMut::Branch(branch_nn.as_mut())
438                    } else {
439                        BodyMut::Branch(branch.as_mut())
440                    }
441                }
442            }
443        }
444    }
445
446    /// Returns an immutable borrow of the body (Leaf or Branch) tied to &self.
447    pub(crate) fn body_ref(&self) -> BodyRef<'_, KEY_LEN, O, V> {
448        match self.body() {
449            BodyPtr::Leaf(nn) => BodyRef::Leaf(unsafe { nn.as_ref() }),
450            BodyPtr::Branch(nn) => BodyRef::Branch(unsafe { nn.as_ref() }),
451        }
452    }
453
454    pub(crate) fn count(&self) -> u64 {
455        match self.body_ref() {
456            BodyRef::Leaf(_) => 1,
457            BodyRef::Branch(branch) => branch.leaf_count,
458        }
459    }
460
461    pub(crate) fn count_segment(&self, at_depth: usize) -> u64 {
462        match self.body_ref() {
463            BodyRef::Leaf(_) => 1,
464            BodyRef::Branch(branch) => branch.count_segment(at_depth),
465        }
466    }
467
468    pub(crate) fn hash(&self) -> u128 {
469        match self.body_ref() {
470            BodyRef::Leaf(leaf) => leaf.hash,
471            BodyRef::Branch(branch) => branch.hash,
472        }
473    }
474
475    pub(crate) fn end_depth(&self) -> usize {
476        match self.body_ref() {
477            BodyRef::Leaf(_) => KEY_LEN,
478            BodyRef::Branch(branch) => branch.end_depth as usize,
479        }
480    }
481
482    /// Return the raw pointer to the child leaf for use in low-level
483    /// operations (for example when constructing a Branch). Prefer
484    /// `childleaf_key()` or other safe accessors when you only need the
485    /// key or value; those avoid unsafe dereferences.
486    pub(crate) fn childleaf_ptr(&self) -> *const Leaf<KEY_LEN, V> {
487        match self.body_ref() {
488            BodyRef::Leaf(leaf) => leaf as *const Leaf<KEY_LEN, V>,
489            BodyRef::Branch(branch) => branch.childleaf_ptr(),
490        }
491    }
492
493    pub(crate) fn childleaf_key(&self) -> &[u8; KEY_LEN] {
494        match self.body_ref() {
495            BodyRef::Leaf(leaf) => &leaf.key,
496            BodyRef::Branch(branch) => &branch.childleaf().key,
497        }
498    }
499
500    // Slot wrapper defined at module level (moved to below the impl block)
501
502    /// Find the first depth in [start_depth, limit) where the tree-ordered
503    /// bytes of `self` and `other` differ. The comparison limit is computed
504    /// as min(self.end_depth(), other.end_depth(), KEY_LEN) which is the
505    /// natural bound for comparing two heads. Returns `Some((depth, a, b))`
506    /// where `a` and `b` are the differing bytes at that depth, or `None`
507    /// if no divergence is found in the range.
508    pub(crate) fn first_divergence(
509        &self,
510        other: &Self,
511        start_depth: usize,
512    ) -> Option<(usize, u8, u8)> {
513        let limit = std::cmp::min(std::cmp::min(self.end_depth(), other.end_depth()), KEY_LEN);
514        debug_assert!(limit <= KEY_LEN);
515        let this_key = self.childleaf_key();
516        let other_key = other.childleaf_key();
517        let mut depth = start_depth;
518        while depth < limit {
519            let i = O::TREE_TO_KEY[depth];
520            let a = this_key[i];
521            let b = other_key[i];
522            if a != b {
523                return Some((depth, a, b));
524            }
525            depth += 1;
526        }
527        None
528    }
529
530    // Mutable access to the child slots for this head. If the head is a
531    // branch, returns a mutable slice referencing the underlying child table
532    // (each element is Option<Head>). If the head is a leaf an empty slice
533    // is returned.
534    //
535    // The caller receives a &mut slice tied to the borrow of `self` and may
536    // reorder entries in-place (e.g., sort_unstable) and then take them using
537    // `Option::take()` to extract Head values. The call uses `body_mut()` so
538    // COW semantics are preserved and callers have exclusive access to the
539    // branch storage while the mutable borrow lasts.
540    // NOTE: mut_children removed — prefer matching on BodyRef returned by
541    // `body_mut()` and operating directly on the `&mut Branch` reference.
542
543    pub(crate) fn remove_leaf(
544        slot: &mut Option<Self>,
545        leaf_key: &[u8; KEY_LEN],
546        start_depth: usize,
547    ) {
548        if let Some(this) = slot {
549            let end_depth = std::cmp::min(this.end_depth(), KEY_LEN);
550            // Check reachable equality by asking the head to test the prefix
551            // up to its end_depth. Using the head/leaf primitive centralises the
552            // unsafe deref into Branch::childleaf()/Leaf::has_prefix.
553            if !this.has_prefix::<KEY_LEN>(start_depth, leaf_key) {
554                return;
555            }
556            if this.tag() == HeadTag::Leaf {
557                slot.take();
558            } else {
559                let mut ed = crate::patch::branch::BranchMut::from_head(this);
560                let key = leaf_key[end_depth];
561                ed.modify_child(key, |mut opt| {
562                    Self::remove_leaf(&mut opt, leaf_key, end_depth);
563                    opt
564                });
565
566                // If the branch now contains a single remaining child we
567                // collapse the branch upward into that child. We must pull
568                // the remaining child out while `ed` is still borrowed,
569                // then drop `ed` before writing back into `slot` to avoid
570                // double mutable borrows of the slot.
571                if ed.leaf_count == 1 {
572                    let mut remaining: Option<Head<KEY_LEN, O, V>> = None;
573                    for slot_child in &mut ed.child_table {
574                        if let Some(child) = slot_child.take() {
575                            remaining = Some(child.with_start(start_depth));
576                            break;
577                        }
578                    }
579                    drop(ed);
580                    if let Some(child) = remaining {
581                        slot.replace(child);
582                    }
583                } else {
584                    // ensure we drop the editor when not collapsing so the
585                    // final pointer is committed back into the head.
586                    drop(ed);
587                }
588            }
589        }
590    }
591
592    // NOTE: slot-level wrappers removed; callers should take the slot and call
593    // the owned helpers (insert_leaf / replace_leaf / union)
594    // directly. This reduces the indirection and keeps ownership semantics
595    // explicit at the call site.
596
597    // Owned variants of the slot-based helpers. These accept the existing
598    // Head by value and return the new Head after performing the
599    // modification. They are used with the split `insert_child` /
600    // `update_child` APIs so we no longer need `Branch::upsert_child`.
601    pub(crate) fn insert_leaf(mut this: Self, leaf: Self, start_depth: usize) -> Self {
602        if let Some((depth, this_byte_key, leaf_byte_key)) =
603            this.first_divergence(&leaf, start_depth)
604        {
605            let old_key = this.key();
606            let new_body = Branch::new(
607                depth,
608                this.with_key(this_byte_key),
609                leaf.with_key(leaf_byte_key),
610            );
611            return Head::new(old_key, new_body);
612        }
613
614        let end_depth = this.end_depth();
615        if end_depth != KEY_LEN {
616            // Use the editable BranchMut view to perform mutations without
617            // exposing pointer juggling at the call site.
618            let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
619            let inserted = leaf.with_start(ed.end_depth as usize);
620            let key = inserted.key();
621            ed.modify_child(key, |opt| match opt {
622                Some(old) => Some(Head::insert_leaf(old, inserted, end_depth)),
623                None => Some(inserted),
624            });
625        }
626        this
627    }
628
629    pub(crate) fn replace_leaf(mut this: Self, leaf: Self, start_depth: usize) -> Self {
630        if let Some((depth, this_byte_key, leaf_byte_key)) =
631            this.first_divergence(&leaf, start_depth)
632        {
633            let old_key = this.key();
634            let new_body = Branch::new(
635                depth,
636                this.with_key(this_byte_key),
637                leaf.with_key(leaf_byte_key),
638            );
639
640            return Head::new(old_key, new_body);
641        }
642
643        let end_depth = this.end_depth();
644        if end_depth == KEY_LEN {
645            let old_key = this.key();
646            return leaf.with_key(old_key);
647        } else {
648            // Use the editor view for branch mutation instead of raw pointer ops.
649            let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
650            let inserted = leaf.with_start(ed.end_depth as usize);
651            let key = inserted.key();
652            ed.modify_child(key, |opt| match opt {
653                Some(old) => Some(Head::replace_leaf(old, inserted, end_depth)),
654                None => Some(inserted),
655            });
656        }
657        this
658    }
659
660    pub(crate) fn union(mut this: Self, mut other: Self, at_depth: usize) -> Self {
661        if this.hash() == other.hash() {
662            return this;
663        }
664
665        if let Some((depth, this_byte_key, other_byte_key)) =
666            this.first_divergence(&other, at_depth)
667        {
668            let old_key = this.key();
669            let new_body = Branch::new(
670                depth,
671                this.with_key(this_byte_key),
672                other.with_key(other_byte_key),
673            );
674
675            return Head::new(old_key, new_body);
676        }
677
678        let this_depth = this.end_depth();
679        let other_depth = other.end_depth();
680        if this_depth < other_depth {
681            // Use BranchMut to edit `this` safely and avoid pointer juggling.
682            let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
683            let inserted = other.with_start(ed.end_depth as usize);
684            let key = inserted.key();
685            ed.modify_child(key, |opt| match opt {
686                Some(old) => Some(Head::union(old, inserted, this_depth)),
687                None => Some(inserted),
688            });
689
690            drop(ed);
691            return this;
692        }
693
694        if other_depth < this_depth {
695            let old_key = this.key();
696            let this_head = this;
697            let mut ed = crate::patch::branch::BranchMut::from_head(&mut other);
698            let inserted = this_head.with_start(ed.end_depth as usize);
699            let key = inserted.key();
700            ed.modify_child(key, |opt| match opt {
701                Some(old) => Some(Head::union(old, inserted, other_depth)),
702                None => Some(inserted),
703            });
704            drop(ed);
705
706            return other.with_key(old_key);
707        }
708
709        // both depths are equal and the hashes differ: merge children
710        let BodyMut::Branch(other_branch_ref) = other.body_mut() else {
711            unreachable!();
712        };
713        {
714            // Editable branch view: construct a BranchMut from the owned `this`
715            // head and perform all mutations via that editor. The editor
716            // performs COW up-front and writes the final pointer back into
717            // `this` when it is dropped.
718            let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
719            for other_child in other_branch_ref
720                .child_table
721                .iter_mut()
722                .filter_map(Option::take)
723            {
724                let inserted = other_child.with_start(ed.end_depth as usize);
725                let key = inserted.key();
726                ed.modify_child(key, |opt| match opt {
727                    Some(old) => Some(Head::union(old, inserted, this_depth)),
728                    None => Some(inserted),
729                });
730            }
731        }
732        this
733    }
734
735    pub(crate) fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
736        &self,
737        prefix: &[u8; PREFIX_LEN],
738        at_depth: usize,
739        f: &mut F,
740    ) where
741        F: FnMut(&[u8; INFIX_LEN]),
742    {
743        match self.body_ref() {
744            BodyRef::Leaf(leaf) => leaf.infixes::<PREFIX_LEN, INFIX_LEN, O, F>(prefix, at_depth, f),
745            BodyRef::Branch(branch) => {
746                branch.infixes::<PREFIX_LEN, INFIX_LEN, F>(prefix, at_depth, f)
747            }
748        }
749    }
750
751    pub(crate) fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
752        &self,
753        prefix: &[u8; PREFIX_LEN],
754        at_depth: usize,
755        min_infix: &[u8; INFIX_LEN],
756        max_infix: &[u8; INFIX_LEN],
757        f: &mut F,
758    ) where
759        F: FnMut(&[u8; INFIX_LEN]),
760    {
761        match self.body_ref() {
762            BodyRef::Leaf(leaf) => leaf.infixes_range::<PREFIX_LEN, INFIX_LEN, O, F>(
763                prefix, at_depth, min_infix, max_infix, f,
764            ),
765            BodyRef::Branch(branch) => branch.infixes_range::<PREFIX_LEN, INFIX_LEN, F>(
766                prefix, at_depth, min_infix, max_infix, f,
767            ),
768        }
769    }
770
771    pub(crate) fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
772        &self,
773        prefix: &[u8; PREFIX_LEN],
774        at_depth: usize,
775        min_infix: &[u8; INFIX_LEN],
776        max_infix: &[u8; INFIX_LEN],
777    ) -> u64 {
778        match self.body_ref() {
779            BodyRef::Leaf(leaf) => {
780                leaf.count_range::<PREFIX_LEN, INFIX_LEN, O>(prefix, at_depth, min_infix, max_infix)
781            }
782            BodyRef::Branch(branch) => {
783                branch.count_range::<PREFIX_LEN, INFIX_LEN>(prefix, at_depth, min_infix, max_infix)
784            }
785        }
786    }
787
788    pub(crate) fn has_prefix<const PREFIX_LEN: usize>(
789        &self,
790        at_depth: usize,
791        prefix: &[u8; PREFIX_LEN],
792    ) -> bool {
793        const {
794            assert!(PREFIX_LEN <= KEY_LEN);
795        }
796        match self.body_ref() {
797            BodyRef::Leaf(leaf) => leaf.has_prefix::<O>(at_depth, prefix),
798            BodyRef::Branch(branch) => branch.has_prefix::<PREFIX_LEN>(at_depth, prefix),
799        }
800    }
801
802    pub(crate) fn get<'a>(&'a self, at_depth: usize, key: &[u8; KEY_LEN]) -> Option<&'a V>
803    where
804        O: 'a,
805    {
806        match self.body_ref() {
807            BodyRef::Leaf(leaf) => leaf.get::<O>(at_depth, key),
808            BodyRef::Branch(branch) => branch.get(at_depth, key),
809        }
810    }
811
812    pub(crate) fn segmented_len<const PREFIX_LEN: usize>(
813        &self,
814        at_depth: usize,
815        prefix: &[u8; PREFIX_LEN],
816    ) -> u64 {
817        match self.body_ref() {
818            BodyRef::Leaf(leaf) => leaf.segmented_len::<O, PREFIX_LEN>(at_depth, prefix),
819            BodyRef::Branch(branch) => branch.segmented_len::<PREFIX_LEN>(at_depth, prefix),
820        }
821    }
822
823    // NOTE: slot-level union wrapper removed; callers should take the slot and
824    // call the owned helper `union` directly.
825
826    pub(crate) fn intersect(&self, other: &Self, at_depth: usize) -> Option<Self> {
827        if self.hash() == other.hash() {
828            return Some(self.clone());
829        }
830
831        if self.first_divergence(other, at_depth).is_some() {
832            return None;
833        }
834
835        let self_depth = self.end_depth();
836        let other_depth = other.end_depth();
837        if self_depth < other_depth {
838            // This means that there can be at most one child in self
839            // that might intersect with other.
840            let BodyRef::Branch(branch) = self.body_ref() else {
841                unreachable!();
842            };
843            return branch
844                .child_table
845                .table_get(other.childleaf_key()[O::TREE_TO_KEY[self_depth]])
846                .and_then(|self_child| other.intersect(self_child, self_depth));
847        }
848
849        if other_depth < self_depth {
850            // This means that there can be at most one child in other
851            // that might intersect with self.
852            // If the depth of other is less than the depth of self, then it can't be a leaf.
853            let BodyRef::Branch(other_branch) = other.body_ref() else {
854                unreachable!();
855            };
856            return other_branch
857                .child_table
858                .table_get(self.childleaf_key()[O::TREE_TO_KEY[other_depth]])
859                .and_then(|other_child| self.intersect(other_child, other_depth));
860        }
861
862        // If we reached this point then the depths are equal. The only way to have a leaf
863        // is if the other is a leaf as well, which is already handled by the hash check if they are equal,
864        // and by the key check if they are not equal.
865        // If one of them is a leaf and the other is a branch, then they would also have different depths,
866        // which is already handled by the above code.
867        let BodyRef::Branch(self_branch) = self.body_ref() else {
868            unreachable!();
869        };
870        let BodyRef::Branch(other_branch) = other.body_ref() else {
871            unreachable!();
872        };
873
874        let mut intersected_children = self_branch
875            .child_table
876            .iter()
877            .filter_map(Option::as_ref)
878            .filter_map(|self_child| {
879                let other_child = other_branch.child_table.table_get(self_child.key())?;
880                self_child.intersect(other_child, self_depth)
881            });
882        let first_child = intersected_children.next()?;
883        let Some(second_child) = intersected_children.next() else {
884            return Some(first_child);
885        };
886        let new_branch = Branch::new(
887            self_depth,
888            first_child.with_start(self_depth),
889            second_child.with_start(self_depth),
890        );
891        // Use a BranchMut editor to perform all child insertions via the
892        // safe editor API instead of manipulating the NonNull pointer
893        // directly. The editor will perform COW and commit the final
894        // pointer into the Head when it is dropped.
895        let mut head_for_branch = Head::new(0, new_branch);
896        {
897            let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
898            for child in intersected_children {
899                let inserted = child.with_start(self_depth);
900                let k = inserted.key();
901                ed.modify_child(k, |_opt| Some(inserted));
902            }
903            // ed dropped here commits the final branch pointer into head_for_branch
904        }
905        Some(head_for_branch)
906    }
907
908    /// Returns the difference between self and other.
909    /// This is the set of elements that are in self but not in other.
910    /// If the difference is empty, None is returned.
911    pub(crate) fn difference(&self, other: &Self, at_depth: usize) -> Option<Self> {
912        if self.hash() == other.hash() {
913            return None;
914        }
915
916        if self.first_divergence(other, at_depth).is_some() {
917            return Some(self.clone());
918        }
919
920        let self_depth = self.end_depth();
921        let other_depth = other.end_depth();
922        if self_depth < other_depth {
923            // This means that there can be at most one child in self
924            // that might intersect with other. It's the only child that may not be in the difference.
925            // The other children are definitely in the difference, as they have no corresponding byte in other.
926            // Thus the cheapest way to compute the difference is compute the difference of the only child
927            // that might intersect with other, copy self with it's correctly filled byte table, then
928            // remove the old child, and insert the new child.
929            let mut new_branch = self.clone();
930            let other_byte_key = other.childleaf_key()[O::TREE_TO_KEY[self_depth]];
931            {
932                let mut ed = crate::patch::branch::BranchMut::from_head(&mut new_branch);
933                ed.modify_child(other_byte_key, |opt| {
934                    opt.and_then(|child| child.difference(other, self_depth))
935                });
936            }
937            return Some(new_branch);
938        }
939
940        if other_depth < self_depth {
941            // This means that we need to check if there is a child in other
942            // that matches the path at the current depth of self.
943            // There is no such child, then then self must be in the difference.
944            // If there is such a child, then we have to compute the difference
945            // between self and that child.
946            // We know that other must be a branch.
947            let BodyRef::Branch(other_branch) = other.body_ref() else {
948                unreachable!();
949            };
950            let self_byte_key = self.childleaf_key()[O::TREE_TO_KEY[other_depth]];
951            if let Some(other_child) = other_branch.child_table.table_get(self_byte_key) {
952                return self.difference(other_child, at_depth);
953            } else {
954                return Some(self.clone());
955            }
956        }
957
958        // If we reached this point then the depths are equal. The only way to have a leaf
959        // is if the other is a leaf as well, which is already handled by the hash check if they are equal,
960        // and by the key check if they are not equal.
961        // If one of them is a leaf and the other is a branch, then they would also have different depths,
962        // which is already handled by the above code.
963        let BodyRef::Branch(self_branch) = self.body_ref() else {
964            unreachable!();
965        };
966        let BodyRef::Branch(other_branch) = other.body_ref() else {
967            unreachable!();
968        };
969
970        let mut differenced_children = self_branch
971            .child_table
972            .iter()
973            .filter_map(Option::as_ref)
974            .filter_map(|self_child| {
975                if let Some(other_child) = other_branch.child_table.table_get(self_child.key()) {
976                    self_child.difference(other_child, self_depth)
977                } else {
978                    Some(self_child.clone())
979                }
980            });
981
982        let first_child = differenced_children.next()?;
983        let second_child = match differenced_children.next() {
984            Some(sc) => sc,
985            None => return Some(first_child),
986        };
987
988        let new_branch = Branch::new(
989            self_depth,
990            first_child.with_start(self_depth),
991            second_child.with_start(self_depth),
992        );
993        let mut head_for_branch = Head::new(0, new_branch);
994        {
995            let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
996            for child in differenced_children {
997                let inserted = child.with_start(self_depth);
998                let k = inserted.key();
999                ed.modify_child(k, |_opt| Some(inserted));
1000            }
1001            // ed dropped here commits the final branch pointer into head_for_branch
1002        }
1003        // The key will be set later, because we don't know it yet.
1004        // The difference might remove multiple levels of branches,
1005        // so we can't just take the key from self or other.
1006        Some(head_for_branch)
1007    }
1008}
1009
1010unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ByteEntry for Head<KEY_LEN, O, V> {
1011    fn key(&self) -> u8 {
1012        self.key()
1013    }
1014}
1015
1016impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> fmt::Debug for Head<KEY_LEN, O, V> {
1017    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1018        self.tag().fmt(f)
1019    }
1020}
1021
1022impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Clone for Head<KEY_LEN, O, V> {
1023    fn clone(&self) -> Self {
1024        unsafe {
1025            match self.body() {
1026                BodyPtr::Leaf(leaf) => Self::new(self.key(), Leaf::rc_inc(leaf)),
1027                BodyPtr::Branch(branch) => Self::new(self.key(), Branch::rc_inc(branch)),
1028            }
1029        }
1030    }
1031}
1032
1033// The Slot wrapper was removed in favor of using BranchMut::from_slot(&mut
1034// Option<Head<...>>) directly. This keeps the API surface smaller and
1035// avoids an extra helper type that simply forwarded to BranchMut.
1036
1037impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Drop for Head<KEY_LEN, O, V> {
1038    fn drop(&mut self) {
1039        unsafe {
1040            match self.body() {
1041                BodyPtr::Leaf(leaf) => Leaf::rc_dec(leaf),
1042                BodyPtr::Branch(branch) => Branch::rc_dec(branch),
1043            }
1044        }
1045    }
1046}
1047
1048/// A PATCH is a persistent data structure that stores a set of keys.
1049/// Each key can be reordered and segmented, based on the provided key ordering and segmentation.
1050///
1051/// The patch supports efficient set operations, like union, intersection, and difference,
1052/// because it efficiently maintains a hash for all keys that are part of a sub-tree.
1053///
1054/// The tree itself is a path- and node-compressed a 256-ary trie.
1055/// Each nodes stores its children in a byte oriented cuckoo hash table,
1056/// allowing for O(1) access to children, while keeping the memory overhead low.
1057/// Table sizes are powers of two, starting at 2.
1058///
1059/// Having a single node type for all branching factors simplifies the implementation,
1060/// compared to other adaptive trie implementations, like ARTs or Judy Arrays
1061///
1062/// The PATCH allows for cheap copy-on-write operations, with `clone` being O(1).
1063#[derive(Debug)]
1064pub struct PATCH<const KEY_LEN: usize, O = IdentitySchema, V = ()>
1065where
1066    O: KeySchema<KEY_LEN>,
1067{
1068    root: Option<Head<KEY_LEN, O, V>>,
1069}
1070
1071impl<const KEY_LEN: usize, O, V> Clone for PATCH<KEY_LEN, O, V>
1072where
1073    O: KeySchema<KEY_LEN>,
1074{
1075    fn clone(&self) -> Self {
1076        Self {
1077            root: self.root.clone(),
1078        }
1079    }
1080}
1081
1082impl<const KEY_LEN: usize, O, V> Default for PATCH<KEY_LEN, O, V>
1083where
1084    O: KeySchema<KEY_LEN>,
1085{
1086    fn default() -> Self {
1087        Self::new()
1088    }
1089}
1090
1091impl<const KEY_LEN: usize, O, V> PATCH<KEY_LEN, O, V>
1092where
1093    O: KeySchema<KEY_LEN>,
1094{
1095    /// Creates a new empty PATCH.
1096    pub fn new() -> Self {
1097        init_sip_key();
1098        PATCH { root: None }
1099    }
1100
1101    /// Inserts a shared key into the PATCH.
1102    ///
1103    /// Takes an [Entry] object that can be created from a key,
1104    /// and inserted into multiple PATCH instances.
1105    ///
1106    /// If the key is already present, this is a no-op.
1107    pub fn insert(&mut self, entry: &Entry<KEY_LEN, V>) {
1108        if self.root.is_some() {
1109            let this = self.root.take().expect("root should not be empty");
1110            let new_head = Head::insert_leaf(this, entry.leaf(), 0);
1111            self.root.replace(new_head);
1112        } else {
1113            self.root.replace(entry.leaf());
1114        }
1115    }
1116
1117    /// Inserts a key into the PATCH, replacing the value if it already exists.
1118    pub fn replace(&mut self, entry: &Entry<KEY_LEN, V>) {
1119        if self.root.is_some() {
1120            let this = self.root.take().expect("root should not be empty");
1121            let new_head = Head::replace_leaf(this, entry.leaf(), 0);
1122            self.root.replace(new_head);
1123        } else {
1124            self.root.replace(entry.leaf());
1125        }
1126    }
1127
1128    /// Removes a key from the PATCH.
1129    ///
1130    /// If the key is not present, this is a no-op.
1131    pub fn remove(&mut self, key: &[u8; KEY_LEN]) {
1132        Head::remove_leaf(&mut self.root, key, 0);
1133    }
1134
1135    /// Returns the number of keys in the PATCH.
1136    pub fn len(&self) -> u64 {
1137        if let Some(root) = &self.root {
1138            root.count()
1139        } else {
1140            0
1141        }
1142    }
1143
1144    /// Returns true if the PATCH contains no keys.
1145    pub fn is_empty(&self) -> bool {
1146        self.len() == 0
1147    }
1148
1149    pub(crate) fn root_hash(&self) -> Option<u128> {
1150        self.root.as_ref().map(|root| root.hash())
1151    }
1152
1153    /// Returns the value associated with `key` if present.
1154    pub fn get(&self, key: &[u8; KEY_LEN]) -> Option<&V> {
1155        self.root.as_ref().and_then(|root| root.get(0, key))
1156    }
1157
1158    /// Allows iteratig over all infixes of a given length with a given prefix.
1159    /// Each infix is passed to the provided closure.
1160    ///
1161    /// The entire operation is performed over the tree view ordering of the keys.
1162    ///
1163    /// The length of the prefix and the infix is provided as type parameters,
1164    /// but will usually inferred from the arguments.
1165    ///
1166    /// The sum of `PREFIX_LEN` and `INFIX_LEN` must be less than or equal to `KEY_LEN`
1167    /// or a compile-time assertion will fail.
1168    ///
1169    /// Because all infixes are iterated in one go, less bookkeeping is required,
1170    /// than when using an Iterator, allowing for better performance.
1171    pub fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
1172        &self,
1173        prefix: &[u8; PREFIX_LEN],
1174        mut for_each: F,
1175    ) where
1176        F: FnMut(&[u8; INFIX_LEN]),
1177    {
1178        const {
1179            assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
1180        }
1181        assert!(
1182            O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
1183                && (PREFIX_LEN + INFIX_LEN == KEY_LEN
1184                    || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
1185            "INFIX_LEN must cover a whole segment"
1186        );
1187        if let Some(root) = &self.root {
1188            root.infixes(prefix, 0, &mut for_each);
1189        }
1190    }
1191
1192    /// Like [`infixes`](Self::infixes) but only yields infixes in the
1193    /// byte range `[min_infix, max_infix]` (inclusive).
1194    ///
1195    /// The trie is pruned at each depth: branches whose byte key falls
1196    /// outside the range at the current infix position are skipped
1197    /// entirely, avoiding traversal of irrelevant subtrees.
1198    pub fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
1199        &self,
1200        prefix: &[u8; PREFIX_LEN],
1201        min_infix: &[u8; INFIX_LEN],
1202        max_infix: &[u8; INFIX_LEN],
1203        mut for_each: F,
1204    ) where
1205        F: FnMut(&[u8; INFIX_LEN]),
1206    {
1207        const {
1208            assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
1209        }
1210        assert!(
1211            O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
1212                && (PREFIX_LEN + INFIX_LEN == KEY_LEN
1213                    || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
1214            "INFIX_LEN must cover a whole segment"
1215        );
1216        if let Some(root) = &self.root {
1217            root.infixes_range(prefix, 0, min_infix, max_infix, &mut for_each);
1218        }
1219    }
1220
1221    /// Count entries whose infix falls within [min_infix, max_infix].
1222    ///
1223    /// Uses cached `leaf_count` on branches to skip entire subtrees that
1224    /// are fully inside the range, making the count O(boundary_nodes)
1225    /// rather than O(matching_leaves).
1226    pub fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
1227        &self,
1228        prefix: &[u8; PREFIX_LEN],
1229        min_infix: &[u8; INFIX_LEN],
1230        max_infix: &[u8; INFIX_LEN],
1231    ) -> u64 {
1232        const {
1233            assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
1234        }
1235        match &self.root {
1236            Some(root) => root.count_range(prefix, 0, min_infix, max_infix),
1237            None => 0,
1238        }
1239    }
1240
1241    /// Returns true if the PATCH has a key with the given prefix.
1242    ///
1243    /// `PREFIX_LEN` must be less than or equal to `KEY_LEN` or a compile-time
1244    /// assertion will fail.
1245    pub fn has_prefix<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> bool {
1246        const {
1247            assert!(PREFIX_LEN <= KEY_LEN);
1248        }
1249        if let Some(root) = &self.root {
1250            root.has_prefix(0, prefix)
1251        } else {
1252            PREFIX_LEN == 0
1253        }
1254    }
1255
1256    /// Returns the number of unique segments in keys with the given prefix.
1257    pub fn segmented_len<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> u64 {
1258        const {
1259            assert!(PREFIX_LEN <= KEY_LEN);
1260            if PREFIX_LEN > 0 && PREFIX_LEN < KEY_LEN {
1261                assert!(
1262                    <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
1263                        [O::TREE_TO_KEY[PREFIX_LEN - 1]]
1264                        != <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
1265                            [O::TREE_TO_KEY[PREFIX_LEN]],
1266                    "PREFIX_LEN must align to segment boundary",
1267                );
1268            }
1269        }
1270        if let Some(root) = &self.root {
1271            root.segmented_len(0, prefix)
1272        } else {
1273            0
1274        }
1275    }
1276
1277    /// Iterates over all keys in the PATCH.
1278    /// The keys are returned in key ordering but random order.
1279    pub fn iter<'a>(&'a self) -> PATCHIterator<'a, KEY_LEN, O, V> {
1280        PATCHIterator::new(self)
1281    }
1282
1283    /// Iterates over all keys in the PATCH in key order.
1284    ///
1285    /// The traversal visits every key in lexicographic key order, without
1286    /// accepting a prefix filter. For prefix-aware iteration, see
1287    /// [`PATCH::iter_prefix_count`].
1288    pub fn iter_ordered<'a>(&'a self) -> PATCHOrderedIterator<'a, KEY_LEN, O, V> {
1289        PATCHOrderedIterator::new(self)
1290    }
1291
1292    /// Iterate over all prefixes of the given length in the PATCH.
1293    /// The prefixes are naturally returned in tree ordering and tree order.
1294    /// A count of the number of elements for the given prefix is also returned.
1295    pub fn iter_prefix_count<'a, const PREFIX_LEN: usize>(
1296        &'a self,
1297    ) -> PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V> {
1298        PATCHPrefixIterator::new(self)
1299    }
1300
1301    /// Unions this PATCH with another PATCH.
1302    ///
1303    /// The other PATCH is consumed, and this PATCH is updated in place.
1304    pub fn union(&mut self, other: Self) {
1305        if let Some(other) = other.root {
1306            if self.root.is_some() {
1307                let this = self.root.take().expect("root should not be empty");
1308                let merged = Head::union(this, other, 0);
1309                self.root.replace(merged);
1310            } else {
1311                self.root.replace(other);
1312            }
1313        }
1314    }
1315
1316    /// Intersects this PATCH with another PATCH.
1317    ///
1318    /// Returns a new PATCH that contains only the keys that are present in both PATCHes.
1319    pub fn intersect(&self, other: &Self) -> Self {
1320        if let Some(root) = &self.root {
1321            if let Some(other_root) = &other.root {
1322                return Self {
1323                    root: root.intersect(other_root, 0).map(|root| root.with_start(0)),
1324                };
1325            }
1326        }
1327        Self::new()
1328    }
1329
1330    /// Returns the difference between this PATCH and another PATCH.
1331    ///
1332    /// Returns a new PATCH that contains only the keys that are present in this PATCH,
1333    /// but not in the other PATCH.
1334    pub fn difference(&self, other: &Self) -> Self {
1335        if let Some(root) = &self.root {
1336            if let Some(other_root) = &other.root {
1337                Self {
1338                    root: root.difference(other_root, 0),
1339                }
1340            } else {
1341                (*self).clone()
1342            }
1343        } else {
1344            Self::new()
1345        }
1346    }
1347
1348    /// Calculates the average fill level for branch nodes grouped by their
1349    /// branching factor. The returned array contains eight entries for branch
1350    /// sizes `2`, `4`, `8`, `16`, `32`, `64`, `128` and `256` in that order.
1351    //#[cfg(debug_assertions)]
1352    pub fn debug_branch_fill(&self) -> [f32; 8] {
1353        let mut counts = [0u64; 8];
1354        let mut used = [0u64; 8];
1355
1356        if let Some(root) = &self.root {
1357            let mut stack = Vec::new();
1358            stack.push(root);
1359
1360            while let Some(head) = stack.pop() {
1361                match head.body_ref() {
1362                    BodyRef::Leaf(_) => {}
1363                    BodyRef::Branch(b) => {
1364                        let size = b.child_table.len();
1365                        let idx = size.trailing_zeros() as usize - 1;
1366                        counts[idx] += 1;
1367                        used[idx] += b.child_table.iter().filter(|c| c.is_some()).count() as u64;
1368                        for child in b.child_table.iter().filter_map(|c| c.as_ref()) {
1369                            stack.push(child);
1370                        }
1371                    }
1372                }
1373            }
1374        }
1375
1376        let mut avg = [0f32; 8];
1377        for i in 0..8 {
1378            if counts[i] > 0 {
1379                let size = 1u64 << (i + 1);
1380                avg[i] = used[i] as f32 / (counts[i] as f32 * size as f32);
1381            }
1382        }
1383        avg
1384    }
1385}
1386
1387impl<const KEY_LEN: usize, O, V> PartialEq for PATCH<KEY_LEN, O, V>
1388where
1389    O: KeySchema<KEY_LEN>,
1390{
1391    fn eq(&self, other: &Self) -> bool {
1392        self.root.as_ref().map(|root| root.hash()) == other.root.as_ref().map(|root| root.hash())
1393    }
1394}
1395
1396impl<const KEY_LEN: usize, O, V> Eq for PATCH<KEY_LEN, O, V> where O: KeySchema<KEY_LEN> {}
1397
1398impl<'a, const KEY_LEN: usize, O, V> IntoIterator for &'a PATCH<KEY_LEN, O, V>
1399where
1400    O: KeySchema<KEY_LEN>,
1401{
1402    type Item = &'a [u8; KEY_LEN];
1403    type IntoIter = PATCHIterator<'a, KEY_LEN, O, V>;
1404
1405    fn into_iter(self) -> Self::IntoIter {
1406        PATCHIterator::new(self)
1407    }
1408}
1409
1410/// An iterator over all keys in a PATCH.
1411/// The keys are returned in key ordering but in random order.
1412pub struct PATCHIterator<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1413    stack: ArrayVec<std::slice::Iter<'a, Option<Head<KEY_LEN, O, V>>>, KEY_LEN>,
1414    remaining: usize,
1415}
1416
1417impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHIterator<'a, KEY_LEN, O, V> {
1418    /// Creates an iterator over all keys in `patch`.
1419    pub fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
1420        let mut r = PATCHIterator {
1421            stack: ArrayVec::new(),
1422            remaining: patch.len().min(usize::MAX as u64) as usize,
1423        };
1424        r.stack.push(std::slice::from_ref(&patch.root).iter());
1425        r
1426    }
1427}
1428
1429impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1430    for PATCHIterator<'a, KEY_LEN, O, V>
1431{
1432    type Item = &'a [u8; KEY_LEN];
1433
1434    fn next(&mut self) -> Option<Self::Item> {
1435        let mut iter = self.stack.last_mut()?;
1436        loop {
1437            if let Some(child) = iter.next() {
1438                if let Some(child) = child {
1439                    match child.body_ref() {
1440                        BodyRef::Leaf(_) => {
1441                            self.remaining = self.remaining.saturating_sub(1);
1442                            // Use the safe accessor on the child reference to obtain the leaf key bytes.
1443                            return Some(child.childleaf_key());
1444                        }
1445                        BodyRef::Branch(branch) => {
1446                            self.stack.push(branch.child_table.iter());
1447                            iter = self.stack.last_mut()?;
1448                        }
1449                    }
1450                }
1451            } else {
1452                self.stack.pop();
1453                iter = self.stack.last_mut()?;
1454            }
1455        }
1456    }
1457
1458    fn size_hint(&self) -> (usize, Option<usize>) {
1459        (self.remaining, Some(self.remaining))
1460    }
1461}
1462
1463impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ExactSizeIterator
1464    for PATCHIterator<'a, KEY_LEN, O, V>
1465{
1466}
1467
1468impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> std::iter::FusedIterator
1469    for PATCHIterator<'a, KEY_LEN, O, V>
1470{
1471}
1472
1473/// An iterator over every key in a PATCH, returned in key order.
1474///
1475/// Keys are yielded in lexicographic key order regardless of their physical
1476/// layout in the underlying tree. This iterator walks the full tree and does
1477/// not accept a prefix filter. For prefix-aware iteration, use
1478/// [`PATCHPrefixIterator`], constructed via [`PATCH::iter_prefix_count`].
1479pub struct PATCHOrderedIterator<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1480    stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V>, 256>>,
1481    remaining: usize,
1482}
1483
1484impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHOrderedIterator<'a, KEY_LEN, O, V> {
1485    pub fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
1486        let mut r = PATCHOrderedIterator {
1487            stack: Vec::with_capacity(KEY_LEN),
1488            remaining: patch.len().min(usize::MAX as u64) as usize,
1489        };
1490        if let Some(root) = &patch.root {
1491            r.stack.push(ArrayVec::new());
1492            match root.body_ref() {
1493                BodyRef::Leaf(_) => {
1494                    r.stack[0].push(root);
1495                }
1496                BodyRef::Branch(branch) => {
1497                    let first_level = &mut r.stack[0];
1498                    first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1499                    first_level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1500                }
1501            }
1502        }
1503        r
1504    }
1505}
1506
1507// --- Owned consuming iterators ---
1508/// Iterator that owns a PATCH and yields keys in key-order. The iterator
1509/// consumes the PATCH and stores it on the heap (Box) so it can safely hold
1510/// raw pointers into the patch memory while the iterator is moved.
1511pub struct PATCHIntoIterator<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1512    queue: Vec<Head<KEY_LEN, O, V>>,
1513    remaining: usize,
1514}
1515
1516impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHIntoIterator<KEY_LEN, O, V> {}
1517
1518impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator for PATCHIntoIterator<KEY_LEN, O, V> {
1519    type Item = [u8; KEY_LEN];
1520
1521    fn next(&mut self) -> Option<Self::Item> {
1522        let q = &mut self.queue;
1523        while let Some(mut head) = q.pop() {
1524            // Match on the mutable body directly. For leaves we can return the
1525            // stored key (the array is Copy), for branches we take children out
1526            // of the table and push them onto the stack so they are visited
1527            // depth-first.
1528            match head.body_mut() {
1529                BodyMut::Leaf(leaf) => {
1530                    self.remaining = self.remaining.saturating_sub(1);
1531                    return Some(leaf.key);
1532                }
1533                BodyMut::Branch(branch) => {
1534                    for slot in branch.child_table.iter_mut().rev() {
1535                        if let Some(c) = slot.take() {
1536                            q.push(c);
1537                        }
1538                    }
1539                }
1540            }
1541        }
1542        None
1543    }
1544}
1545
1546/// Iterator that owns a PATCH and yields keys in key order.
1547pub struct PATCHIntoOrderedIterator<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1548    queue: Vec<Head<KEY_LEN, O, V>>,
1549    remaining: usize,
1550}
1551
1552impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1553    for PATCHIntoOrderedIterator<KEY_LEN, O, V>
1554{
1555    type Item = [u8; KEY_LEN];
1556
1557    fn next(&mut self) -> Option<Self::Item> {
1558        let q = &mut self.queue;
1559        while let Some(mut head) = q.pop() {
1560            // Match the mutable body directly — we own `head` so calling
1561            // `body_mut()` is safe and allows returning the copied leaf key
1562            // or mutating the branch child table in-place.
1563            match head.body_mut() {
1564                BodyMut::Leaf(leaf) => {
1565                    self.remaining = self.remaining.saturating_sub(1);
1566                    return Some(leaf.key);
1567                }
1568                BodyMut::Branch(branch) => {
1569                    let slice: &mut [Option<Head<KEY_LEN, O, V>>] = &mut branch.child_table;
1570                    // Sort children by their byte-key, placing empty slots (None)
1571                    // after all occupied slots. Using `sort_unstable_by_key` with
1572                    // a simple key projection is clearer than a custom
1573                    // comparator; it also avoids allocating temporaries. The
1574                    // old comparator manually handled None/Some cases — we
1575                    // express that intent directly by sorting on the tuple
1576                    // (is_none, key_opt).
1577                    slice
1578                        .sort_unstable_by_key(|opt| (opt.is_none(), opt.as_ref().map(|h| h.key())));
1579                    for slot in slice.iter_mut().rev() {
1580                        if let Some(c) = slot.take() {
1581                            q.push(c);
1582                        }
1583                    }
1584                }
1585            }
1586        }
1587        None
1588    }
1589}
1590
1591impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> IntoIterator for PATCH<KEY_LEN, O, V> {
1592    type Item = [u8; KEY_LEN];
1593    type IntoIter = PATCHIntoIterator<KEY_LEN, O, V>;
1594
1595    fn into_iter(self) -> Self::IntoIter {
1596        let remaining = self.len().min(usize::MAX as u64) as usize;
1597        let mut q = Vec::new();
1598        if let Some(root) = self.root {
1599            q.push(root);
1600        }
1601        PATCHIntoIterator {
1602            queue: q,
1603            remaining,
1604        }
1605    }
1606}
1607
1608impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCH<KEY_LEN, O, V> {
1609    /// Consume and return an iterator that yields keys in key order.
1610    pub fn into_iter_ordered(self) -> PATCHIntoOrderedIterator<KEY_LEN, O, V> {
1611        let remaining = self.len().min(usize::MAX as u64) as usize;
1612        let mut q = Vec::new();
1613        if let Some(root) = self.root {
1614            q.push(root);
1615        }
1616        PATCHIntoOrderedIterator {
1617            queue: q,
1618            remaining,
1619        }
1620    }
1621}
1622
1623impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1624    for PATCHOrderedIterator<'a, KEY_LEN, O, V>
1625{
1626    type Item = &'a [u8; KEY_LEN];
1627
1628    fn next(&mut self) -> Option<Self::Item> {
1629        let mut level = self.stack.last_mut()?;
1630        loop {
1631            if let Some(child) = level.pop() {
1632                match child.body_ref() {
1633                    BodyRef::Leaf(_) => {
1634                        self.remaining = self.remaining.saturating_sub(1);
1635                        return Some(child.childleaf_key());
1636                    }
1637                    BodyRef::Branch(branch) => {
1638                        self.stack.push(ArrayVec::new());
1639                        level = self.stack.last_mut()?;
1640                        level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1641                        level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1642                    }
1643                }
1644            } else {
1645                self.stack.pop();
1646                level = self.stack.last_mut()?;
1647            }
1648        }
1649    }
1650
1651    fn size_hint(&self) -> (usize, Option<usize>) {
1652        (self.remaining, Some(self.remaining))
1653    }
1654}
1655
1656impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ExactSizeIterator
1657    for PATCHOrderedIterator<'a, KEY_LEN, O, V>
1658{
1659}
1660
1661impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> std::iter::FusedIterator
1662    for PATCHOrderedIterator<'a, KEY_LEN, O, V>
1663{
1664}
1665
1666/// An iterator over all keys in a PATCH that have a given prefix.
1667/// The keys are returned in tree ordering and in tree order.
1668pub struct PATCHPrefixIterator<
1669    'a,
1670    const KEY_LEN: usize,
1671    const PREFIX_LEN: usize,
1672    O: KeySchema<KEY_LEN>,
1673    V,
1674> {
1675    stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V>, 256>>,
1676}
1677
1678impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V>
1679    PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V>
1680{
1681    fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
1682        const {
1683            assert!(PREFIX_LEN <= KEY_LEN);
1684        }
1685        let mut r = PATCHPrefixIterator {
1686            stack: Vec::with_capacity(PREFIX_LEN),
1687        };
1688        if let Some(root) = &patch.root {
1689            r.stack.push(ArrayVec::new());
1690            if root.end_depth() >= PREFIX_LEN {
1691                r.stack[0].push(root);
1692            } else {
1693                let BodyRef::Branch(branch) = root.body_ref() else {
1694                    unreachable!();
1695                };
1696                let first_level = &mut r.stack[0];
1697                first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1698                first_level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1699            }
1700        }
1701        r
1702    }
1703}
1704
1705impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1706    for PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V>
1707{
1708    type Item = ([u8; PREFIX_LEN], u64);
1709
1710    fn next(&mut self) -> Option<Self::Item> {
1711        let mut level = self.stack.last_mut()?;
1712        loop {
1713            if let Some(child) = level.pop() {
1714                if child.end_depth() >= PREFIX_LEN {
1715                    let key = O::tree_ordered(child.childleaf_key());
1716                    let suffix_count = child.count();
1717                    return Some((key[0..PREFIX_LEN].try_into().unwrap(), suffix_count));
1718                } else {
1719                    let BodyRef::Branch(branch) = child.body_ref() else {
1720                        unreachable!();
1721                    };
1722                    self.stack.push(ArrayVec::new());
1723                    level = self.stack.last_mut()?;
1724                    level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1725                    level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1726                }
1727            } else {
1728                self.stack.pop();
1729                level = self.stack.last_mut()?;
1730            }
1731        }
1732    }
1733}
1734
1735#[cfg(test)]
1736mod tests {
1737    use super::*;
1738    use itertools::Itertools;
1739    use proptest::prelude::*;
1740    use std::collections::HashSet;
1741    use std::convert::TryInto;
1742    use std::iter::FromIterator;
1743    use std::mem;
1744
1745    #[test]
1746    fn head_tag() {
1747        let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(0, NonNull::dangling());
1748        assert_eq!(head.tag(), HeadTag::Leaf);
1749        mem::forget(head);
1750    }
1751
1752    #[test]
1753    fn head_key() {
1754        for k in 0..=255 {
1755            let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(k, NonNull::dangling());
1756            assert_eq!(head.key(), k);
1757            mem::forget(head);
1758        }
1759    }
1760
1761    #[test]
1762    fn head_size() {
1763        assert_eq!(mem::size_of::<Head<64, IdentitySchema, ()>>(), 8);
1764    }
1765
1766    #[test]
1767    fn option_head_size() {
1768        assert_eq!(mem::size_of::<Option<Head<64, IdentitySchema, ()>>>(), 8);
1769    }
1770
1771    #[test]
1772    fn empty_tree() {
1773        let _tree = PATCH::<64, IdentitySchema, ()>::new();
1774    }
1775
1776    #[test]
1777    fn tree_put_one() {
1778        const KEY_SIZE: usize = 64;
1779        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1780        let entry = Entry::new(&[0; KEY_SIZE]);
1781        tree.insert(&entry);
1782    }
1783
1784    #[test]
1785    fn tree_clone_one() {
1786        const KEY_SIZE: usize = 64;
1787        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1788        let entry = Entry::new(&[0; KEY_SIZE]);
1789        tree.insert(&entry);
1790        let _clone = tree.clone();
1791    }
1792
1793    #[test]
1794    fn tree_put_same() {
1795        const KEY_SIZE: usize = 64;
1796        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1797        let entry = Entry::new(&[0; KEY_SIZE]);
1798        tree.insert(&entry);
1799        tree.insert(&entry);
1800    }
1801
1802    #[test]
1803    fn tree_replace_existing() {
1804        const KEY_SIZE: usize = 64;
1805        let key = [1u8; KEY_SIZE];
1806        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1807        let entry1 = Entry::with_value(&key, 1);
1808        tree.insert(&entry1);
1809        let entry2 = Entry::with_value(&key, 2);
1810        tree.replace(&entry2);
1811        assert_eq!(tree.get(&key), Some(&2));
1812    }
1813
1814    #[test]
1815    fn tree_replace_childleaf_updates_branch() {
1816        const KEY_SIZE: usize = 64;
1817        let key1 = [0u8; KEY_SIZE];
1818        let key2 = [1u8; KEY_SIZE];
1819        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1820        let entry1 = Entry::with_value(&key1, 1);
1821        let entry2 = Entry::with_value(&key2, 2);
1822        tree.insert(&entry1);
1823        tree.insert(&entry2);
1824        let entry1b = Entry::with_value(&key1, 3);
1825        tree.replace(&entry1b);
1826        assert_eq!(tree.get(&key1), Some(&3));
1827        assert_eq!(tree.get(&key2), Some(&2));
1828    }
1829
1830    #[test]
1831    fn update_child_refreshes_childleaf_on_replace() {
1832        const KEY_SIZE: usize = 4;
1833        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1834
1835        let key1 = [0u8; KEY_SIZE];
1836        let key2 = [1u8; KEY_SIZE];
1837        tree.insert(&Entry::with_value(&key1, 1));
1838        tree.insert(&Entry::with_value(&key2, 2));
1839
1840        // Determine which child currently provides the branch childleaf.
1841        let root_ref = tree.root.as_ref().expect("root exists");
1842        let before_childleaf = *root_ref.childleaf_key();
1843
1844        // Find the slot key (the byte index used in the branch table) for the child
1845        // that currently provides the childleaf.
1846        let slot_key = match root_ref.body_ref() {
1847            BodyRef::Branch(branch) => branch
1848                .child_table
1849                .iter()
1850                .filter_map(|c| c.as_ref())
1851                .find(|c| c.childleaf_key() == &before_childleaf)
1852                .expect("child exists")
1853                .key(),
1854            BodyRef::Leaf(_) => panic!("root should be a branch"),
1855        };
1856
1857        // Replace that child with a new leaf that has a different childleaf key.
1858        let new_key = [2u8; KEY_SIZE];
1859        {
1860            let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
1861            ed.modify_child(slot_key, |_| {
1862                Some(Entry::with_value(&new_key, 42).leaf::<IdentitySchema>())
1863            });
1864            // drop(ed) commits
1865        }
1866
1867        let after = tree.root.as_ref().expect("root exists");
1868        assert_eq!(after.childleaf_key(), &new_key);
1869    }
1870
1871    #[test]
1872    fn remove_childleaf_updates_branch() {
1873        const KEY_SIZE: usize = 4;
1874        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1875
1876        let key1 = [0u8; KEY_SIZE];
1877        let key2 = [1u8; KEY_SIZE];
1878        tree.insert(&Entry::with_value(&key1, 1));
1879        tree.insert(&Entry::with_value(&key2, 2));
1880
1881        let childleaf_before = *tree.root.as_ref().unwrap().childleaf_key();
1882        // remove the leaf that currently provides the branch.childleaf
1883        tree.remove(&childleaf_before);
1884
1885        // Ensure the removed key is gone and the other key remains and is now the childleaf.
1886        let other = if childleaf_before == key1 { key2 } else { key1 };
1887        assert_eq!(tree.get(&childleaf_before), None);
1888        assert_eq!(tree.get(&other), Some(&2u32));
1889        let after_childleaf = tree.root.as_ref().unwrap().childleaf_key();
1890        assert_eq!(after_childleaf, &other);
1891    }
1892
1893    #[test]
1894    fn remove_collapses_branch_to_single_child() {
1895        const KEY_SIZE: usize = 4;
1896        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1897
1898        let key1 = [0u8; KEY_SIZE];
1899        let key2 = [1u8; KEY_SIZE];
1900        tree.insert(&Entry::with_value(&key1, 1));
1901        tree.insert(&Entry::with_value(&key2, 2));
1902
1903        // Remove one key and ensure the root collapses to the remaining child.
1904        tree.remove(&key1);
1905        assert_eq!(tree.get(&key1), None);
1906        assert_eq!(tree.get(&key2), Some(&2u32));
1907        let root = tree.root.as_ref().expect("root exists");
1908        match root.body_ref() {
1909            BodyRef::Leaf(_) => {}
1910            BodyRef::Branch(_) => panic!("root should have collapsed to a leaf"),
1911        }
1912    }
1913
1914    #[test]
1915    fn branch_size() {
1916        assert_eq!(
1917            mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 2], ()>>(
1918            ),
1919            64
1920        );
1921        assert_eq!(
1922            mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 4], ()>>(
1923            ),
1924            48 + 16 * 2
1925        );
1926        assert_eq!(
1927            mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 8], ()>>(
1928            ),
1929            48 + 16 * 4
1930        );
1931        assert_eq!(
1932            mem::size_of::<
1933                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 16], ()>,
1934            >(),
1935            48 + 16 * 8
1936        );
1937        assert_eq!(
1938            mem::size_of::<
1939                Branch<64, IdentitySchema, [Option<Head<32, IdentitySchema, ()>>; 32], ()>,
1940            >(),
1941            48 + 16 * 16
1942        );
1943        assert_eq!(
1944            mem::size_of::<
1945                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 64], ()>,
1946            >(),
1947            48 + 16 * 32
1948        );
1949        assert_eq!(
1950            mem::size_of::<
1951                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 128], ()>,
1952            >(),
1953            48 + 16 * 64
1954        );
1955        assert_eq!(
1956            mem::size_of::<
1957                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 256], ()>,
1958            >(),
1959            48 + 16 * 128
1960        );
1961    }
1962
1963    /// Checks what happens if we join two PATCHes that
1964    /// only contain a single element each, that differs in the last byte.
1965    #[test]
1966    fn tree_union_single() {
1967        const KEY_SIZE: usize = 8;
1968        let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1969        let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1970        let left_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 0]);
1971        let right_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 1]);
1972        left.insert(&left_entry);
1973        right.insert(&right_entry);
1974        left.union(right);
1975        assert_eq!(left.len(), 2);
1976    }
1977
1978    // Small unit tests that ensure BranchMut-based editing is used by
1979    // the higher-level set operations like intersect/difference. These are
1980    // ordinary unit tests (not proptest) and must appear outside the
1981    // `proptest!` macro below.
1982
1983    proptest! {
1984        #[test]
1985        fn tree_insert(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
1986            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
1987            for key in keys {
1988                let key: [u8; 64] = key.try_into().unwrap();
1989                let entry = Entry::new(&key);
1990                tree.insert(&entry);
1991            }
1992        }
1993
1994        #[test]
1995        fn tree_len(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
1996            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
1997            let mut set = HashSet::new();
1998            for key in keys {
1999                let key: [u8; 64] = key.try_into().unwrap();
2000                let entry = Entry::new(&key);
2001                tree.insert(&entry);
2002                set.insert(key);
2003            }
2004
2005            prop_assert_eq!(set.len() as u64, tree.len())
2006        }
2007
2008        #[test]
2009        fn tree_infixes(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
2010            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
2011            let mut set = HashSet::new();
2012            for key in keys {
2013                let key: [u8; 64] = key.try_into().unwrap();
2014                let entry = Entry::new(&key);
2015                tree.insert(&entry);
2016                set.insert(key);
2017            }
2018            let mut set_vec = Vec::from_iter(set.into_iter());
2019            let mut tree_vec = vec![];
2020            tree.infixes(&[0; 0], &mut |&x: &[u8; 64]| tree_vec.push(x));
2021
2022            set_vec.sort();
2023            tree_vec.sort();
2024
2025            prop_assert_eq!(set_vec, tree_vec);
2026        }
2027
2028        #[test]
2029        fn tree_iter(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
2030            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
2031            let mut set = HashSet::new();
2032            for key in keys {
2033                let key: [u8; 64] = key.try_into().unwrap();
2034                let entry = Entry::new(&key);
2035                tree.insert(&entry);
2036                set.insert(key);
2037            }
2038            let mut set_vec = Vec::from_iter(set.into_iter());
2039            let mut tree_vec = vec![];
2040            for key in &tree {
2041                tree_vec.push(*key);
2042            }
2043
2044            set_vec.sort();
2045            tree_vec.sort();
2046
2047            prop_assert_eq!(set_vec, tree_vec);
2048        }
2049
2050        #[test]
2051        fn tree_union(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200),
2052                        right in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200)) {
2053            let mut set = HashSet::new();
2054
2055            let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
2056            for entry in left {
2057                let mut key = [0; 64];
2058                key.iter_mut().set_from(entry.iter().cloned());
2059                let entry = Entry::new(&key);
2060                left_tree.insert(&entry);
2061                set.insert(key);
2062            }
2063
2064            let mut right_tree = PATCH::<64, IdentitySchema, ()>::new();
2065            for entry in right {
2066                let mut key = [0; 64];
2067                key.iter_mut().set_from(entry.iter().cloned());
2068                let entry = Entry::new(&key);
2069                right_tree.insert(&entry);
2070                set.insert(key);
2071            }
2072
2073            left_tree.union(right_tree);
2074
2075            let mut set_vec = Vec::from_iter(set.into_iter());
2076            let mut tree_vec = vec![];
2077            left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
2078
2079            set_vec.sort();
2080            tree_vec.sort();
2081
2082            prop_assert_eq!(set_vec, tree_vec);
2083            }
2084
2085        #[test]
2086        fn tree_union_empty(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 2)) {
2087            let mut set = HashSet::new();
2088
2089            let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
2090            for entry in left {
2091                let mut key = [0; 64];
2092                key.iter_mut().set_from(entry.iter().cloned());
2093                let entry = Entry::new(&key);
2094                left_tree.insert(&entry);
2095                set.insert(key);
2096            }
2097
2098            let right_tree = PATCH::<64, IdentitySchema, ()>::new();
2099
2100            left_tree.union(right_tree);
2101
2102            let mut set_vec = Vec::from_iter(set.into_iter());
2103            let mut tree_vec = vec![];
2104            left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
2105
2106            set_vec.sort();
2107            tree_vec.sort();
2108
2109            prop_assert_eq!(set_vec, tree_vec);
2110            }
2111
2112        // I got a feeling that we're not testing COW properly.
2113        // We should check if a tree remains the same after a clone of it
2114        // is modified by inserting new keys.
2115
2116    #[test]
2117    fn cow_on_insert(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
2118                         new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
2119            // Note that we can't compare the trees directly, as that uses the hash,
2120            // which might not be affected by nodes in lower levels being changed accidentally.
2121            // Instead we need to iterate over the keys and check if they are the same.
2122
2123            let mut tree = PATCH::<8, IdentitySchema, ()>::new();
2124            for key in base_keys {
2125                let key: [u8; 8] = key[..].try_into().unwrap();
2126                let entry = Entry::new(&key);
2127                tree.insert(&entry);
2128            }
2129            let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2130
2131            let mut tree_clone = tree.clone();
2132            for key in new_keys {
2133                let key: [u8; 8] = key[..].try_into().unwrap();
2134                let entry = Entry::new(&key);
2135                tree_clone.insert(&entry);
2136            }
2137
2138            let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2139            prop_assert_eq!(base_tree_content, new_tree_content);
2140        }
2141
2142        #[test]
2143    fn cow_on_union(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
2144                         new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
2145            // Note that we can't compare the trees directly, as that uses the hash,
2146            // which might not be affected by nodes in lower levels being changed accidentally.
2147            // Instead we need to iterate over the keys and check if they are the same.
2148
2149            let mut tree = PATCH::<8, IdentitySchema, ()>::new();
2150            for key in base_keys {
2151                let key: [u8; 8] = key[..].try_into().unwrap();
2152                let entry = Entry::new(&key);
2153                tree.insert(&entry);
2154            }
2155            let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2156
2157            let mut tree_clone = tree.clone();
2158            let mut new_tree = PATCH::<8, IdentitySchema, ()>::new();
2159            for key in new_keys {
2160                let key: [u8; 8] = key[..].try_into().unwrap();
2161                let entry = Entry::new(&key);
2162                new_tree.insert(&entry);
2163            }
2164            tree_clone.union(new_tree);
2165
2166            let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2167            prop_assert_eq!(base_tree_content, new_tree_content);
2168        }
2169    }
2170
2171    #[test]
2172    fn intersect_multiple_common_children_commits_branchmut() {
2173        const KEY_SIZE: usize = 4;
2174        let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2175        let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2176
2177        let a = [0u8, 0u8, 0u8, 1u8];
2178        let b = [0u8, 0u8, 0u8, 2u8];
2179        let c = [0u8, 0u8, 0u8, 3u8];
2180        let d = [2u8, 0u8, 0u8, 0u8];
2181        let e = [3u8, 0u8, 0u8, 0u8];
2182
2183        left.insert(&Entry::with_value(&a, 1));
2184        left.insert(&Entry::with_value(&b, 2));
2185        left.insert(&Entry::with_value(&c, 3));
2186        left.insert(&Entry::with_value(&d, 4));
2187
2188        right.insert(&Entry::with_value(&a, 10));
2189        right.insert(&Entry::with_value(&b, 11));
2190        right.insert(&Entry::with_value(&c, 12));
2191        right.insert(&Entry::with_value(&e, 13));
2192
2193        let res = left.intersect(&right);
2194        // A, B, C are common
2195        assert_eq!(res.len(), 3);
2196        assert!(res.get(&a).is_some());
2197        assert!(res.get(&b).is_some());
2198        assert!(res.get(&c).is_some());
2199    }
2200
2201    #[test]
2202    fn difference_multiple_children_commits_branchmut() {
2203        const KEY_SIZE: usize = 4;
2204        let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2205        let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2206
2207        let a = [0u8, 0u8, 0u8, 1u8];
2208        let b = [0u8, 0u8, 0u8, 2u8];
2209        let c = [0u8, 0u8, 0u8, 3u8];
2210        let d = [2u8, 0u8, 0u8, 0u8];
2211        let e = [3u8, 0u8, 0u8, 0u8];
2212
2213        left.insert(&Entry::with_value(&a, 1));
2214        left.insert(&Entry::with_value(&b, 2));
2215        left.insert(&Entry::with_value(&c, 3));
2216        left.insert(&Entry::with_value(&d, 4));
2217
2218        right.insert(&Entry::with_value(&a, 10));
2219        right.insert(&Entry::with_value(&b, 11));
2220        right.insert(&Entry::with_value(&c, 12));
2221        right.insert(&Entry::with_value(&e, 13));
2222
2223        let res = left.difference(&right);
2224        // left only has d
2225        assert_eq!(res.len(), 1);
2226        assert!(res.get(&d).is_some());
2227    }
2228
2229    #[test]
2230    fn difference_empty_left_is_empty() {
2231        const KEY_SIZE: usize = 4;
2232        let left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2233        let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2234        let key = [1u8, 2u8, 3u8, 4u8];
2235        right.insert(&Entry::with_value(&key, 7));
2236
2237        let res = left.difference(&right);
2238        assert_eq!(res.len(), 0);
2239    }
2240
2241    #[test]
2242    fn difference_empty_right_returns_left() {
2243        const KEY_SIZE: usize = 4;
2244        let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2245        let right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2246        let key = [1u8, 2u8, 3u8, 4u8];
2247        left.insert(&Entry::with_value(&key, 7));
2248
2249        let res = left.difference(&right);
2250        assert_eq!(res.len(), 1);
2251        assert!(res.get(&key).is_some());
2252    }
2253
2254    #[test]
2255    fn slot_edit_branchmut_insert_update() {
2256        // Small unit test demonstrating the Slot::edit -> BranchMut insert/update pattern.
2257        const KEY_SIZE: usize = 8;
2258        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2259
2260        let entry1 = Entry::with_value(&[0u8; KEY_SIZE], 1u32);
2261        let entry2 = Entry::with_value(&[1u8; KEY_SIZE], 2u32);
2262        tree.insert(&entry1);
2263        tree.insert(&entry2);
2264        assert_eq!(tree.len(), 2);
2265
2266        // Edit the root slot in-place using the BranchMut editor.
2267        {
2268            let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
2269
2270            // Compute the insertion start depth first to avoid borrowing `ed` inside the closure.
2271            let start_depth = ed.end_depth as usize;
2272            let inserted = Entry::with_value(&[2u8; KEY_SIZE], 3u32)
2273                .leaf::<IdentitySchema>()
2274                .with_start(start_depth);
2275            let key = inserted.key();
2276
2277            ed.modify_child(key, |opt| match opt {
2278                Some(old) => Some(Head::insert_leaf(old, inserted, start_depth)),
2279                None => Some(inserted),
2280            });
2281            // BranchMut is dropped here and commits the updated branch pointer back into the head.
2282        }
2283
2284        assert_eq!(tree.len(), 3);
2285        assert_eq!(tree.get(&[2u8; KEY_SIZE]), Some(&3u32));
2286    }
2287}