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