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