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>(prefix, at_depth, min_infix, max_infix, f),
763            BodyRef::Branch(branch) => {
764                branch.infixes_range::<PREFIX_LEN, INFIX_LEN, F>(prefix, at_depth, min_infix, max_infix, f)
765            }
766        }
767    }
768
769    pub(crate) fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
770        &self,
771        prefix: &[u8; PREFIX_LEN],
772        at_depth: usize,
773        min_infix: &[u8; INFIX_LEN],
774        max_infix: &[u8; INFIX_LEN],
775    ) -> u64 {
776        match self.body_ref() {
777            BodyRef::Leaf(leaf) => leaf.count_range::<PREFIX_LEN, INFIX_LEN, O>(prefix, at_depth, min_infix, max_infix),
778            BodyRef::Branch(branch) => branch.count_range::<PREFIX_LEN, INFIX_LEN>(prefix, at_depth, min_infix, max_infix),
779        }
780    }
781
782    pub(crate) fn has_prefix<const PREFIX_LEN: usize>(
783        &self,
784        at_depth: usize,
785        prefix: &[u8; PREFIX_LEN],
786    ) -> bool {
787        const {
788            assert!(PREFIX_LEN <= KEY_LEN);
789        }
790        match self.body_ref() {
791            BodyRef::Leaf(leaf) => leaf.has_prefix::<O>(at_depth, prefix),
792            BodyRef::Branch(branch) => branch.has_prefix::<PREFIX_LEN>(at_depth, prefix),
793        }
794    }
795
796    pub(crate) fn get<'a>(&'a self, at_depth: usize, key: &[u8; KEY_LEN]) -> Option<&'a V>
797    where
798        O: 'a,
799    {
800        match self.body_ref() {
801            BodyRef::Leaf(leaf) => leaf.get::<O>(at_depth, key),
802            BodyRef::Branch(branch) => branch.get(at_depth, key),
803        }
804    }
805
806    pub(crate) fn segmented_len<const PREFIX_LEN: usize>(
807        &self,
808        at_depth: usize,
809        prefix: &[u8; PREFIX_LEN],
810    ) -> u64 {
811        match self.body_ref() {
812            BodyRef::Leaf(leaf) => leaf.segmented_len::<O, PREFIX_LEN>(at_depth, prefix),
813            BodyRef::Branch(branch) => branch.segmented_len::<PREFIX_LEN>(at_depth, prefix),
814        }
815    }
816
817    // NOTE: slot-level union wrapper removed; callers should take the slot and
818    // call the owned helper `union` directly.
819
820    pub(crate) fn intersect(&self, other: &Self, at_depth: usize) -> Option<Self> {
821        if self.hash() == other.hash() {
822            return Some(self.clone());
823        }
824
825        if self.first_divergence(other, at_depth).is_some() {
826            return None;
827        }
828
829        let self_depth = self.end_depth();
830        let other_depth = other.end_depth();
831        if self_depth < other_depth {
832            // This means that there can be at most one child in self
833            // that might intersect with other.
834            let BodyRef::Branch(branch) = self.body_ref() else {
835                unreachable!();
836            };
837            return branch
838                .child_table
839                .table_get(other.childleaf_key()[O::TREE_TO_KEY[self_depth]])
840                .and_then(|self_child| other.intersect(self_child, self_depth));
841        }
842
843        if other_depth < self_depth {
844            // This means that there can be at most one child in other
845            // that might intersect with self.
846            // If the depth of other is less than the depth of self, then it can't be a leaf.
847            let BodyRef::Branch(other_branch) = other.body_ref() else {
848                unreachable!();
849            };
850            return other_branch
851                .child_table
852                .table_get(self.childleaf_key()[O::TREE_TO_KEY[other_depth]])
853                .and_then(|other_child| self.intersect(other_child, other_depth));
854        }
855
856        // If we reached this point then the depths are equal. The only way to have a leaf
857        // is if the other is a leaf as well, which is already handled by the hash check if they are equal,
858        // and by the key check if they are not equal.
859        // If one of them is a leaf and the other is a branch, then they would also have different depths,
860        // which is already handled by the above code.
861        let BodyRef::Branch(self_branch) = self.body_ref() else {
862            unreachable!();
863        };
864        let BodyRef::Branch(other_branch) = other.body_ref() else {
865            unreachable!();
866        };
867
868        let mut intersected_children = self_branch
869            .child_table
870            .iter()
871            .filter_map(Option::as_ref)
872            .filter_map(|self_child| {
873                let other_child = other_branch.child_table.table_get(self_child.key())?;
874                self_child.intersect(other_child, self_depth)
875            });
876        let first_child = intersected_children.next()?;
877        let Some(second_child) = intersected_children.next() else {
878            return Some(first_child);
879        };
880        let new_branch = Branch::new(
881            self_depth,
882            first_child.with_start(self_depth),
883            second_child.with_start(self_depth),
884        );
885        // Use a BranchMut editor to perform all child insertions via the
886        // safe editor API instead of manipulating the NonNull pointer
887        // directly. The editor will perform COW and commit the final
888        // pointer into the Head when it is dropped.
889        let mut head_for_branch = Head::new(0, new_branch);
890        {
891            let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
892            for child in intersected_children {
893                let inserted = child.with_start(self_depth);
894                let k = inserted.key();
895                ed.modify_child(k, |_opt| Some(inserted));
896            }
897            // ed dropped here commits the final branch pointer into head_for_branch
898        }
899        Some(head_for_branch)
900    }
901
902    /// Returns the difference between self and other.
903    /// This is the set of elements that are in self but not in other.
904    /// If the difference is empty, None is returned.
905    pub(crate) fn difference(&self, other: &Self, at_depth: usize) -> Option<Self> {
906        if self.hash() == other.hash() {
907            return None;
908        }
909
910        if self.first_divergence(other, at_depth).is_some() {
911            return Some(self.clone());
912        }
913
914        let self_depth = self.end_depth();
915        let other_depth = other.end_depth();
916        if self_depth < other_depth {
917            // This means that there can be at most one child in self
918            // that might intersect with other. It's the only child that may not be in the difference.
919            // The other children are definitely in the difference, as they have no corresponding byte in other.
920            // Thus the cheapest way to compute the difference is compute the difference of the only child
921            // that might intersect with other, copy self with it's correctly filled byte table, then
922            // remove the old child, and insert the new child.
923            let mut new_branch = self.clone();
924            let other_byte_key = other.childleaf_key()[O::TREE_TO_KEY[self_depth]];
925            {
926                let mut ed = crate::patch::branch::BranchMut::from_head(&mut new_branch);
927                ed.modify_child(other_byte_key, |opt| {
928                    opt.and_then(|child| child.difference(other, self_depth))
929                });
930            }
931            return Some(new_branch);
932        }
933
934        if other_depth < self_depth {
935            // This means that we need to check if there is a child in other
936            // that matches the path at the current depth of self.
937            // There is no such child, then then self must be in the difference.
938            // If there is such a child, then we have to compute the difference
939            // between self and that child.
940            // We know that other must be a branch.
941            let BodyRef::Branch(other_branch) = other.body_ref() else {
942                unreachable!();
943            };
944            let self_byte_key = self.childleaf_key()[O::TREE_TO_KEY[other_depth]];
945            if let Some(other_child) = other_branch.child_table.table_get(self_byte_key) {
946                return self.difference(other_child, at_depth);
947            } else {
948                return Some(self.clone());
949            }
950        }
951
952        // If we reached this point then the depths are equal. The only way to have a leaf
953        // is if the other is a leaf as well, which is already handled by the hash check if they are equal,
954        // and by the key check if they are not equal.
955        // If one of them is a leaf and the other is a branch, then they would also have different depths,
956        // which is already handled by the above code.
957        let BodyRef::Branch(self_branch) = self.body_ref() else {
958            unreachable!();
959        };
960        let BodyRef::Branch(other_branch) = other.body_ref() else {
961            unreachable!();
962        };
963
964        let mut differenced_children = self_branch
965            .child_table
966            .iter()
967            .filter_map(Option::as_ref)
968            .filter_map(|self_child| {
969                if let Some(other_child) = other_branch.child_table.table_get(self_child.key()) {
970                    self_child.difference(other_child, self_depth)
971                } else {
972                    Some(self_child.clone())
973                }
974            });
975
976        let first_child = differenced_children.next()?;
977        let second_child = match differenced_children.next() {
978            Some(sc) => sc,
979            None => return Some(first_child),
980        };
981
982        let new_branch = Branch::new(
983            self_depth,
984            first_child.with_start(self_depth),
985            second_child.with_start(self_depth),
986        );
987        let mut head_for_branch = Head::new(0, new_branch);
988        {
989            let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
990            for child in differenced_children {
991                let inserted = child.with_start(self_depth);
992                let k = inserted.key();
993                ed.modify_child(k, |_opt| Some(inserted));
994            }
995            // ed dropped here commits the final branch pointer into head_for_branch
996        }
997        // The key will be set later, because we don't know it yet.
998        // The difference might remove multiple levels of branches,
999        // so we can't just take the key from self or other.
1000        Some(head_for_branch)
1001    }
1002}
1003
1004unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ByteEntry for Head<KEY_LEN, O, V> {
1005    fn key(&self) -> u8 {
1006        self.key()
1007    }
1008}
1009
1010impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> fmt::Debug for Head<KEY_LEN, O, V> {
1011    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1012        self.tag().fmt(f)
1013    }
1014}
1015
1016impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Clone for Head<KEY_LEN, O, V> {
1017    fn clone(&self) -> Self {
1018        unsafe {
1019            match self.body() {
1020                BodyPtr::Leaf(leaf) => Self::new(self.key(), Leaf::rc_inc(leaf)),
1021                BodyPtr::Branch(branch) => Self::new(self.key(), Branch::rc_inc(branch)),
1022            }
1023        }
1024    }
1025}
1026
1027// The Slot wrapper was removed in favor of using BranchMut::from_slot(&mut
1028// Option<Head<...>>) directly. This keeps the API surface smaller and
1029// avoids an extra helper type that simply forwarded to BranchMut.
1030
1031impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Drop for Head<KEY_LEN, O, V> {
1032    fn drop(&mut self) {
1033        unsafe {
1034            match self.body() {
1035                BodyPtr::Leaf(leaf) => Leaf::rc_dec(leaf),
1036                BodyPtr::Branch(branch) => Branch::rc_dec(branch),
1037            }
1038        }
1039    }
1040}
1041
1042/// A PATCH is a persistent data structure that stores a set of keys.
1043/// Each key can be reordered and segmented, based on the provided key ordering and segmentation.
1044///
1045/// The patch supports efficient set operations, like union, intersection, and difference,
1046/// because it efficiently maintains a hash for all keys that are part of a sub-tree.
1047///
1048/// The tree itself is a path- and node-compressed a 256-ary trie.
1049/// Each nodes stores its children in a byte oriented cuckoo hash table,
1050/// allowing for O(1) access to children, while keeping the memory overhead low.
1051/// Table sizes are powers of two, starting at 2.
1052///
1053/// Having a single node type for all branching factors simplifies the implementation,
1054/// compared to other adaptive trie implementations, like ARTs or Judy Arrays
1055///
1056/// The PATCH allows for cheap copy-on-write operations, with `clone` being O(1).
1057#[derive(Debug)]
1058pub struct PATCH<const KEY_LEN: usize, O = IdentitySchema, V = ()>
1059where
1060    O: KeySchema<KEY_LEN>,
1061{
1062    root: Option<Head<KEY_LEN, O, V>>,
1063}
1064
1065impl<const KEY_LEN: usize, O, V> Clone for PATCH<KEY_LEN, O, V>
1066where
1067    O: KeySchema<KEY_LEN>,
1068{
1069    fn clone(&self) -> Self {
1070        Self {
1071            root: self.root.clone(),
1072        }
1073    }
1074}
1075
1076impl<const KEY_LEN: usize, O, V> Default for PATCH<KEY_LEN, O, V>
1077where
1078    O: KeySchema<KEY_LEN>,
1079{
1080    fn default() -> Self {
1081        Self::new()
1082    }
1083}
1084
1085impl<const KEY_LEN: usize, O, V> PATCH<KEY_LEN, O, V>
1086where
1087    O: KeySchema<KEY_LEN>,
1088{
1089    /// Creates a new empty PATCH.
1090    pub fn new() -> Self {
1091        init_sip_key();
1092        PATCH { root: None }
1093    }
1094
1095    /// Inserts a shared key into the PATCH.
1096    ///
1097    /// Takes an [Entry] object that can be created from a key,
1098    /// and inserted into multiple PATCH instances.
1099    ///
1100    /// If the key is already present, this is a no-op.
1101    pub fn insert(&mut self, entry: &Entry<KEY_LEN, V>) {
1102        if self.root.is_some() {
1103            let this = self.root.take().expect("root should not be empty");
1104            let new_head = Head::insert_leaf(this, entry.leaf(), 0);
1105            self.root.replace(new_head);
1106        } else {
1107            self.root.replace(entry.leaf());
1108        }
1109    }
1110
1111    /// Inserts a key into the PATCH, replacing the value if it already exists.
1112    pub fn replace(&mut self, entry: &Entry<KEY_LEN, V>) {
1113        if self.root.is_some() {
1114            let this = self.root.take().expect("root should not be empty");
1115            let new_head = Head::replace_leaf(this, entry.leaf(), 0);
1116            self.root.replace(new_head);
1117        } else {
1118            self.root.replace(entry.leaf());
1119        }
1120    }
1121
1122    /// Removes a key from the PATCH.
1123    ///
1124    /// If the key is not present, this is a no-op.
1125    pub fn remove(&mut self, key: &[u8; KEY_LEN]) {
1126        Head::remove_leaf(&mut self.root, key, 0);
1127    }
1128
1129    /// Returns the number of keys in the PATCH.
1130    pub fn len(&self) -> u64 {
1131        if let Some(root) = &self.root {
1132            root.count()
1133        } else {
1134            0
1135        }
1136    }
1137
1138    /// Returns true if the PATCH contains no keys.
1139    pub fn is_empty(&self) -> bool {
1140        self.len() == 0
1141    }
1142
1143    pub(crate) fn root_hash(&self) -> Option<u128> {
1144        self.root.as_ref().map(|root| root.hash())
1145    }
1146
1147    /// Returns the value associated with `key` if present.
1148    pub fn get(&self, key: &[u8; KEY_LEN]) -> Option<&V> {
1149        self.root.as_ref().and_then(|root| root.get(0, key))
1150    }
1151
1152    /// Allows iteratig over all infixes of a given length with a given prefix.
1153    /// Each infix is passed to the provided closure.
1154    ///
1155    /// The entire operation is performed over the tree view ordering of the keys.
1156    ///
1157    /// The length of the prefix and the infix is provided as type parameters,
1158    /// but will usually inferred from the arguments.
1159    ///
1160    /// The sum of `PREFIX_LEN` and `INFIX_LEN` must be less than or equal to `KEY_LEN`
1161    /// or a compile-time assertion will fail.
1162    ///
1163    /// Because all infixes are iterated in one go, less bookkeeping is required,
1164    /// than when using an Iterator, allowing for better performance.
1165    pub fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
1166        &self,
1167        prefix: &[u8; PREFIX_LEN],
1168        mut for_each: F,
1169    ) where
1170        F: FnMut(&[u8; INFIX_LEN]),
1171    {
1172        const {
1173            assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
1174        }
1175        assert!(
1176            O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
1177                && (PREFIX_LEN + INFIX_LEN == KEY_LEN
1178                    || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
1179            "INFIX_LEN must cover a whole segment"
1180        );
1181        if let Some(root) = &self.root {
1182            root.infixes(prefix, 0, &mut for_each);
1183        }
1184    }
1185
1186    /// Like [`infixes`](Self::infixes) but only yields infixes in the
1187    /// byte range `[min_infix, max_infix]` (inclusive).
1188    ///
1189    /// The trie is pruned at each depth: branches whose byte key falls
1190    /// outside the range at the current infix position are skipped
1191    /// entirely, avoiding traversal of irrelevant subtrees.
1192    pub fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
1193        &self,
1194        prefix: &[u8; PREFIX_LEN],
1195        min_infix: &[u8; INFIX_LEN],
1196        max_infix: &[u8; INFIX_LEN],
1197        mut for_each: F,
1198    ) where
1199        F: FnMut(&[u8; INFIX_LEN]),
1200    {
1201        const {
1202            assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
1203        }
1204        assert!(
1205            O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
1206                && (PREFIX_LEN + INFIX_LEN == KEY_LEN
1207                    || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
1208            "INFIX_LEN must cover a whole segment"
1209        );
1210        if let Some(root) = &self.root {
1211            root.infixes_range(prefix, 0, min_infix, max_infix, &mut for_each);
1212        }
1213    }
1214
1215    /// Count entries whose infix falls within [min_infix, max_infix].
1216    ///
1217    /// Uses cached `leaf_count` on branches to skip entire subtrees that
1218    /// are fully inside the range, making the count O(boundary_nodes)
1219    /// rather than O(matching_leaves).
1220    pub fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
1221        &self,
1222        prefix: &[u8; PREFIX_LEN],
1223        min_infix: &[u8; INFIX_LEN],
1224        max_infix: &[u8; INFIX_LEN],
1225    ) -> u64 {
1226        const {
1227            assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
1228        }
1229        match &self.root {
1230            Some(root) => root.count_range(prefix, 0, min_infix, max_infix),
1231            None => 0,
1232        }
1233    }
1234
1235    /// Returns true if the PATCH has a key with the given prefix.
1236    ///
1237    /// `PREFIX_LEN` must be less than or equal to `KEY_LEN` or a compile-time
1238    /// assertion will fail.
1239    pub fn has_prefix<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> bool {
1240        const {
1241            assert!(PREFIX_LEN <= KEY_LEN);
1242        }
1243        if let Some(root) = &self.root {
1244            root.has_prefix(0, prefix)
1245        } else {
1246            PREFIX_LEN == 0
1247        }
1248    }
1249
1250    /// Returns the number of unique segments in keys with the given prefix.
1251    pub fn segmented_len<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> u64 {
1252        const {
1253            assert!(PREFIX_LEN <= KEY_LEN);
1254            if PREFIX_LEN > 0 && PREFIX_LEN < KEY_LEN {
1255                assert!(
1256                    <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
1257                        [O::TREE_TO_KEY[PREFIX_LEN - 1]]
1258                        != <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
1259                            [O::TREE_TO_KEY[PREFIX_LEN]],
1260                    "PREFIX_LEN must align to segment boundary",
1261                );
1262            }
1263        }
1264        if let Some(root) = &self.root {
1265            root.segmented_len(0, prefix)
1266        } else {
1267            0
1268        }
1269    }
1270
1271    /// Iterates over all keys in the PATCH.
1272    /// The keys are returned in key ordering but random order.
1273    pub fn iter<'a>(&'a self) -> PATCHIterator<'a, KEY_LEN, O, V> {
1274        PATCHIterator::new(self)
1275    }
1276
1277    /// Iterates over all keys in the PATCH in key order.
1278    ///
1279    /// The traversal visits every key in lexicographic key order, without
1280    /// accepting a prefix filter. For prefix-aware iteration, see
1281    /// [`PATCH::iter_prefix_count`].
1282    pub fn iter_ordered<'a>(&'a self) -> PATCHOrderedIterator<'a, KEY_LEN, O, V> {
1283        PATCHOrderedIterator::new(self)
1284    }
1285
1286    /// Iterate over all prefixes of the given length in the PATCH.
1287    /// The prefixes are naturally returned in tree ordering and tree order.
1288    /// A count of the number of elements for the given prefix is also returned.
1289    pub fn iter_prefix_count<'a, const PREFIX_LEN: usize>(
1290        &'a self,
1291    ) -> PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V> {
1292        PATCHPrefixIterator::new(self)
1293    }
1294
1295    /// Unions this PATCH with another PATCH.
1296    ///
1297    /// The other PATCH is consumed, and this PATCH is updated in place.
1298    pub fn union(&mut self, other: Self) {
1299        if let Some(other) = other.root {
1300            if self.root.is_some() {
1301                let this = self.root.take().expect("root should not be empty");
1302                let merged = Head::union(this, other, 0);
1303                self.root.replace(merged);
1304            } else {
1305                self.root.replace(other);
1306            }
1307        }
1308    }
1309
1310    /// Intersects this PATCH with another PATCH.
1311    ///
1312    /// Returns a new PATCH that contains only the keys that are present in both PATCHes.
1313    pub fn intersect(&self, other: &Self) -> Self {
1314        if let Some(root) = &self.root {
1315            if let Some(other_root) = &other.root {
1316                return Self {
1317                    root: root.intersect(other_root, 0).map(|root| root.with_start(0)),
1318                };
1319            }
1320        }
1321        Self::new()
1322    }
1323
1324    /// Returns the difference between this PATCH and another PATCH.
1325    ///
1326    /// Returns a new PATCH that contains only the keys that are present in this PATCH,
1327    /// but not in the other PATCH.
1328    pub fn difference(&self, other: &Self) -> Self {
1329        if let Some(root) = &self.root {
1330            if let Some(other_root) = &other.root {
1331                Self {
1332                    root: root.difference(other_root, 0),
1333                }
1334            } else {
1335                (*self).clone()
1336            }
1337        } else {
1338            Self::new()
1339        }
1340    }
1341
1342    /// Calculates the average fill level for branch nodes grouped by their
1343    /// branching factor. The returned array contains eight entries for branch
1344    /// sizes `2`, `4`, `8`, `16`, `32`, `64`, `128` and `256` in that order.
1345    //#[cfg(debug_assertions)]
1346    pub fn debug_branch_fill(&self) -> [f32; 8] {
1347        let mut counts = [0u64; 8];
1348        let mut used = [0u64; 8];
1349
1350        if let Some(root) = &self.root {
1351            let mut stack = Vec::new();
1352            stack.push(root);
1353
1354            while let Some(head) = stack.pop() {
1355                match head.body_ref() {
1356                    BodyRef::Leaf(_) => {}
1357                    BodyRef::Branch(b) => {
1358                        let size = b.child_table.len();
1359                        let idx = size.trailing_zeros() as usize - 1;
1360                        counts[idx] += 1;
1361                        used[idx] += b.child_table.iter().filter(|c| c.is_some()).count() as u64;
1362                        for child in b.child_table.iter().filter_map(|c| c.as_ref()) {
1363                            stack.push(child);
1364                        }
1365                    }
1366                }
1367            }
1368        }
1369
1370        let mut avg = [0f32; 8];
1371        for i in 0..8 {
1372            if counts[i] > 0 {
1373                let size = 1u64 << (i + 1);
1374                avg[i] = used[i] as f32 / (counts[i] as f32 * size as f32);
1375            }
1376        }
1377        avg
1378    }
1379}
1380
1381impl<const KEY_LEN: usize, O, V> PartialEq for PATCH<KEY_LEN, O, V>
1382where
1383    O: KeySchema<KEY_LEN>,
1384{
1385    fn eq(&self, other: &Self) -> bool {
1386        self.root.as_ref().map(|root| root.hash()) == other.root.as_ref().map(|root| root.hash())
1387    }
1388}
1389
1390impl<const KEY_LEN: usize, O, V> Eq for PATCH<KEY_LEN, O, V> where O: KeySchema<KEY_LEN> {}
1391
1392impl<'a, const KEY_LEN: usize, O, V> IntoIterator for &'a PATCH<KEY_LEN, O, V>
1393where
1394    O: KeySchema<KEY_LEN>,
1395{
1396    type Item = &'a [u8; KEY_LEN];
1397    type IntoIter = PATCHIterator<'a, KEY_LEN, O, V>;
1398
1399    fn into_iter(self) -> Self::IntoIter {
1400        PATCHIterator::new(self)
1401    }
1402}
1403
1404/// An iterator over all keys in a PATCH.
1405/// The keys are returned in key ordering but in random order.
1406pub struct PATCHIterator<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1407    stack: ArrayVec<std::slice::Iter<'a, Option<Head<KEY_LEN, O, V>>>, KEY_LEN>,
1408    remaining: usize,
1409}
1410
1411impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHIterator<'a, KEY_LEN, O, V> {
1412    /// Creates an iterator over all keys in `patch`.
1413    pub fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
1414        let mut r = PATCHIterator {
1415            stack: ArrayVec::new(),
1416            remaining: patch.len().min(usize::MAX as u64) as usize,
1417        };
1418        r.stack.push(std::slice::from_ref(&patch.root).iter());
1419        r
1420    }
1421}
1422
1423impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1424    for PATCHIterator<'a, KEY_LEN, O, V>
1425{
1426    type Item = &'a [u8; KEY_LEN];
1427
1428    fn next(&mut self) -> Option<Self::Item> {
1429        let mut iter = self.stack.last_mut()?;
1430        loop {
1431            if let Some(child) = iter.next() {
1432                if let Some(child) = child {
1433                    match child.body_ref() {
1434                        BodyRef::Leaf(_) => {
1435                            self.remaining = self.remaining.saturating_sub(1);
1436                            // Use the safe accessor on the child reference to obtain the leaf key bytes.
1437                            return Some(child.childleaf_key());
1438                        }
1439                        BodyRef::Branch(branch) => {
1440                            self.stack.push(branch.child_table.iter());
1441                            iter = self.stack.last_mut()?;
1442                        }
1443                    }
1444                }
1445            } else {
1446                self.stack.pop();
1447                iter = self.stack.last_mut()?;
1448            }
1449        }
1450    }
1451
1452    fn size_hint(&self) -> (usize, Option<usize>) {
1453        (self.remaining, Some(self.remaining))
1454    }
1455}
1456
1457impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ExactSizeIterator
1458    for PATCHIterator<'a, KEY_LEN, O, V>
1459{
1460}
1461
1462impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> std::iter::FusedIterator
1463    for PATCHIterator<'a, KEY_LEN, O, V>
1464{
1465}
1466
1467/// An iterator over every key in a PATCH, returned in key order.
1468///
1469/// Keys are yielded in lexicographic key order regardless of their physical
1470/// layout in the underlying tree. This iterator walks the full tree and does
1471/// not accept a prefix filter. For prefix-aware iteration, use
1472/// [`PATCHPrefixIterator`], constructed via [`PATCH::iter_prefix_count`].
1473pub struct PATCHOrderedIterator<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1474    stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V>, 256>>,
1475    remaining: usize,
1476}
1477
1478impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHOrderedIterator<'a, KEY_LEN, O, V> {
1479    pub fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
1480        let mut r = PATCHOrderedIterator {
1481            stack: Vec::with_capacity(KEY_LEN),
1482            remaining: patch.len().min(usize::MAX as u64) as usize,
1483        };
1484        if let Some(root) = &patch.root {
1485            r.stack.push(ArrayVec::new());
1486            match root.body_ref() {
1487                BodyRef::Leaf(_) => {
1488                    r.stack[0].push(root);
1489                }
1490                BodyRef::Branch(branch) => {
1491                    let first_level = &mut r.stack[0];
1492                    first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1493                    first_level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1494                }
1495            }
1496        }
1497        r
1498    }
1499}
1500
1501// --- Owned consuming iterators ---
1502/// Iterator that owns a PATCH and yields keys in key-order. The iterator
1503/// consumes the PATCH and stores it on the heap (Box) so it can safely hold
1504/// raw pointers into the patch memory while the iterator is moved.
1505pub struct PATCHIntoIterator<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1506    queue: Vec<Head<KEY_LEN, O, V>>,
1507    remaining: usize,
1508}
1509
1510impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCHIntoIterator<KEY_LEN, O, V> {}
1511
1512impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator for PATCHIntoIterator<KEY_LEN, O, V> {
1513    type Item = [u8; KEY_LEN];
1514
1515    fn next(&mut self) -> Option<Self::Item> {
1516        let q = &mut self.queue;
1517        while let Some(mut head) = q.pop() {
1518            // Match on the mutable body directly. For leaves we can return the
1519            // stored key (the array is Copy), for branches we take children out
1520            // of the table and push them onto the stack so they are visited
1521            // depth-first.
1522            match head.body_mut() {
1523                BodyMut::Leaf(leaf) => {
1524                    self.remaining = self.remaining.saturating_sub(1);
1525                    return Some(leaf.key);
1526                }
1527                BodyMut::Branch(branch) => {
1528                    for slot in branch.child_table.iter_mut().rev() {
1529                        if let Some(c) = slot.take() {
1530                            q.push(c);
1531                        }
1532                    }
1533                }
1534            }
1535        }
1536        None
1537    }
1538}
1539
1540/// Iterator that owns a PATCH and yields keys in key order.
1541pub struct PATCHIntoOrderedIterator<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> {
1542    queue: Vec<Head<KEY_LEN, O, V>>,
1543    remaining: usize,
1544}
1545
1546impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1547    for PATCHIntoOrderedIterator<KEY_LEN, O, V>
1548{
1549    type Item = [u8; KEY_LEN];
1550
1551    fn next(&mut self) -> Option<Self::Item> {
1552        let q = &mut self.queue;
1553        while let Some(mut head) = q.pop() {
1554            // Match the mutable body directly — we own `head` so calling
1555            // `body_mut()` is safe and allows returning the copied leaf key
1556            // or mutating the branch child table in-place.
1557            match head.body_mut() {
1558                BodyMut::Leaf(leaf) => {
1559                    self.remaining = self.remaining.saturating_sub(1);
1560                    return Some(leaf.key);
1561                }
1562                BodyMut::Branch(branch) => {
1563                    let slice: &mut [Option<Head<KEY_LEN, O, V>>] = &mut branch.child_table;
1564                    // Sort children by their byte-key, placing empty slots (None)
1565                    // after all occupied slots. Using `sort_unstable_by_key` with
1566                    // a simple key projection is clearer than a custom
1567                    // comparator; it also avoids allocating temporaries. The
1568                    // old comparator manually handled None/Some cases — we
1569                    // express that intent directly by sorting on the tuple
1570                    // (is_none, key_opt).
1571                    slice
1572                        .sort_unstable_by_key(|opt| (opt.is_none(), opt.as_ref().map(|h| h.key())));
1573                    for slot in slice.iter_mut().rev() {
1574                        if let Some(c) = slot.take() {
1575                            q.push(c);
1576                        }
1577                    }
1578                }
1579            }
1580        }
1581        None
1582    }
1583}
1584
1585impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> IntoIterator for PATCH<KEY_LEN, O, V> {
1586    type Item = [u8; KEY_LEN];
1587    type IntoIter = PATCHIntoIterator<KEY_LEN, O, V>;
1588
1589    fn into_iter(self) -> Self::IntoIter {
1590        let remaining = self.len().min(usize::MAX as u64) as usize;
1591        let mut q = Vec::new();
1592        if let Some(root) = self.root {
1593            q.push(root);
1594        }
1595        PATCHIntoIterator {
1596            queue: q,
1597            remaining,
1598        }
1599    }
1600}
1601
1602impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> PATCH<KEY_LEN, O, V> {
1603    /// Consume and return an iterator that yields keys in key order.
1604    pub fn into_iter_ordered(self) -> PATCHIntoOrderedIterator<KEY_LEN, O, V> {
1605        let remaining = self.len().min(usize::MAX as u64) as usize;
1606        let mut q = Vec::new();
1607        if let Some(root) = self.root {
1608            q.push(root);
1609        }
1610        PATCHIntoOrderedIterator {
1611            queue: q,
1612            remaining,
1613        }
1614    }
1615}
1616
1617impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1618    for PATCHOrderedIterator<'a, KEY_LEN, O, V>
1619{
1620    type Item = &'a [u8; KEY_LEN];
1621
1622    fn next(&mut self) -> Option<Self::Item> {
1623        let mut level = self.stack.last_mut()?;
1624        loop {
1625            if let Some(child) = level.pop() {
1626                match child.body_ref() {
1627                    BodyRef::Leaf(_) => {
1628                        self.remaining = self.remaining.saturating_sub(1);
1629                        return Some(child.childleaf_key());
1630                    }
1631                    BodyRef::Branch(branch) => {
1632                        self.stack.push(ArrayVec::new());
1633                        level = self.stack.last_mut()?;
1634                        level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1635                        level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1636                    }
1637                }
1638            } else {
1639                self.stack.pop();
1640                level = self.stack.last_mut()?;
1641            }
1642        }
1643    }
1644
1645    fn size_hint(&self) -> (usize, Option<usize>) {
1646        (self.remaining, Some(self.remaining))
1647    }
1648}
1649
1650impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> ExactSizeIterator
1651    for PATCHOrderedIterator<'a, KEY_LEN, O, V>
1652{
1653}
1654
1655impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V> std::iter::FusedIterator
1656    for PATCHOrderedIterator<'a, KEY_LEN, O, V>
1657{
1658}
1659
1660/// An iterator over all keys in a PATCH that have a given prefix.
1661/// The keys are returned in tree ordering and in tree order.
1662pub struct PATCHPrefixIterator<
1663    'a,
1664    const KEY_LEN: usize,
1665    const PREFIX_LEN: usize,
1666    O: KeySchema<KEY_LEN>,
1667    V,
1668> {
1669    stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V>, 256>>,
1670}
1671
1672impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V>
1673    PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V>
1674{
1675    fn new(patch: &'a PATCH<KEY_LEN, O, V>) -> Self {
1676        const {
1677            assert!(PREFIX_LEN <= KEY_LEN);
1678        }
1679        let mut r = PATCHPrefixIterator {
1680            stack: Vec::with_capacity(PREFIX_LEN),
1681        };
1682        if let Some(root) = &patch.root {
1683            r.stack.push(ArrayVec::new());
1684            if root.end_depth() >= PREFIX_LEN {
1685                r.stack[0].push(root);
1686            } else {
1687                let BodyRef::Branch(branch) = root.body_ref() else {
1688                    unreachable!();
1689                };
1690                let first_level = &mut r.stack[0];
1691                first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1692                first_level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1693            }
1694        }
1695        r
1696    }
1697}
1698
1699impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V> Iterator
1700    for PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V>
1701{
1702    type Item = ([u8; PREFIX_LEN], u64);
1703
1704    fn next(&mut self) -> Option<Self::Item> {
1705        let mut level = self.stack.last_mut()?;
1706        loop {
1707            if let Some(child) = level.pop() {
1708                if child.end_depth() >= PREFIX_LEN {
1709                    let key = O::tree_ordered(child.childleaf_key());
1710                    let suffix_count = child.count();
1711                    return Some((key[0..PREFIX_LEN].try_into().unwrap(), suffix_count));
1712                } else {
1713                    let BodyRef::Branch(branch) = child.body_ref() else {
1714                        unreachable!();
1715                    };
1716                    self.stack.push(ArrayVec::new());
1717                    level = self.stack.last_mut()?;
1718                    level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
1719                    level.sort_unstable_by_key(|&k| Reverse(k.key())); // We need to reverse here because we pop from the vec.
1720                }
1721            } else {
1722                self.stack.pop();
1723                level = self.stack.last_mut()?;
1724            }
1725        }
1726    }
1727}
1728
1729#[cfg(test)]
1730mod tests {
1731    use super::*;
1732    use itertools::Itertools;
1733    use proptest::prelude::*;
1734    use std::collections::HashSet;
1735    use std::convert::TryInto;
1736    use std::iter::FromIterator;
1737    use std::mem;
1738
1739    #[test]
1740    fn head_tag() {
1741        let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(0, NonNull::dangling());
1742        assert_eq!(head.tag(), HeadTag::Leaf);
1743        mem::forget(head);
1744    }
1745
1746    #[test]
1747    fn head_key() {
1748        for k in 0..=255 {
1749            let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(k, NonNull::dangling());
1750            assert_eq!(head.key(), k);
1751            mem::forget(head);
1752        }
1753    }
1754
1755    #[test]
1756    fn head_size() {
1757        assert_eq!(mem::size_of::<Head<64, IdentitySchema, ()>>(), 8);
1758    }
1759
1760    #[test]
1761    fn option_head_size() {
1762        assert_eq!(mem::size_of::<Option<Head<64, IdentitySchema, ()>>>(), 8);
1763    }
1764
1765    #[test]
1766    fn empty_tree() {
1767        let _tree = PATCH::<64, IdentitySchema, ()>::new();
1768    }
1769
1770    #[test]
1771    fn tree_put_one() {
1772        const KEY_SIZE: usize = 64;
1773        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1774        let entry = Entry::new(&[0; KEY_SIZE]);
1775        tree.insert(&entry);
1776    }
1777
1778    #[test]
1779    fn tree_clone_one() {
1780        const KEY_SIZE: usize = 64;
1781        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1782        let entry = Entry::new(&[0; KEY_SIZE]);
1783        tree.insert(&entry);
1784        let _clone = tree.clone();
1785    }
1786
1787    #[test]
1788    fn tree_put_same() {
1789        const KEY_SIZE: usize = 64;
1790        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1791        let entry = Entry::new(&[0; KEY_SIZE]);
1792        tree.insert(&entry);
1793        tree.insert(&entry);
1794    }
1795
1796    #[test]
1797    fn tree_replace_existing() {
1798        const KEY_SIZE: usize = 64;
1799        let key = [1u8; KEY_SIZE];
1800        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1801        let entry1 = Entry::with_value(&key, 1);
1802        tree.insert(&entry1);
1803        let entry2 = Entry::with_value(&key, 2);
1804        tree.replace(&entry2);
1805        assert_eq!(tree.get(&key), Some(&2));
1806    }
1807
1808    #[test]
1809    fn tree_replace_childleaf_updates_branch() {
1810        const KEY_SIZE: usize = 64;
1811        let key1 = [0u8; KEY_SIZE];
1812        let key2 = [1u8; KEY_SIZE];
1813        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1814        let entry1 = Entry::with_value(&key1, 1);
1815        let entry2 = Entry::with_value(&key2, 2);
1816        tree.insert(&entry1);
1817        tree.insert(&entry2);
1818        let entry1b = Entry::with_value(&key1, 3);
1819        tree.replace(&entry1b);
1820        assert_eq!(tree.get(&key1), Some(&3));
1821        assert_eq!(tree.get(&key2), Some(&2));
1822    }
1823
1824    #[test]
1825    fn update_child_refreshes_childleaf_on_replace() {
1826        const KEY_SIZE: usize = 4;
1827        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1828
1829        let key1 = [0u8; KEY_SIZE];
1830        let key2 = [1u8; KEY_SIZE];
1831        tree.insert(&Entry::with_value(&key1, 1));
1832        tree.insert(&Entry::with_value(&key2, 2));
1833
1834        // Determine which child currently provides the branch childleaf.
1835        let root_ref = tree.root.as_ref().expect("root exists");
1836        let before_childleaf = *root_ref.childleaf_key();
1837
1838        // Find the slot key (the byte index used in the branch table) for the child
1839        // that currently provides the childleaf.
1840        let slot_key = match root_ref.body_ref() {
1841            BodyRef::Branch(branch) => branch
1842                .child_table
1843                .iter()
1844                .filter_map(|c| c.as_ref())
1845                .find(|c| c.childleaf_key() == &before_childleaf)
1846                .expect("child exists")
1847                .key(),
1848            BodyRef::Leaf(_) => panic!("root should be a branch"),
1849        };
1850
1851        // Replace that child with a new leaf that has a different childleaf key.
1852        let new_key = [2u8; KEY_SIZE];
1853        {
1854            let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
1855            ed.modify_child(slot_key, |_| {
1856                Some(Entry::with_value(&new_key, 42).leaf::<IdentitySchema>())
1857            });
1858            // drop(ed) commits
1859        }
1860
1861        let after = tree.root.as_ref().expect("root exists");
1862        assert_eq!(after.childleaf_key(), &new_key);
1863    }
1864
1865    #[test]
1866    fn remove_childleaf_updates_branch() {
1867        const KEY_SIZE: usize = 4;
1868        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1869
1870        let key1 = [0u8; KEY_SIZE];
1871        let key2 = [1u8; KEY_SIZE];
1872        tree.insert(&Entry::with_value(&key1, 1));
1873        tree.insert(&Entry::with_value(&key2, 2));
1874
1875        let childleaf_before = *tree.root.as_ref().unwrap().childleaf_key();
1876        // remove the leaf that currently provides the branch.childleaf
1877        tree.remove(&childleaf_before);
1878
1879        // Ensure the removed key is gone and the other key remains and is now the childleaf.
1880        let other = if childleaf_before == key1 { key2 } else { key1 };
1881        assert_eq!(tree.get(&childleaf_before), None);
1882        assert_eq!(tree.get(&other), Some(&2u32));
1883        let after_childleaf = tree.root.as_ref().unwrap().childleaf_key();
1884        assert_eq!(after_childleaf, &other);
1885    }
1886
1887    #[test]
1888    fn remove_collapses_branch_to_single_child() {
1889        const KEY_SIZE: usize = 4;
1890        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
1891
1892        let key1 = [0u8; KEY_SIZE];
1893        let key2 = [1u8; KEY_SIZE];
1894        tree.insert(&Entry::with_value(&key1, 1));
1895        tree.insert(&Entry::with_value(&key2, 2));
1896
1897        // Remove one key and ensure the root collapses to the remaining child.
1898        tree.remove(&key1);
1899        assert_eq!(tree.get(&key1), None);
1900        assert_eq!(tree.get(&key2), Some(&2u32));
1901        let root = tree.root.as_ref().expect("root exists");
1902        match root.body_ref() {
1903            BodyRef::Leaf(_) => {}
1904            BodyRef::Branch(_) => panic!("root should have collapsed to a leaf"),
1905        }
1906    }
1907
1908    #[test]
1909    fn branch_size() {
1910        assert_eq!(
1911            mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 2], ()>>(
1912            ),
1913            64
1914        );
1915        assert_eq!(
1916            mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 4], ()>>(
1917            ),
1918            48 + 16 * 2
1919        );
1920        assert_eq!(
1921            mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 8], ()>>(
1922            ),
1923            48 + 16 * 4
1924        );
1925        assert_eq!(
1926            mem::size_of::<
1927                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 16], ()>,
1928            >(),
1929            48 + 16 * 8
1930        );
1931        assert_eq!(
1932            mem::size_of::<
1933                Branch<64, IdentitySchema, [Option<Head<32, IdentitySchema, ()>>; 32], ()>,
1934            >(),
1935            48 + 16 * 16
1936        );
1937        assert_eq!(
1938            mem::size_of::<
1939                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 64], ()>,
1940            >(),
1941            48 + 16 * 32
1942        );
1943        assert_eq!(
1944            mem::size_of::<
1945                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 128], ()>,
1946            >(),
1947            48 + 16 * 64
1948        );
1949        assert_eq!(
1950            mem::size_of::<
1951                Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 256], ()>,
1952            >(),
1953            48 + 16 * 128
1954        );
1955    }
1956
1957    /// Checks what happens if we join two PATCHes that
1958    /// only contain a single element each, that differs in the last byte.
1959    #[test]
1960    fn tree_union_single() {
1961        const KEY_SIZE: usize = 8;
1962        let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1963        let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
1964        let left_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 0]);
1965        let right_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 1]);
1966        left.insert(&left_entry);
1967        right.insert(&right_entry);
1968        left.union(right);
1969        assert_eq!(left.len(), 2);
1970    }
1971
1972    // Small unit tests that ensure BranchMut-based editing is used by
1973    // the higher-level set operations like intersect/difference. These are
1974    // ordinary unit tests (not proptest) and must appear outside the
1975    // `proptest!` macro below.
1976
1977    proptest! {
1978        #[test]
1979        fn tree_insert(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
1980            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
1981            for key in keys {
1982                let key: [u8; 64] = key.try_into().unwrap();
1983                let entry = Entry::new(&key);
1984                tree.insert(&entry);
1985            }
1986        }
1987
1988        #[test]
1989        fn tree_len(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
1990            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
1991            let mut set = HashSet::new();
1992            for key in keys {
1993                let key: [u8; 64] = key.try_into().unwrap();
1994                let entry = Entry::new(&key);
1995                tree.insert(&entry);
1996                set.insert(key);
1997            }
1998
1999            prop_assert_eq!(set.len() as u64, tree.len())
2000        }
2001
2002        #[test]
2003        fn tree_infixes(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
2004            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
2005            let mut set = HashSet::new();
2006            for key in keys {
2007                let key: [u8; 64] = key.try_into().unwrap();
2008                let entry = Entry::new(&key);
2009                tree.insert(&entry);
2010                set.insert(key);
2011            }
2012            let mut set_vec = Vec::from_iter(set.into_iter());
2013            let mut tree_vec = vec![];
2014            tree.infixes(&[0; 0], &mut |&x: &[u8; 64]| tree_vec.push(x));
2015
2016            set_vec.sort();
2017            tree_vec.sort();
2018
2019            prop_assert_eq!(set_vec, tree_vec);
2020        }
2021
2022        #[test]
2023        fn tree_iter(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
2024            let mut tree = PATCH::<64, IdentitySchema, ()>::new();
2025            let mut set = HashSet::new();
2026            for key in keys {
2027                let key: [u8; 64] = key.try_into().unwrap();
2028                let entry = Entry::new(&key);
2029                tree.insert(&entry);
2030                set.insert(key);
2031            }
2032            let mut set_vec = Vec::from_iter(set.into_iter());
2033            let mut tree_vec = vec![];
2034            for key in &tree {
2035                tree_vec.push(*key);
2036            }
2037
2038            set_vec.sort();
2039            tree_vec.sort();
2040
2041            prop_assert_eq!(set_vec, tree_vec);
2042        }
2043
2044        #[test]
2045        fn tree_union(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200),
2046                        right in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200)) {
2047            let mut set = HashSet::new();
2048
2049            let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
2050            for entry in left {
2051                let mut key = [0; 64];
2052                key.iter_mut().set_from(entry.iter().cloned());
2053                let entry = Entry::new(&key);
2054                left_tree.insert(&entry);
2055                set.insert(key);
2056            }
2057
2058            let mut right_tree = PATCH::<64, IdentitySchema, ()>::new();
2059            for entry in right {
2060                let mut key = [0; 64];
2061                key.iter_mut().set_from(entry.iter().cloned());
2062                let entry = Entry::new(&key);
2063                right_tree.insert(&entry);
2064                set.insert(key);
2065            }
2066
2067            left_tree.union(right_tree);
2068
2069            let mut set_vec = Vec::from_iter(set.into_iter());
2070            let mut tree_vec = vec![];
2071            left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
2072
2073            set_vec.sort();
2074            tree_vec.sort();
2075
2076            prop_assert_eq!(set_vec, tree_vec);
2077            }
2078
2079        #[test]
2080        fn tree_union_empty(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 2)) {
2081            let mut set = HashSet::new();
2082
2083            let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
2084            for entry in left {
2085                let mut key = [0; 64];
2086                key.iter_mut().set_from(entry.iter().cloned());
2087                let entry = Entry::new(&key);
2088                left_tree.insert(&entry);
2089                set.insert(key);
2090            }
2091
2092            let right_tree = PATCH::<64, IdentitySchema, ()>::new();
2093
2094            left_tree.union(right_tree);
2095
2096            let mut set_vec = Vec::from_iter(set.into_iter());
2097            let mut tree_vec = vec![];
2098            left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
2099
2100            set_vec.sort();
2101            tree_vec.sort();
2102
2103            prop_assert_eq!(set_vec, tree_vec);
2104            }
2105
2106        // I got a feeling that we're not testing COW properly.
2107        // We should check if a tree remains the same after a clone of it
2108        // is modified by inserting new keys.
2109
2110    #[test]
2111    fn cow_on_insert(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
2112                         new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
2113            // Note that we can't compare the trees directly, as that uses the hash,
2114            // which might not be affected by nodes in lower levels being changed accidentally.
2115            // Instead we need to iterate over the keys and check if they are the same.
2116
2117            let mut tree = PATCH::<8, IdentitySchema, ()>::new();
2118            for key in base_keys {
2119                let key: [u8; 8] = key[..].try_into().unwrap();
2120                let entry = Entry::new(&key);
2121                tree.insert(&entry);
2122            }
2123            let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2124
2125            let mut tree_clone = tree.clone();
2126            for key in new_keys {
2127                let key: [u8; 8] = key[..].try_into().unwrap();
2128                let entry = Entry::new(&key);
2129                tree_clone.insert(&entry);
2130            }
2131
2132            let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2133            prop_assert_eq!(base_tree_content, new_tree_content);
2134        }
2135
2136        #[test]
2137    fn cow_on_union(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
2138                         new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
2139            // Note that we can't compare the trees directly, as that uses the hash,
2140            // which might not be affected by nodes in lower levels being changed accidentally.
2141            // Instead we need to iterate over the keys and check if they are the same.
2142
2143            let mut tree = PATCH::<8, IdentitySchema, ()>::new();
2144            for key in base_keys {
2145                let key: [u8; 8] = key[..].try_into().unwrap();
2146                let entry = Entry::new(&key);
2147                tree.insert(&entry);
2148            }
2149            let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2150
2151            let mut tree_clone = tree.clone();
2152            let mut new_tree = PATCH::<8, IdentitySchema, ()>::new();
2153            for key in new_keys {
2154                let key: [u8; 8] = key[..].try_into().unwrap();
2155                let entry = Entry::new(&key);
2156                new_tree.insert(&entry);
2157            }
2158            tree_clone.union(new_tree);
2159
2160            let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
2161            prop_assert_eq!(base_tree_content, new_tree_content);
2162        }
2163    }
2164
2165    #[test]
2166    fn intersect_multiple_common_children_commits_branchmut() {
2167        const KEY_SIZE: usize = 4;
2168        let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2169        let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2170
2171        let a = [0u8, 0u8, 0u8, 1u8];
2172        let b = [0u8, 0u8, 0u8, 2u8];
2173        let c = [0u8, 0u8, 0u8, 3u8];
2174        let d = [2u8, 0u8, 0u8, 0u8];
2175        let e = [3u8, 0u8, 0u8, 0u8];
2176
2177        left.insert(&Entry::with_value(&a, 1));
2178        left.insert(&Entry::with_value(&b, 2));
2179        left.insert(&Entry::with_value(&c, 3));
2180        left.insert(&Entry::with_value(&d, 4));
2181
2182        right.insert(&Entry::with_value(&a, 10));
2183        right.insert(&Entry::with_value(&b, 11));
2184        right.insert(&Entry::with_value(&c, 12));
2185        right.insert(&Entry::with_value(&e, 13));
2186
2187        let res = left.intersect(&right);
2188        // A, B, C are common
2189        assert_eq!(res.len(), 3);
2190        assert!(res.get(&a).is_some());
2191        assert!(res.get(&b).is_some());
2192        assert!(res.get(&c).is_some());
2193    }
2194
2195    #[test]
2196    fn difference_multiple_children_commits_branchmut() {
2197        const KEY_SIZE: usize = 4;
2198        let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2199        let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2200
2201        let a = [0u8, 0u8, 0u8, 1u8];
2202        let b = [0u8, 0u8, 0u8, 2u8];
2203        let c = [0u8, 0u8, 0u8, 3u8];
2204        let d = [2u8, 0u8, 0u8, 0u8];
2205        let e = [3u8, 0u8, 0u8, 0u8];
2206
2207        left.insert(&Entry::with_value(&a, 1));
2208        left.insert(&Entry::with_value(&b, 2));
2209        left.insert(&Entry::with_value(&c, 3));
2210        left.insert(&Entry::with_value(&d, 4));
2211
2212        right.insert(&Entry::with_value(&a, 10));
2213        right.insert(&Entry::with_value(&b, 11));
2214        right.insert(&Entry::with_value(&c, 12));
2215        right.insert(&Entry::with_value(&e, 13));
2216
2217        let res = left.difference(&right);
2218        // left only has d
2219        assert_eq!(res.len(), 1);
2220        assert!(res.get(&d).is_some());
2221    }
2222
2223    #[test]
2224    fn difference_empty_left_is_empty() {
2225        const KEY_SIZE: usize = 4;
2226        let left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2227        let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2228        let key = [1u8, 2u8, 3u8, 4u8];
2229        right.insert(&Entry::with_value(&key, 7));
2230
2231        let res = left.difference(&right);
2232        assert_eq!(res.len(), 0);
2233    }
2234
2235    #[test]
2236    fn difference_empty_right_returns_left() {
2237        const KEY_SIZE: usize = 4;
2238        let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2239        let right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2240        let key = [1u8, 2u8, 3u8, 4u8];
2241        left.insert(&Entry::with_value(&key, 7));
2242
2243        let res = left.difference(&right);
2244        assert_eq!(res.len(), 1);
2245        assert!(res.get(&key).is_some());
2246    }
2247
2248    #[test]
2249    fn slot_edit_branchmut_insert_update() {
2250        // Small unit test demonstrating the Slot::edit -> BranchMut insert/update pattern.
2251        const KEY_SIZE: usize = 8;
2252        let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
2253
2254        let entry1 = Entry::with_value(&[0u8; KEY_SIZE], 1u32);
2255        let entry2 = Entry::with_value(&[1u8; KEY_SIZE], 2u32);
2256        tree.insert(&entry1);
2257        tree.insert(&entry2);
2258        assert_eq!(tree.len(), 2);
2259
2260        // Edit the root slot in-place using the BranchMut editor.
2261        {
2262            let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
2263
2264            // Compute the insertion start depth first to avoid borrowing `ed` inside the closure.
2265            let start_depth = ed.end_depth as usize;
2266            let inserted = Entry::with_value(&[2u8; KEY_SIZE], 3u32)
2267                .leaf::<IdentitySchema>()
2268                .with_start(start_depth);
2269            let key = inserted.key();
2270
2271            ed.modify_child(key, |opt| match opt {
2272                Some(old) => Some(Head::insert_leaf(old, inserted, start_depth)),
2273                None => Some(inserted),
2274            });
2275            // BranchMut is dropped here and commits the updated branch pointer back into the head.
2276        }
2277
2278        assert_eq!(tree.len(), 3);
2279        assert_eq!(tree.get(&[2u8; KEY_SIZE]), Some(&3u32));
2280    }
2281}