1#![allow(unstable_name_collisions)]
13
14mod branch;
15pub mod bytetable;
17mod entry;
18mod leaf;
19
20use arrayvec::ArrayVec;
21
22use branch::*;
24pub use entry::{ArchiveEntry, Entry};
25use leaf::*;
26
27pub use bytetable::*;
29use rand::thread_rng;
30use rand::RngCore;
31use std::cmp::{Ordering, Reverse};
32use std::convert::TryInto;
33use std::fmt;
34use std::fmt::Debug;
35use std::marker::PhantomData;
36use std::ptr::NonNull;
37use std::sync::{Arc, OnceLock};
38
39pub trait ArchiveOwner: Send + Sync + 'static {}
43
44impl<T: Send + Sync + 'static + ?Sized> ArchiveOwner for T {}
45
46#[derive(Clone)]
55enum OwnerNode {
56 Owner(Arc<dyn ArchiveOwner>),
57 Branch(Arc<OwnerBranch>),
58}
59
60struct OwnerBranch {
61 mask: usize,
62 zero: OwnerNode,
63 one: OwnerNode,
64}
65
66#[derive(Clone)]
73struct OwnerCover {
74 latest_address: usize,
75 len: usize,
76 root: OwnerNode,
77}
78
79impl core::fmt::Debug for OwnerCover {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 f.debug_struct("OwnerCover")
82 .field("len", &self.len)
83 .finish()
84 }
85}
86
87impl OwnerNode {
88 #[inline]
89 fn takes_one(address: usize, mask: usize) -> bool {
90 address & mask != 0
91 }
92
93 #[inline]
94 fn critical_mask(left: usize, right: usize) -> usize {
95 let differing = left ^ right;
96 debug_assert_ne!(differing, 0);
97 1usize << (usize::BITS - 1 - differing.leading_zeros())
98 }
99
100 fn matching_owner(&self, address: usize) -> &Arc<dyn ArchiveOwner> {
101 let mut node = self;
102 loop {
103 match node {
104 Self::Owner(owner) => return owner,
105 Self::Branch(branch) => {
106 node = if Self::takes_one(address, branch.mask) {
107 &branch.one
108 } else {
109 &branch.zero
110 };
111 }
112 }
113 }
114 }
115
116 #[cfg(any(debug_assertions, test))]
117 fn contains(&self, address: usize) -> bool {
118 OwnerCover::address(self.matching_owner(address)) == address
119 }
120
121 #[cfg(test)]
122 fn same_shape(&self, other: &Self) -> bool {
123 match (self, other) {
124 (Self::Owner(left), Self::Owner(right)) => {
125 OwnerCover::address(left) == OwnerCover::address(right)
126 }
127 (Self::Branch(left), Self::Branch(right)) => {
128 left.mask == right.mask
129 && left.zero.same_shape(&right.zero)
130 && left.one.same_shape(&right.one)
131 }
132 _ => false,
133 }
134 }
135
136 fn insert(&self, owner: &Arc<dyn ArchiveOwner>) -> (Self, bool) {
138 let address = OwnerCover::address(owner);
139 let matching = self.matching_owner(address);
140 let existing_address = OwnerCover::address(matching);
141 if existing_address == address {
142 debug_assert!(Arc::ptr_eq(matching, owner));
143 return (self.clone(), false);
144 }
145
146 let critical_mask = Self::critical_mask(address, existing_address);
147 (
148 Self::insert_at(
149 self,
150 Self::Owner(owner.clone()),
151 address,
152 existing_address,
153 critical_mask,
154 ),
155 true,
156 )
157 }
158
159 fn insert_at(
160 root: &Self,
161 inserted: Self,
162 inserted_address: usize,
163 existing_address: usize,
164 critical_mask: usize,
165 ) -> Self {
166 if let Self::Branch(branch) = root {
167 if branch.mask > critical_mask {
168 if Self::takes_one(inserted_address, branch.mask) {
169 return Self::Branch(Arc::new(OwnerBranch {
170 mask: branch.mask,
171 zero: branch.zero.clone(),
172 one: Self::insert_at(
173 &branch.one,
174 inserted,
175 inserted_address,
176 existing_address,
177 critical_mask,
178 ),
179 }));
180 }
181 return Self::Branch(Arc::new(OwnerBranch {
182 mask: branch.mask,
183 zero: Self::insert_at(
184 &branch.zero,
185 inserted,
186 inserted_address,
187 existing_address,
188 critical_mask,
189 ),
190 one: branch.one.clone(),
191 }));
192 }
193 debug_assert_ne!(branch.mask, critical_mask);
194 }
195
196 debug_assert_ne!(
197 Self::takes_one(inserted_address, critical_mask),
198 Self::takes_one(existing_address, critical_mask),
199 );
200 let (zero, one) = if Self::takes_one(inserted_address, critical_mask) {
201 (root.clone(), inserted)
202 } else {
203 (inserted, root.clone())
204 };
205 Self::Branch(Arc::new(OwnerBranch {
206 mask: critical_mask,
207 zero,
208 one,
209 }))
210 }
211
212 fn for_each_owner<F>(&self, f: &mut F)
213 where
214 F: FnMut(&Arc<dyn ArchiveOwner>),
215 {
216 match self {
217 Self::Owner(owner) => f(owner),
218 Self::Branch(branch) => {
219 branch.zero.for_each_owner(f);
220 branch.one.for_each_owner(f);
221 }
222 }
223 }
224}
225
226impl OwnerCover {
227 #[inline]
228 fn address(owner: &Arc<dyn ArchiveOwner>) -> usize {
229 Arc::as_ptr(owner) as *const () as usize
230 }
231
232 fn singleton(owner: &Arc<dyn ArchiveOwner>) -> Arc<Self> {
233 Arc::new(Self {
234 latest_address: Self::address(owner),
235 len: 1,
236 root: OwnerNode::Owner(owner.clone()),
237 })
238 }
239
240 fn retain(current: &mut Option<Arc<Self>>, owner: &Arc<dyn ArchiveOwner>) {
241 let address = Self::address(owner);
242 let Some(existing) = current.as_mut() else {
243 *current = Some(Self::singleton(owner));
244 return;
245 };
246 if existing.latest_address == address {
247 return;
248 }
249
250 let (root, inserted) = existing.root.insert(owner);
253 let cover = Arc::make_mut(existing);
254 cover.root = root;
255 cover.len += usize::from(inserted);
256 cover.latest_address = address;
257 }
258
259 fn merge_into(current: &mut Option<Arc<Self>>, other: &Option<Arc<Self>>) {
261 *current = Self::union(current.clone(), other);
262 }
263
264 fn union(left: Option<Arc<Self>>, right: &Option<Arc<Self>>) -> Option<Arc<Self>> {
265 let Some(right) = right.as_ref() else {
266 return left;
267 };
268 let Some(left) = left else {
269 return Some(right.clone());
270 };
271 if Arc::ptr_eq(&left, right) {
272 return Some(left);
273 }
274
275 let (mut result, additions) = if left.len >= right.len {
278 (left.clone(), right)
279 } else {
280 (right.clone(), &left)
281 };
282 additions.root.for_each_owner(&mut |owner| {
283 let (root, inserted) = result.root.insert(owner);
284 if inserted {
285 let cover = Arc::make_mut(&mut result);
286 cover.root = root;
287 cover.len += 1;
288 }
289 });
290 if result.latest_address != right.latest_address {
291 Arc::make_mut(&mut result).latest_address = right.latest_address;
292 }
293 Some(result)
294 }
295
296 #[cfg(debug_assertions)]
300 fn covers(&self, covered: &Self) -> bool {
301 if self.len < covered.len {
302 return false;
303 }
304 let mut covers = true;
305 covered.root.for_each_owner(&mut |owner| {
306 covers &= self.root.contains(Self::address(owner));
307 });
308 covers
309 }
310}
311
312#[cfg(target_pointer_width = "64")]
315const _: () = {
316 assert!(std::mem::size_of::<OwnerNode>() == 2 * std::mem::size_of::<usize>());
317 assert!(std::mem::size_of::<OwnerBranch>() == 5 * std::mem::size_of::<usize>());
318 assert!(std::mem::size_of::<OwnerCover>() == 4 * std::mem::size_of::<usize>());
319};
320
321#[derive(Clone, Debug, Default)]
327pub(crate) struct PATCHOwnerGuard(Option<Arc<OwnerCover>>);
328
329impl PATCHOwnerGuard {
330 pub(crate) fn join(self, other: Self) -> Self {
332 Self(OwnerCover::union(self.0, &other.0))
333 }
334
335 pub(crate) fn retain_archive_owner(&mut self, owner: &Arc<dyn ArchiveOwner>) {
337 OwnerCover::retain(&mut self.0, owner);
338 }
339
340 #[cfg(debug_assertions)]
341 fn covers(&self, current: &Option<Arc<OwnerCover>>) -> bool {
342 let Some(current) = current else {
343 return true;
344 };
345 let Some(replacement) = self.0.as_ref() else {
346 return false;
347 };
348 Arc::ptr_eq(current, replacement) || replacement.covers(current)
349 }
350
351 #[cfg(test)]
352 pub(crate) fn ptr_eq(&self, other: &Self) -> bool {
353 match (&self.0, &other.0) {
354 (None, None) => true,
355 (Some(left), Some(right)) => Arc::ptr_eq(left, right),
356 _ => false,
357 }
358 }
359
360 #[cfg(test)]
361 pub(crate) fn owner_count(&self) -> usize {
362 self.0.as_ref().map_or(0, |cover| cover.len)
363 }
364}
365
366#[cfg(not(target_pointer_width = "64"))]
367compile_error!("PATCH tagged pointers require 64-bit targets");
368
369struct HashKeys {
370 leaf: [u8; 16],
371 exported_fingerprint: [u8; 16],
372}
373
374static HASH_KEYS: OnceLock<HashKeys> = OnceLock::new();
375
376mod sealed {
377 pub trait Sealed {}
378}
379
380pub trait PatchHash: sealed::Sealed + Send + Sync + 'static {
387 type Digest: Copy + core::fmt::Debug + Eq + Send + Sync + 'static;
389
390 type BranchState;
392
393 const COMMUTATIVE_BRANCH: bool;
398
399 const INCREMENTAL_BRANCH: bool;
404
405 fn init();
407
408 fn leaf(bytes: &[u8]) -> Self::Digest;
410
411 fn begin_branch(
417 representative: &[u8],
418 tree_to_key: &[usize],
419 end_depth: usize,
420 child_count: usize,
421 leaf_count: u64,
422 ) -> Self::BranchState;
423
424 fn push_child(state: &mut Self::BranchState, edge: u8, leaf_count: u64, digest: Self::Digest);
426
427 fn finish_branch(state: Self::BranchState) -> Self::Digest;
429
430 fn edit_branch(
435 current: Self::Digest,
436 edge: u8,
437 old: Option<Self::Digest>,
438 new: Option<Self::Digest>,
439 ) -> Self::Digest;
440}
441
442#[derive(Clone, Copy, Debug, Default)]
448pub struct XorSip128;
449
450impl sealed::Sealed for XorSip128 {}
451
452impl PatchHash for XorSip128 {
453 type Digest = u128;
454 type BranchState = u128;
455 const COMMUTATIVE_BRANCH: bool = true;
456 const INCREMENTAL_BRANCH: bool = true;
457
458 #[inline]
459 fn init() {
460 init_hash_keys();
461 }
462
463 #[inline]
464 fn leaf(bytes: &[u8]) -> Self::Digest {
465 xor_hash_leaf_bytes(bytes)
466 }
467
468 #[inline]
469 fn begin_branch(
470 _representative: &[u8],
471 _tree_to_key: &[usize],
472 _end_depth: usize,
473 _child_count: usize,
474 _leaf_count: u64,
475 ) -> Self::BranchState {
476 0
477 }
478
479 #[inline]
480 fn push_child(
481 state: &mut Self::BranchState,
482 _edge: u8,
483 _leaf_count: u64,
484 digest: Self::Digest,
485 ) {
486 *state ^= digest;
487 }
488
489 #[inline]
490 fn finish_branch(state: Self::BranchState) -> Self::Digest {
491 state
492 }
493
494 #[inline]
495 fn edit_branch(
496 mut current: Self::Digest,
497 _edge: u8,
498 old: Option<Self::Digest>,
499 new: Option<Self::Digest>,
500 ) -> Self::Digest {
501 if let Some(old) = old {
502 current ^= old;
503 }
504 if let Some(new) = new {
505 current ^= new;
506 }
507 current
508 }
509}
510
511#[derive(Clone, Copy, Debug, Default)]
526pub struct Blake3Merkle;
527
528impl sealed::Sealed for Blake3Merkle {}
529
530impl PatchHash for Blake3Merkle {
531 type Digest = [u8; 32];
532 type BranchState = blake3::Hasher;
533 const COMMUTATIVE_BRANCH: bool = false;
534 const INCREMENTAL_BRANCH: bool = false;
535
536 #[inline]
537 fn init() {
538 bytetable::init();
539 }
540
541 fn leaf(bytes: &[u8]) -> Self::Digest {
542 let mut state = blake3::Hasher::new();
543 state.update(b"triblespace.patch.leaf.v1\0");
544 state.update(&(bytes.len() as u64).to_le_bytes());
545 state.update(bytes);
546 *state.finalize().as_bytes()
547 }
548
549 fn begin_branch(
550 representative: &[u8],
551 tree_to_key: &[usize],
552 end_depth: usize,
553 child_count: usize,
554 leaf_count: u64,
555 ) -> Self::BranchState {
556 debug_assert_eq!(representative.len(), tree_to_key.len());
557 debug_assert!(end_depth <= representative.len());
558 let mut state = blake3::Hasher::new();
559 state.update(b"triblespace.patch.branch.v2\0");
560 state.update(&(representative.len() as u64).to_le_bytes());
561 state.update(&(end_depth as u64).to_le_bytes());
562 for &key_index in &tree_to_key[..end_depth] {
563 state.update(&[representative[key_index]]);
564 }
565 state.update(&(child_count as u64).to_le_bytes());
566 state.update(&leaf_count.to_le_bytes());
567 state
568 }
569
570 #[inline]
571 fn push_child(state: &mut Self::BranchState, edge: u8, leaf_count: u64, digest: Self::Digest) {
572 state.update(&[edge]);
573 state.update(&leaf_count.to_le_bytes());
574 state.update(&digest);
575 }
576
577 #[inline]
578 fn finish_branch(state: Self::BranchState) -> Self::Digest {
579 *state.finalize().as_bytes()
580 }
581
582 #[inline]
583 fn edit_branch(
584 _current: Self::Digest,
585 _edge: u8,
586 _old: Option<Self::Digest>,
587 _new: Option<Self::Digest>,
588 ) -> Self::Digest {
589 unreachable!("non-incremental PATCH hash policy was asked to edit a branch")
590 }
591}
592
593const EXPORTED_FINGERPRINT_DOMAIN: [u8; 16] = *b"TribleSet.fp.v1\0";
601
602#[cfg(feature = "parallel")]
607const PARALLEL_PATCH_UNION_THRESHOLD: usize = 4096;
608
609#[cfg(feature = "parallel")]
629mod parallel_union {
630 use core::sync::atomic::{AtomicUsize, Ordering};
631
632 pub(crate) struct ParUnionCtx {
635 pub(crate) budget: AtomicUsize,
636 }
637
638 impl ParUnionCtx {
639 pub(crate) fn new() -> Self {
640 let n = rayon::current_num_threads();
641 Self {
642 budget: AtomicUsize::new(n.saturating_mul(n).max(2)),
643 }
644 }
645
646 pub(crate) fn try_claim(&self) -> bool {
655 let mut current = self.budget.load(Ordering::Relaxed);
656 loop {
657 if current == 0 {
658 return false;
659 }
660 match self.budget.compare_exchange_weak(
661 current,
662 current - 1,
663 Ordering::Relaxed,
664 Ordering::Relaxed,
665 ) {
666 Ok(_) => return true,
667 Err(observed) => current = observed,
668 }
669 }
670 }
671 }
672
673 pub(crate) struct ScatterPtr<T>(pub *mut T);
686
687 impl<T> Clone for ScatterPtr<T> {
691 fn clone(&self) -> Self {
692 *self
693 }
694 }
695 impl<T> Copy for ScatterPtr<T> {}
696
697 unsafe impl<T: Send> Send for ScatterPtr<T> {}
701 unsafe impl<T: Send> Sync for ScatterPtr<T> {}
702
703 impl<T> ScatterPtr<T> {
704 pub(crate) unsafe fn write_at(self, i: usize, v: T) {
708 self.0.add(i).write(v);
709 }
710 }
711}
712
713fn hash_keys() -> &'static HashKeys {
716 HASH_KEYS.get_or_init(|| {
717 bytetable::init();
718
719 let mut rng = thread_rng();
720 let mut leaf = [0u8; 16];
721 let mut exported_fingerprint = [0u8; 16];
722 rng.fill_bytes(&mut leaf);
723 loop {
726 rng.fill_bytes(&mut exported_fingerprint);
727 if exported_fingerprint != leaf {
728 break;
729 }
730 }
731 HashKeys {
732 leaf,
733 exported_fingerprint,
734 }
735 })
736}
737
738pub(crate) fn init_hash_keys() {
744 let _ = hash_keys();
745}
746
747#[inline]
749fn xor_hash_leaf_bytes(bytes: &[u8]) -> u128 {
750 use siphasher::sip128::SipHasher24;
751
752 SipHasher24::new_with_key(&hash_keys().leaf)
753 .hash(bytes)
754 .into()
755}
756
757#[inline]
763fn blind_root_hash_with_key(root_hash: u128, key: &[u8; 16]) -> u128 {
764 use siphasher::sip128::SipHasher24;
765
766 let mut input = [0u8; 32];
767 input[..16].copy_from_slice(&EXPORTED_FINGERPRINT_DOMAIN);
768 input[16..].copy_from_slice(&root_hash.to_le_bytes());
769 SipHasher24::new_with_key(key).hash(&input).into()
770}
771
772#[inline]
780pub(crate) fn blind_root_hash(root_hash: Option<u128>) -> Option<u128> {
781 let root_hash = root_hash?;
782 Some(blind_root_hash_with_key(
783 root_hash,
784 &hash_keys().exported_fingerprint,
785 ))
786}
787
788#[cfg(any(test, feature = "parallel"))]
794#[inline]
795pub(crate) fn hash_key(bytes: &[u8]) -> u128 {
796 XorSip128::leaf(bytes)
797}
798
799pub const fn build_segmentation<const N: usize, const M: usize>(lens: [usize; M]) -> [usize; N] {
803 let mut res = [0; N];
804 let mut seg = 0;
805 let mut off = 0;
806 while seg < M {
807 let len = lens[seg];
808 let mut i = 0;
809 while i < len {
810 res[off + i] = seg;
811 i += 1;
812 }
813 off += len;
814 seg += 1;
815 }
816 res
817}
818
819pub const fn identity_map<const N: usize>() -> [usize; N] {
821 let mut res = [0; N];
822 let mut i = 0;
823 while i < N {
824 res[i] = i;
825 i += 1;
826 }
827 res
828}
829
830pub const fn build_key_to_tree<const N: usize, const M: usize>(
835 lens: [usize; M],
836 perm: [usize; M],
837) -> [usize; N] {
838 let mut key_starts = [0; M];
839 let mut off = 0;
840 let mut i = 0;
841 while i < M {
842 key_starts[i] = off;
843 off += lens[i];
844 i += 1;
845 }
846
847 let mut tree_starts = [0; M];
848 off = 0;
849 i = 0;
850 while i < M {
851 let seg = perm[i];
852 tree_starts[seg] = off;
853 off += lens[seg];
854 i += 1;
855 }
856
857 let mut res = [0; N];
858 let mut seg = 0;
859 while seg < M {
860 let len = lens[seg];
861 let ks = key_starts[seg];
862 let ts = tree_starts[seg];
863 let mut j = 0;
864 while j < len {
865 res[ks + j] = ts + j;
866 j += 1;
867 }
868 seg += 1;
869 }
870 res
871}
872
873pub const fn invert<const N: usize>(arr: [usize; N]) -> [usize; N] {
875 let mut res = [0; N];
876 let mut i = 0;
877 while i < N {
878 res[arr[i]] = i;
879 i += 1;
880 }
881 res
882}
883
884pub const fn build_segment_ends<const N: usize>(
892 segments: [usize; N],
893 tree_to_key: [usize; N],
894) -> [usize; N] {
895 let mut ends = [0usize; N];
896 let mut d = 0;
897 while d < N {
898 let seg = segments[tree_to_key[d]];
899 let mut e = d + 1;
900 while e < N && segments[tree_to_key[e]] == seg {
901 e += 1;
902 }
903 ends[d] = e;
904 d += 1;
905 }
906 ends
907}
908
909#[doc(hidden)]
910#[macro_export]
911macro_rules! key_segmentation {
912 (@count $($e:expr),* $(,)?) => {
913 <[()]>::len(&[$($crate::key_segmentation!(@sub $e)),*])
914 };
915 (@sub $e:expr) => { () };
916 ($(#[$meta:meta])* $name:ident, $len:expr, [$($seg_len:expr),+ $(,)?]) => {
917 $(#[$meta])*
918 #[derive(Copy, Clone, Debug)]
919 pub struct $name;
920 impl $name {
921 pub const SEG_LENS: [usize; $crate::key_segmentation!(@count $($seg_len),*)] = [$($seg_len),*];
922 }
923 impl $crate::patch::KeySegmentation<$len> for $name {
924 const SEGMENTS: [usize; $len] = $crate::patch::build_segmentation::<$len, {$crate::key_segmentation!(@count $($seg_len),*)}>(Self::SEG_LENS);
925 }
926 };
927}
928
929#[doc(hidden)]
930#[macro_export]
931macro_rules! key_schema {
932 (@count $($e:expr),* $(,)?) => {
933 <[()]>::len(&[$($crate::key_schema!(@sub $e)),*])
934 };
935 (@sub $e:expr) => { () };
936 ($(#[$meta:meta])* $name:ident, $seg:ty, $len:expr, [$($perm:expr),+ $(,)?]) => {
937 $(#[$meta])*
938 #[derive(Copy, Clone, Debug)]
939 pub struct $name;
940 impl $crate::patch::KeySchema<$len> for $name {
941 type Segmentation = $seg;
942 const SEGMENT_PERM: &'static [usize] = &[$($perm),*];
943 const KEY_TO_TREE: [usize; $len] = $crate::patch::build_key_to_tree::<$len, {$crate::key_schema!(@count $($perm),*)}>(<$seg>::SEG_LENS, [$($perm),*]);
944 const TREE_TO_KEY: [usize; $len] = $crate::patch::invert(Self::KEY_TO_TREE);
945 }
946 };
947}
948
949pub trait KeySchema<const KEY_LEN: usize>: Copy + Clone + Debug {
953 type Segmentation: KeySegmentation<KEY_LEN>;
955 const SEGMENT_PERM: &'static [usize];
957 const KEY_TO_TREE: [usize; KEY_LEN];
959 const TREE_TO_KEY: [usize; KEY_LEN];
961
962 const SEGMENT_ENDS: [usize; KEY_LEN] = build_segment_ends::<KEY_LEN>(
970 <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS,
971 Self::TREE_TO_KEY,
972 );
973
974 fn next_boundary(tree_depth: usize) -> usize {
980 Self::SEGMENT_ENDS[tree_depth]
981 }
982
983 fn tree_ordered(key: &[u8; KEY_LEN]) -> [u8; KEY_LEN] {
985 let mut new_key = [0; KEY_LEN];
986 let mut i = 0;
987 while i < KEY_LEN {
988 new_key[Self::KEY_TO_TREE[i]] = key[i];
989 i += 1;
990 }
991 new_key
992 }
993
994 fn key_ordered(tree_key: &[u8; KEY_LEN]) -> [u8; KEY_LEN] {
996 let mut new_key = [0; KEY_LEN];
997 let mut i = 0;
998 while i < KEY_LEN {
999 new_key[Self::TREE_TO_KEY[i]] = tree_key[i];
1000 i += 1;
1001 }
1002 new_key
1003 }
1004
1005 fn segment_of_tree_depth(at_depth: usize) -> usize {
1011 <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[at_depth]]
1012 }
1013
1014 fn same_segment_tree(a: usize, b: usize) -> bool {
1017 <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[a]]
1018 == <Self::Segmentation as KeySegmentation<KEY_LEN>>::SEGMENTS[Self::TREE_TO_KEY[b]]
1019 }
1020}
1021
1022pub trait KeySegmentation<const KEY_LEN: usize>: Copy + Clone + Debug {
1033 const SEGMENTS: [usize; KEY_LEN];
1035}
1036
1037#[derive(Copy, Clone, Debug)]
1041pub struct IdentitySchema {}
1042
1043#[derive(Copy, Clone, Debug)]
1047pub struct SingleSegmentation {}
1048impl<const KEY_LEN: usize> KeySchema<KEY_LEN> for IdentitySchema {
1049 type Segmentation = SingleSegmentation;
1050 const SEGMENT_PERM: &'static [usize] = &[0];
1051 const KEY_TO_TREE: [usize; KEY_LEN] = identity_map::<KEY_LEN>();
1052 const TREE_TO_KEY: [usize; KEY_LEN] = identity_map::<KEY_LEN>();
1053}
1054
1055impl<const KEY_LEN: usize> KeySegmentation<KEY_LEN> for SingleSegmentation {
1056 const SEGMENTS: [usize; KEY_LEN] = [0; KEY_LEN];
1057}
1058
1059#[allow(dead_code)]
1060#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
1061#[repr(u8)]
1062pub(crate) enum HeadTag {
1063 Leaf = 0,
1078 Branch2 = 1,
1079 Branch4 = 2,
1080 Branch8 = 3,
1081 Branch16 = 4,
1082 Branch32 = 5,
1083 Branch64 = 6,
1084 Branch128 = 7,
1085 Branch256 = 8,
1086 LocalLeaf = 9,
1087}
1088
1089impl HeadTag {
1090 #[inline]
1091 fn from_raw(raw: u8) -> Self {
1092 debug_assert!(raw <= HeadTag::LocalLeaf as u8);
1093 unsafe { std::mem::transmute(raw) }
1097 }
1098}
1099
1100pub(crate) enum BodyPtr<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> {
1101 Leaf(NonNull<Leaf<KEY_LEN, V, H>>),
1102 LocalLeaf(NonNull<[u8; KEY_LEN]>),
1106 Branch(branch::BranchNN<KEY_LEN, O, V, H>),
1107}
1108
1109pub(crate) enum BodyRef<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> {
1112 Leaf(&'a Leaf<KEY_LEN, V, H>),
1113 LocalLeaf(&'a [u8; KEY_LEN]),
1117 Branch(&'a Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V, H>>], V, H>),
1118}
1119
1120pub(crate) enum BodyMut<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> {
1127 Leaf(&'a Leaf<KEY_LEN, V, H>),
1128 LocalLeaf(&'a [u8; KEY_LEN]),
1133 Branch(&'a mut Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V, H>>], V, H>),
1134}
1135
1136pub(crate) trait Body {
1137 fn tag(body: NonNull<Self>) -> HeadTag;
1138}
1139
1140#[repr(C)]
1141pub(crate) struct Head<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash = XorSip128> {
1142 tptr: std::ptr::NonNull<u8>,
1143 key_ordering: PhantomData<O>,
1144 key_segments: PhantomData<O::Segmentation>,
1145 value: PhantomData<V>,
1146 hash_policy: PhantomData<H>,
1147}
1148
1149unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V: Send + Sync, H: PatchHash> Send
1156 for Head<KEY_LEN, O, V, H>
1157{
1158}
1159
1160unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V: Send + Sync, H: PatchHash> Sync
1162 for Head<KEY_LEN, O, V, H>
1163{
1164}
1165
1166impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Head<KEY_LEN, O, V, H> {
1167 const TAG_MASK: u64 = 0x0f;
1172 const BODY_MASK: u64 = 0x00_ff_ff_ff_ff_ff_ff_f0;
1173 const KEY_MASK: u64 = 0xff_00_00_00_00_00_00_00;
1174
1175 pub(crate) fn new<T: Body + ?Sized>(key: u8, body: NonNull<T>) -> Self {
1176 unsafe {
1177 let tptr =
1178 std::ptr::NonNull::new_unchecked((body.as_ptr() as *mut u8).map_addr(|addr| {
1179 debug_assert_eq!(addr as u64 & Self::TAG_MASK, 0);
1180 ((addr as u64 & Self::BODY_MASK)
1181 | ((key as u64) << 56)
1182 | (<T as Body>::tag(body) as u64)) as usize
1183 }));
1184 Self {
1185 tptr,
1186 key_ordering: PhantomData,
1187 key_segments: PhantomData,
1188 value: PhantomData,
1189 hash_policy: PhantomData,
1190 }
1191 }
1192 }
1193
1194 pub(crate) unsafe fn new_local_leaf(key: u8, trible_ptr: NonNull<[u8; KEY_LEN]>) -> Self {
1212 unsafe {
1213 let tptr = std::ptr::NonNull::new_unchecked((trible_ptr.as_ptr() as *mut u8).map_addr(
1214 |addr| {
1215 debug_assert_eq!(
1216 addr as u64 & Self::TAG_MASK,
1217 0,
1218 "LocalLeaf trible pointer must be 16-byte aligned"
1219 );
1220 ((addr as u64 & Self::BODY_MASK)
1221 | ((key as u64) << 56)
1222 | (HeadTag::LocalLeaf as u64)) as usize
1223 },
1224 ));
1225 Self {
1226 tptr,
1227 key_ordering: PhantomData,
1228 key_segments: PhantomData,
1229 value: PhantomData,
1230 hash_policy: PhantomData,
1231 }
1232 }
1233 }
1234
1235 #[inline]
1236 pub(crate) fn tag(&self) -> HeadTag {
1237 HeadTag::from_raw((self.tptr.as_ptr() as u64 & Self::TAG_MASK) as u8)
1238 }
1239
1240 #[inline]
1241 pub(crate) fn key(&self) -> u8 {
1242 (self.tptr.as_ptr() as u64 >> 56) as u8
1243 }
1244
1245 #[inline]
1246 pub(crate) fn with_key(mut self, key: u8) -> Self {
1247 self.tptr =
1248 std::ptr::NonNull::new(self.tptr.as_ptr().map_addr(|addr| {
1249 ((addr as u64 & !Self::KEY_MASK) | ((key as u64) << 56)) as usize
1250 }))
1251 .unwrap();
1252 self
1253 }
1254
1255 #[inline]
1256 pub(crate) fn set_body<T: Body + ?Sized>(&mut self, body: NonNull<T>) {
1257 unsafe {
1258 self.tptr = NonNull::new_unchecked((body.as_ptr() as *mut u8).map_addr(|addr| {
1259 debug_assert_eq!(addr as u64 & Self::TAG_MASK, 0);
1260 ((addr as u64 & Self::BODY_MASK)
1261 | (self.tptr.as_ptr() as u64 & Self::KEY_MASK)
1262 | (<T as Body>::tag(body) as u64)) as usize
1263 }))
1264 }
1265 }
1266
1267 pub(crate) fn with_start(self, new_start_depth: usize) -> Head<KEY_LEN, O, V, H> {
1268 let leaf_key = self.childleaf_key();
1269 let i = O::TREE_TO_KEY[new_start_depth];
1270 let key = leaf_key[i];
1271 self.with_key(key)
1272 }
1273
1274 pub(crate) fn body(&self) -> BodyPtr<KEY_LEN, O, V, H> {
1280 unsafe {
1281 let ptr = NonNull::new_unchecked(self.tptr.as_ptr().map_addr(|addr| {
1282 let masked = (addr as u64) & Self::BODY_MASK;
1283 masked as usize
1284 }));
1285 match self.tag() {
1286 HeadTag::Leaf => BodyPtr::Leaf(ptr.cast()),
1287 HeadTag::LocalLeaf => BodyPtr::LocalLeaf(ptr.cast()),
1288 branch_tag => {
1289 let count = 1 << (branch_tag as usize);
1290 BodyPtr::Branch(NonNull::new_unchecked(std::ptr::slice_from_raw_parts(
1291 ptr.as_ptr(),
1292 count,
1293 )
1294 as *mut Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V, H>>], V, H>))
1295 }
1296 }
1297 }
1298 }
1299
1300 pub(crate) fn body_mut(&mut self) -> BodyMut<'_, KEY_LEN, O, V, H> {
1301 unsafe {
1302 match self.body() {
1303 BodyPtr::Leaf(leaf) => BodyMut::Leaf(leaf.as_ref()),
1304 BodyPtr::LocalLeaf(ptr) => BodyMut::LocalLeaf(ptr.as_ref()),
1305 BodyPtr::Branch(mut branch) => {
1306 let mut branch_nn = branch;
1308 if Branch::rc_cow(&mut branch_nn).is_some() {
1309 self.set_body(branch_nn);
1310 BodyMut::Branch(branch_nn.as_mut())
1311 } else {
1312 BodyMut::Branch(branch.as_mut())
1313 }
1314 }
1315 }
1316 }
1317 }
1318
1319 pub(crate) fn body_ref(&self) -> BodyRef<'_, KEY_LEN, O, V, H> {
1322 match self.body() {
1323 BodyPtr::Leaf(nn) => BodyRef::Leaf(unsafe { nn.as_ref() }),
1324 BodyPtr::LocalLeaf(nn) => BodyRef::LocalLeaf(unsafe { nn.as_ref() }),
1325 BodyPtr::Branch(nn) => BodyRef::Branch(unsafe { nn.as_ref() }),
1326 }
1327 }
1328
1329 pub(crate) fn count(&self) -> u64 {
1330 match self.body_ref() {
1331 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => 1,
1332 BodyRef::Branch(branch) => branch.leaf_count,
1333 }
1334 }
1335
1336 #[inline]
1337 fn is_archive_singleton_pair(&self, other: &Self) -> bool {
1338 matches!(
1339 (self.tag(), other.tag()),
1340 (HeadTag::LocalLeaf, HeadTag::Leaf | HeadTag::LocalLeaf)
1341 | (HeadTag::Leaf, HeadTag::LocalLeaf)
1342 )
1343 }
1344
1345 #[inline]
1350 fn local_leaf_cardinality_allows_equality(&self, other: &Self) -> bool {
1351 match (self.tag(), other.tag()) {
1352 (HeadTag::LocalLeaf, _) => other.count() == 1,
1353 (_, HeadTag::LocalLeaf) => self.count() == 1,
1354 _ => true,
1355 }
1356 }
1357
1358 pub(crate) fn count_segment(&self, at_depth: usize) -> u64 {
1359 match self.body_ref() {
1360 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => 1,
1361 BodyRef::Branch(branch) => branch.count_segment(at_depth),
1362 }
1363 }
1364
1365 pub(crate) fn hash(&self) -> H::Digest {
1366 match self.body_ref() {
1367 BodyRef::Leaf(leaf) => leaf.hash,
1368 BodyRef::LocalLeaf(bytes) => H::leaf(&bytes[..]),
1369 BodyRef::Branch(branch) => branch.hash,
1370 }
1371 }
1372
1373 pub(crate) fn end_depth(&self) -> usize {
1374 match self.body_ref() {
1375 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => KEY_LEN,
1376 BodyRef::Branch(branch) => branch.end_depth as usize,
1377 }
1378 }
1379
1380 pub(crate) fn childleaf_ptr(&self) -> *const [u8; KEY_LEN] {
1386 match self.body_ref() {
1387 BodyRef::Leaf(leaf) => &leaf.key as *const [u8; KEY_LEN],
1388 BodyRef::LocalLeaf(bytes) => bytes as *const [u8; KEY_LEN],
1389 BodyRef::Branch(branch) => branch.childleaf_ptr(),
1390 }
1391 }
1392
1393 pub(crate) fn childleaf_key(&self) -> &[u8; KEY_LEN] {
1394 match self.body_ref() {
1395 BodyRef::Leaf(leaf) => &leaf.key,
1396 BodyRef::LocalLeaf(bytes) => bytes,
1397 BodyRef::Branch(branch) => branch.childleaf_key(),
1398 }
1399 }
1400
1401 pub(crate) fn first_divergence(
1410 &self,
1411 other: &Self,
1412 start_depth: usize,
1413 ) -> Option<(usize, u8, u8)> {
1414 let limit = std::cmp::min(std::cmp::min(self.end_depth(), other.end_depth()), KEY_LEN);
1415 debug_assert!(limit <= KEY_LEN);
1416 let this_key = self.childleaf_key();
1417 let other_key = other.childleaf_key();
1418 let mut depth = start_depth;
1419 while depth < limit {
1420 let i = O::TREE_TO_KEY[depth];
1421 let a = this_key[i];
1422 let b = other_key[i];
1423 if a != b {
1424 return Some((depth, a, b));
1425 }
1426 depth += 1;
1427 }
1428 None
1429 }
1430
1431 #[must_use = "drop the retired heap leaf only after the replacement root is committed"]
1449 pub(crate) fn remove_leaf(
1450 slot: &mut Option<Self>,
1451 leaf_key: &[u8; KEY_LEN],
1452 start_depth: usize,
1453 ) -> Option<Self> {
1454 if let Some(this) = slot {
1455 let end_depth = std::cmp::min(this.end_depth(), KEY_LEN);
1456 if !this.has_prefix::<KEY_LEN>(start_depth, leaf_key) {
1460 return None;
1461 }
1462 match this.tag() {
1463 HeadTag::Leaf => {
1464 slot.take()
1467 }
1468 HeadTag::LocalLeaf => {
1469 drop(slot.take());
1473 None
1474 }
1475 _ => {
1476 let mut retired_leaf = None;
1477 let mut ed = crate::patch::branch::BranchMut::from_head(this);
1478 let key = leaf_key[end_depth];
1479 ed.modify_child(key, |mut opt| {
1480 retired_leaf = Self::remove_leaf(&mut opt, leaf_key, end_depth);
1481 opt
1482 });
1483
1484 let occupied_children = ed.child_table.iter().flatten().take(2).count();
1490 if occupied_children == 0 {
1491 drop(ed);
1492 drop(slot.take());
1493 } else if occupied_children == 1 {
1494 let mut remaining: Option<Head<KEY_LEN, O, V, H>> = None;
1495 for slot_child in &mut ed.child_table {
1496 if let Some(child) = slot_child.take() {
1497 remaining = Some(child.with_start(start_depth));
1498 break;
1499 }
1500 }
1501 drop(ed);
1502 if let Some(child) = remaining {
1503 slot.replace(child);
1504 }
1505 } else {
1506 drop(ed);
1509 }
1510 retired_leaf
1511 }
1512 }
1513 } else {
1514 None
1515 }
1516 }
1517
1518 pub(crate) fn insert_leaf(mut this: Self, leaf: Self, start_depth: usize) -> Self {
1528 if let Some((depth, this_byte_key, leaf_byte_key)) =
1529 this.first_divergence(&leaf, start_depth)
1530 {
1531 let old_key = this.key();
1532 let new_body = crate::patch::branch::Branch::new(
1533 depth,
1534 this.with_key(this_byte_key),
1535 leaf.with_key(leaf_byte_key),
1536 );
1537 return Head::new(old_key, new_body);
1538 }
1539
1540 let end_depth = this.end_depth();
1541 if end_depth != KEY_LEN {
1542 let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
1543 let inserted = leaf.with_start(ed.end_depth as usize);
1544 let key = inserted.key();
1545 ed.modify_child(key, |opt| match opt {
1546 Some(old) => Some(Head::insert_leaf(old, inserted, end_depth)),
1547 None => Some(inserted),
1548 });
1549 }
1550 this
1551 }
1552}
1553
1554impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, H: PatchHash> Head<KEY_LEN, O, (), H> {
1556 pub(crate) fn insert_archive_leaf(
1560 mut this: Self,
1561 leaf: Self,
1562 leaf_hash: H::Digest,
1563 start_depth: usize,
1564 ) -> Self {
1565 if let Some((depth, this_byte_key, leaf_byte_key)) =
1566 this.first_divergence(&leaf, start_depth)
1567 {
1568 let old_key = this.key();
1569 let new_body = crate::patch::branch::Branch::new_with_rchild_hash(
1570 depth,
1571 this.with_key(this_byte_key),
1572 leaf.with_key(leaf_byte_key),
1573 leaf_hash,
1574 );
1575 return Head::new(old_key, new_body);
1576 }
1577
1578 let end_depth = this.end_depth();
1579 if end_depth != KEY_LEN {
1580 let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
1581 let inserted = leaf.with_start(ed.end_depth as usize);
1582 let key = inserted.key();
1583 ed.modify_child_with_inserted_hint(key, leaf_hash, |opt| match opt {
1584 None => Some(inserted),
1585 Some(old) => Some(Head::insert_archive_leaf(
1586 old, inserted, leaf_hash, end_depth,
1587 )),
1588 });
1589 }
1590 this
1591 }
1592}
1593
1594impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Head<KEY_LEN, O, V, H> {
1598 pub(crate) fn replace_leaf(
1605 mut this: Self,
1606 leaf: Self,
1607 start_depth: usize,
1608 ) -> (Self, Option<Self>) {
1609 if let Some((depth, this_byte_key, leaf_byte_key)) =
1610 this.first_divergence(&leaf, start_depth)
1611 {
1612 let old_key = this.key();
1613 let new_body = Branch::new(
1614 depth,
1615 this.with_key(this_byte_key),
1616 leaf.with_key(leaf_byte_key),
1617 );
1618
1619 return (Head::new(old_key, new_body), None);
1620 }
1621
1622 let end_depth = this.end_depth();
1623 if end_depth == KEY_LEN {
1624 let old_key = this.key();
1625 return (leaf.with_key(old_key), Some(this));
1626 } else {
1627 let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
1629 let inserted = leaf.with_start(ed.end_depth as usize);
1630 let key = inserted.key();
1631 let mut retired = None;
1632 ed.modify_child(key, |opt| match opt {
1633 Some(old) => {
1634 let (replacement, old_leaf) = Head::replace_leaf(old, inserted, end_depth);
1635 retired = old_leaf;
1636 Some(replacement)
1637 }
1638 None => Some(inserted),
1639 });
1640 drop(ed);
1641 return (this, retired);
1642 }
1643 }
1644
1645 pub(crate) fn union(mut this: Self, mut other: Self, at_depth: usize) -> Self {
1649 if this.is_archive_singleton_pair(&other) {
1653 if let Some((depth, this_byte_key, other_byte_key)) =
1654 this.first_divergence(&other, at_depth)
1655 {
1656 let this_hash = this.hash();
1657 let other_hash = other.hash();
1658 let old_key = this.key();
1659 let new_body = Branch::new_with_child_hashes(
1660 depth,
1661 this.with_key(this_byte_key),
1662 other.with_key(other_byte_key),
1663 this_hash,
1664 other_hash,
1665 );
1666 return Head::new(old_key, new_body);
1667 }
1668 return this;
1669 }
1670
1671 if this.local_leaf_cardinality_allows_equality(&other) && this.hash() == other.hash() {
1672 return this;
1673 }
1674
1675 if let Some((depth, this_byte_key, other_byte_key)) =
1676 this.first_divergence(&other, at_depth)
1677 {
1678 let old_key = this.key();
1679 let new_body = Branch::new(
1680 depth,
1681 this.with_key(this_byte_key),
1682 other.with_key(other_byte_key),
1683 );
1684
1685 return Head::new(old_key, new_body);
1686 }
1687
1688 let this_depth = this.end_depth();
1689 let other_depth = other.end_depth();
1690 if this_depth < other_depth {
1691 let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
1692 let inserted = other.with_start(ed.end_depth as usize);
1693 let key = inserted.key();
1694 ed.modify_child(key, |opt| match opt {
1695 Some(old) => Some(Head::union(old, inserted, this_depth)),
1696 None => Some(inserted),
1697 });
1698 drop(ed);
1699 return this;
1700 }
1701
1702 if other_depth < this_depth {
1703 let old_key = this.key();
1704 let this_head = this;
1705 let mut ed = crate::patch::branch::BranchMut::from_head(&mut other);
1706 let inserted = this_head.with_start(ed.end_depth as usize);
1707 let key = inserted.key();
1708 ed.modify_child(key, |opt| match opt {
1709 Some(old) => Some(Head::union(old, inserted, other_depth)),
1710 None => Some(inserted),
1711 });
1712 drop(ed);
1713 return other.with_key(old_key);
1714 }
1715
1716 if other.tag() > this.tag() {
1728 std::mem::swap(&mut this, &mut other);
1729 }
1730 let BodyMut::Branch(other_branch_ref) = other.body_mut() else {
1731 unreachable!();
1732 };
1733 let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
1734 for other_child in other_branch_ref
1735 .child_table
1736 .iter_mut()
1737 .filter_map(Option::take)
1738 {
1739 let inserted = other_child.with_start(ed.end_depth as usize);
1740 let key = inserted.key();
1741 ed.modify_child(key, |opt| match opt {
1742 Some(old) => Some(Head::union(old, inserted, this_depth)),
1743 None => Some(inserted),
1744 });
1745 }
1746 drop(ed);
1747 this
1748 }
1749
1750 #[cfg(feature = "parallel")]
1757 pub(crate) fn par_union(this: Self, other: Self, at_depth: usize) -> Self
1758 where
1759 O: Send + Sync,
1760 V: Send + Sync,
1761 {
1762 let ctx = parallel_union::ParUnionCtx::new();
1763 Self::par_union_with_ctx(this, other, at_depth, &ctx)
1764 }
1765
1766 #[cfg(feature = "parallel")]
1773 pub(crate) fn par_union_with_ctx(
1774 mut this: Self,
1775 mut other: Self,
1776 at_depth: usize,
1777 ctx: ¶llel_union::ParUnionCtx,
1778 ) -> Self
1779 where
1780 O: Send + Sync,
1781 V: Send + Sync,
1782 {
1783 if this.is_archive_singleton_pair(&other) {
1785 return Self::union(this, other, at_depth);
1786 }
1787
1788 if this.local_leaf_cardinality_allows_equality(&other) && this.hash() == other.hash() {
1789 return this;
1790 }
1791
1792 if let Some((depth, this_byte_key, other_byte_key)) =
1793 this.first_divergence(&other, at_depth)
1794 {
1795 let old_key = this.key();
1796 let new_body = Branch::new(
1797 depth,
1798 this.with_key(this_byte_key),
1799 other.with_key(other_byte_key),
1800 );
1801 return Head::new(old_key, new_body);
1802 }
1803
1804 let this_depth = this.end_depth();
1805 let other_depth = other.end_depth();
1806 if this_depth != other_depth {
1807 return Self::union(this, other, at_depth);
1809 }
1810
1811 if other.tag() > this.tag() {
1820 std::mem::swap(&mut this, &mut other);
1821 }
1822
1823 let small = match other.body_ref() {
1827 BodyRef::Branch(b) => (b.leaf_count as usize) < PARALLEL_PATCH_UNION_THRESHOLD,
1828 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => unreachable!(),
1829 };
1830 if small {
1831 return Self::union(this, other, at_depth);
1832 }
1833
1834 let BodyMut::Branch(other_branch_ref) = other.body_mut() else {
1835 unreachable!();
1836 };
1837
1838 {
1839 let mut ed = crate::patch::branch::BranchMut::from_head(&mut this);
1840 let end_depth = ed.end_depth as usize;
1841
1842 let mut this_arr: [Option<Head<KEY_LEN, O, V, H>>; 256] = std::array::from_fn(|_| None);
1847 let mut other_arr: [Option<Head<KEY_LEN, O, V, H>>; 256] =
1848 std::array::from_fn(|_| None);
1849 let mut this_present = crate::patch::bytetable::ByteSet::new_empty();
1850 let mut other_present = crate::patch::bytetable::ByteSet::new_empty();
1851
1852 for slot in ed.child_table.iter_mut() {
1853 if let Some(head) = slot.take() {
1854 let key = head.key();
1855 this_present.insert(key);
1856 this_arr[key as usize] = Some(head);
1857 }
1858 }
1859 for slot in other_branch_ref.child_table.iter_mut() {
1860 if let Some(head) = slot.take() {
1861 let head = head.with_start(end_depth);
1862 let key = head.key();
1863 other_present.insert(key);
1864 other_arr[key as usize] = Some(head);
1865 }
1866 }
1867
1868 let mut both = this_present.intersect(&other_present);
1869 let mut only = this_present.symmetric_difference(&other_present);
1870
1871 let mut resolved: [Option<Head<KEY_LEN, O, V, H>>; 256] = std::array::from_fn(|_| None);
1876 let resolved_ptr = parallel_union::ScatterPtr(resolved.as_mut_ptr());
1877
1878 rayon::scope(|s| {
1879 while let Some(k) = both.drain_next_ascending() {
1885 let i = k as usize;
1886 let t = this_arr[i].take().expect("both ⇒ this");
1887 let o = other_arr[i].take().expect("both ⇒ other");
1888 if ctx.try_claim() {
1889 s.spawn(move |_| {
1890 let head = Self::par_union_with_ctx(t, o, this_depth, ctx);
1891 unsafe {
1895 resolved_ptr.write_at(i, Some(head));
1896 }
1897 });
1898 } else {
1899 let head = Self::union(t, o, this_depth);
1905 unsafe {
1906 resolved_ptr.write_at(i, Some(head));
1907 }
1908 }
1909 }
1910 });
1911 for slot in resolved.iter_mut() {
1916 if let Some(head) = slot.take() {
1917 ed.install_child_growing(head);
1918 }
1919 }
1920 while let Some(k) = only.drain_next_ascending() {
1921 let i = k as usize;
1922 let head = this_arr[i]
1923 .take()
1924 .or_else(|| other_arr[i].take())
1925 .expect("only ⇒ exactly one side");
1926 ed.install_child_growing(head);
1927 }
1928
1929 ed.recompute_aggregates();
1930 }
1931 this
1932 }
1933
1934 #[cfg(feature = "parallel")]
1941 pub(crate) fn par_intersect(&self, other: &Self, at_depth: usize) -> Option<Self>
1942 where
1943 O: Send + Sync,
1944 V: Send + Sync,
1945 {
1946 let ctx = parallel_union::ParUnionCtx::new();
1947 self.par_intersect_with_ctx(other, at_depth, &ctx)
1948 }
1949
1950 #[cfg(feature = "parallel")]
1957 pub(crate) fn par_intersect_with_ctx(
1958 &self,
1959 other: &Self,
1960 at_depth: usize,
1961 ctx: ¶llel_union::ParUnionCtx,
1962 ) -> Option<Self>
1963 where
1964 O: Send + Sync,
1965 V: Send + Sync,
1966 {
1967 if self.is_archive_singleton_pair(other) {
1968 return self.intersect(other, at_depth);
1969 }
1970 if self.local_leaf_cardinality_allows_equality(other) && self.hash() == other.hash() {
1971 return Some(self.clone());
1972 }
1973 if self.first_divergence(other, at_depth).is_some() {
1974 return None;
1975 }
1976 let self_depth = self.end_depth();
1977 let other_depth = other.end_depth();
1978 if self_depth != other_depth {
1979 return self.intersect(other, at_depth);
1980 }
1981
1982 let BodyRef::Branch(self_branch) = self.body_ref() else {
1983 unreachable!();
1984 };
1985 let BodyRef::Branch(other_branch) = other.body_ref() else {
1986 unreachable!();
1987 };
1988
1989 let min_leaves = self_branch.leaf_count.min(other_branch.leaf_count) as usize;
1992 if min_leaves < PARALLEL_PATCH_UNION_THRESHOLD {
1993 return self.intersect(other, at_depth);
1994 }
1995
1996 let mut resolved: [Option<Head<KEY_LEN, O, V, H>>; 256] = std::array::from_fn(|_| None);
1997 let resolved_ptr = parallel_union::ScatterPtr(resolved.as_mut_ptr());
1998
1999 rayon::in_place_scope(|s| {
2005 for slot in self_branch.child_table.iter() {
2006 let Some(self_child) = slot.as_ref() else {
2007 continue;
2008 };
2009 let key = self_child.key();
2010 let Some(other_child) = other_branch.child_table.table_get(key) else {
2011 continue;
2012 };
2013
2014 if ctx.try_claim() {
2015 s.spawn(move |_| {
2016 let result =
2017 self_child.par_intersect_with_ctx(other_child, self_depth, ctx);
2018 unsafe {
2020 resolved_ptr.write_at(key as usize, result);
2021 }
2022 });
2023 } else {
2024 let result = self_child.intersect(other_child, self_depth);
2025 unsafe {
2026 resolved_ptr.write_at(key as usize, result);
2027 }
2028 }
2029 }
2030 });
2031
2032 let mut iter = resolved.into_iter().flatten();
2040 let first = iter.next()?;
2041 let Some(second) = iter.next() else {
2042 return Some(first);
2043 };
2044 let new_branch = Branch::new(
2045 self_depth,
2046 first.with_start(self_depth),
2047 second.with_start(self_depth),
2048 );
2049 let mut head_for_branch = Head::new(0, new_branch);
2050 {
2051 let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
2052 for child in iter {
2053 let inserted = child.with_start(self_depth);
2054 let k = inserted.key();
2055 ed.modify_child(k, |_opt| Some(inserted));
2056 }
2057 }
2058 Some(head_for_branch)
2059 }
2060
2061 #[cfg(feature = "parallel")]
2065 pub(crate) fn par_difference(&self, other: &Self, at_depth: usize) -> Option<Self>
2066 where
2067 O: Send + Sync,
2068 V: Send + Sync,
2069 {
2070 let ctx = parallel_union::ParUnionCtx::new();
2071 self.par_difference_with_ctx(other, at_depth, &ctx)
2072 }
2073
2074 #[cfg(feature = "parallel")]
2079 pub(crate) fn par_difference_with_ctx(
2080 &self,
2081 other: &Self,
2082 at_depth: usize,
2083 ctx: ¶llel_union::ParUnionCtx,
2084 ) -> Option<Self>
2085 where
2086 O: Send + Sync,
2087 V: Send + Sync,
2088 {
2089 if self.is_archive_singleton_pair(other) {
2090 return self.difference(other, at_depth);
2091 }
2092 if self.local_leaf_cardinality_allows_equality(other) && self.hash() == other.hash() {
2093 return None;
2094 }
2095 if self.first_divergence(other, at_depth).is_some() {
2096 return Some(self.clone());
2097 }
2098 let self_depth = self.end_depth();
2099 let other_depth = other.end_depth();
2100 if self_depth != other_depth {
2101 return self.difference(other, at_depth);
2102 }
2103
2104 let BodyRef::Branch(self_branch) = self.body_ref() else {
2105 unreachable!();
2106 };
2107 let BodyRef::Branch(other_branch) = other.body_ref() else {
2108 unreachable!();
2109 };
2110
2111 if (self_branch.leaf_count as usize) < PARALLEL_PATCH_UNION_THRESHOLD {
2114 return self.difference(other, at_depth);
2115 }
2116
2117 let mut resolved: [Option<Head<KEY_LEN, O, V, H>>; 256] = std::array::from_fn(|_| None);
2118 let resolved_ptr = parallel_union::ScatterPtr(resolved.as_mut_ptr());
2119
2120 rayon::in_place_scope(|s| {
2123 for slot in self_branch.child_table.iter() {
2124 let Some(self_child) = slot.as_ref() else {
2125 continue;
2126 };
2127 let key = self_child.key();
2128
2129 match other_branch.child_table.table_get(key) {
2130 Some(other_child) => {
2131 if ctx.try_claim() {
2132 s.spawn(move |_| {
2133 let result = self_child.par_difference_with_ctx(
2134 other_child,
2135 self_depth,
2136 ctx,
2137 );
2138 unsafe {
2139 resolved_ptr.write_at(key as usize, result);
2140 }
2141 });
2142 } else {
2143 let result = self_child.difference(other_child, self_depth);
2144 unsafe {
2145 resolved_ptr.write_at(key as usize, result);
2146 }
2147 }
2148 }
2149 None => {
2150 let cloned = self_child.clone();
2154 unsafe {
2155 resolved_ptr.write_at(key as usize, Some(cloned));
2156 }
2157 }
2158 }
2159 }
2160 });
2161
2162 let mut iter = resolved.into_iter().flatten();
2171 let first = iter.next()?;
2172 let Some(second) = iter.next() else {
2173 return Some(first);
2174 };
2175 let new_branch = Branch::new(
2176 self_depth,
2177 first.with_start(self_depth),
2178 second.with_start(self_depth),
2179 );
2180 let mut head_for_branch = Head::new(0, new_branch);
2181 {
2182 let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
2183 for child in iter {
2184 ed.install_child_growing(child.with_start(self_depth));
2185 }
2186 ed.recompute_aggregates();
2187 }
2188 Some(head_for_branch)
2189 }
2190
2191 pub(crate) fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
2192 &self,
2193 prefix: &[u8; PREFIX_LEN],
2194 at_depth: usize,
2195 f: &mut F,
2196 ) where
2197 F: FnMut(&[u8; INFIX_LEN]),
2198 {
2199 match self.body_ref() {
2200 BodyRef::Leaf(leaf) => leaf.infixes::<PREFIX_LEN, INFIX_LEN, O, F>(prefix, at_depth, f),
2201 BodyRef::LocalLeaf(bytes) => {
2202 leaf::key_ops::infixes::<KEY_LEN, PREFIX_LEN, INFIX_LEN, O, F>(
2203 bytes, prefix, at_depth, f,
2204 )
2205 }
2206 BodyRef::Branch(branch) => {
2207 branch.infixes::<PREFIX_LEN, INFIX_LEN, F>(prefix, at_depth, f)
2208 }
2209 }
2210 }
2211
2212 pub(crate) fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
2213 &self,
2214 prefix: &[u8; PREFIX_LEN],
2215 at_depth: usize,
2216 min_infix: &[u8; INFIX_LEN],
2217 max_infix: &[u8; INFIX_LEN],
2218 f: &mut F,
2219 ) where
2220 F: FnMut(&[u8; INFIX_LEN]),
2221 {
2222 match self.body_ref() {
2223 BodyRef::Leaf(leaf) => leaf.infixes_range::<PREFIX_LEN, INFIX_LEN, O, F>(
2224 prefix, at_depth, min_infix, max_infix, f,
2225 ),
2226 BodyRef::LocalLeaf(bytes) => {
2227 leaf::key_ops::infixes_range::<KEY_LEN, PREFIX_LEN, INFIX_LEN, O, F>(
2228 bytes, prefix, at_depth, min_infix, max_infix, f,
2229 )
2230 }
2231 BodyRef::Branch(branch) => branch.infixes_range::<PREFIX_LEN, INFIX_LEN, F>(
2232 prefix, at_depth, min_infix, max_infix, f,
2233 ),
2234 }
2235 }
2236
2237 pub(crate) fn first_infix_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
2238 &self,
2239 prefix: &[u8; PREFIX_LEN],
2240 at_depth: usize,
2241 min_infix: &[u8; INFIX_LEN],
2242 max_infix: &[u8; INFIX_LEN],
2243 ) -> Option<[u8; INFIX_LEN]> {
2244 match self.body_ref() {
2245 BodyRef::Leaf(leaf) => leaf.first_infix_range::<PREFIX_LEN, INFIX_LEN, O>(
2246 prefix, at_depth, min_infix, max_infix,
2247 ),
2248 BodyRef::LocalLeaf(bytes) => {
2249 leaf::key_ops::first_infix_range::<KEY_LEN, PREFIX_LEN, INFIX_LEN, O>(
2250 bytes, prefix, at_depth, min_infix, max_infix,
2251 )
2252 }
2253 BodyRef::Branch(branch) => branch
2254 .first_infix_range::<PREFIX_LEN, INFIX_LEN>(prefix, at_depth, min_infix, max_infix),
2255 }
2256 }
2257
2258 pub(crate) fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
2259 &self,
2260 prefix: &[u8; PREFIX_LEN],
2261 at_depth: usize,
2262 min_infix: &[u8; INFIX_LEN],
2263 max_infix: &[u8; INFIX_LEN],
2264 ) -> u64 {
2265 match self.body_ref() {
2266 BodyRef::Leaf(leaf) => {
2267 leaf.count_range::<PREFIX_LEN, INFIX_LEN, O>(prefix, at_depth, min_infix, max_infix)
2268 }
2269 BodyRef::LocalLeaf(bytes) => {
2270 leaf::key_ops::count_range::<KEY_LEN, PREFIX_LEN, INFIX_LEN, O>(
2271 bytes, prefix, at_depth, min_infix, max_infix,
2272 )
2273 }
2274 BodyRef::Branch(branch) => {
2275 branch.count_range::<PREFIX_LEN, INFIX_LEN>(prefix, at_depth, min_infix, max_infix)
2276 }
2277 }
2278 }
2279
2280 pub(crate) fn has_prefix<const PREFIX_LEN: usize>(
2281 &self,
2282 at_depth: usize,
2283 prefix: &[u8; PREFIX_LEN],
2284 ) -> bool {
2285 const {
2286 assert!(PREFIX_LEN <= KEY_LEN);
2287 }
2288 match self.body_ref() {
2289 BodyRef::Leaf(leaf) => leaf.has_prefix::<O>(at_depth, prefix),
2290 BodyRef::LocalLeaf(bytes) => {
2291 leaf::key_ops::has_prefix::<KEY_LEN, O>(bytes, at_depth, prefix)
2292 }
2293 BodyRef::Branch(branch) => branch.has_prefix::<PREFIX_LEN>(at_depth, prefix),
2294 }
2295 }
2296
2297 pub(crate) fn traversal_depth<const PREFIX_LEN: usize>(
2298 &self,
2299 at_depth: usize,
2300 prefix: &[u8; PREFIX_LEN],
2301 ) -> usize {
2302 const {
2303 assert!(PREFIX_LEN <= KEY_LEN);
2304 }
2305 match self.body_ref() {
2306 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => 1,
2307 BodyRef::Branch(branch) => branch.traversal_depth::<PREFIX_LEN>(at_depth, prefix),
2308 }
2309 }
2310
2311 pub(crate) fn get<'a>(&'a self, at_depth: usize, key: &[u8; KEY_LEN]) -> Option<&'a V>
2312 where
2313 O: 'a,
2314 {
2315 match self.body_ref() {
2316 BodyRef::Leaf(leaf) => leaf.get::<O>(at_depth, key),
2317 BodyRef::LocalLeaf(bytes) => {
2318 if !leaf::key_ops::matches::<KEY_LEN, O>(bytes, at_depth, key) {
2319 return None;
2320 }
2321 static UNIT: () = ();
2331 let unit_ref: &V = unsafe {
2332 debug_assert_eq!(std::mem::size_of::<V>(), 0, "LocalLeaf requires V = ()");
2333 &*(&UNIT as *const () as *const V)
2334 };
2335 Some(unit_ref)
2336 }
2337 BodyRef::Branch(branch) => branch.get(at_depth, key),
2338 }
2339 }
2340
2341 pub(crate) fn segmented_len<const PREFIX_LEN: usize>(
2342 &self,
2343 at_depth: usize,
2344 prefix: &[u8; PREFIX_LEN],
2345 ) -> u64 {
2346 match self.body_ref() {
2347 BodyRef::Leaf(leaf) => leaf.segmented_len::<O, PREFIX_LEN>(at_depth, prefix),
2348 BodyRef::LocalLeaf(bytes) => {
2349 leaf::key_ops::segmented_len::<KEY_LEN, PREFIX_LEN, O>(bytes, at_depth, prefix)
2350 }
2351 BodyRef::Branch(branch) => branch.segmented_len::<PREFIX_LEN>(at_depth, prefix),
2352 }
2353 }
2354
2355 fn locate_prefix<const PREFIX_LEN: usize>(
2362 &self,
2363 at_depth: usize,
2364 prefix: &[u8; PREFIX_LEN],
2365 ) -> Option<&Self> {
2366 let node_end_depth = self.end_depth();
2367 let limit = std::cmp::min(PREFIX_LEN, node_end_depth);
2368 if !leaf::key_ops::has_prefix::<KEY_LEN, O>(
2369 self.childleaf_key(),
2370 at_depth,
2371 &prefix[..limit],
2372 ) {
2373 return None;
2374 }
2375 if PREFIX_LEN <= node_end_depth {
2376 return Some(self);
2377 }
2378 let BodyRef::Branch(branch) = self.body_ref() else {
2379 unreachable!("a leaf always covers the complete key");
2380 };
2381 branch
2382 .child_table
2383 .table_get(prefix[node_end_depth])
2384 .and_then(|child| child.locate_prefix(node_end_depth, prefix))
2385 }
2386
2387 fn infixes_from_matched_prefix<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
2390 &self,
2391 for_each: &mut F,
2392 ) where
2393 F: FnMut(&[u8; INFIX_LEN]),
2394 {
2395 if PREFIX_LEN + INFIX_LEN <= self.end_depth() {
2396 let infix: [u8; INFIX_LEN] =
2397 core::array::from_fn(|i| self.childleaf_key()[O::TREE_TO_KEY[PREFIX_LEN + i]]);
2398 for_each(&infix);
2399 return;
2400 }
2401
2402 let BodyRef::Branch(branch) = self.body_ref() else {
2403 unreachable!("a leaf always covers the complete key");
2404 };
2405 for child in branch.child_table.iter().flatten() {
2406 child.infixes_from_matched_prefix::<PREFIX_LEN, INFIX_LEN, F>(for_each);
2407 }
2408 }
2409
2410 pub(crate) fn node_stats(&self, acc: &mut (u64, u64, u64, u64)) {
2416 match self.body_ref() {
2417 BodyRef::Leaf(_) => acc.2 += 1,
2418 BodyRef::LocalLeaf(_) => acc.3 += 1,
2419 BodyRef::Branch(branch) => {
2420 acc.0 += 1;
2421 acc.1 += branch.child_table.len() as u64;
2422 for child in branch.child_table.iter().flatten() {
2423 child.node_stats(acc);
2424 }
2425 }
2426 }
2427 }
2428
2429 pub(crate) fn branch_hist(&self, hist: &mut [(u64, u64); 65]) {
2434 if let BodyRef::Branch(branch) = self.body_ref() {
2435 let d = self.end_depth().min(64);
2436 let fanout = branch.child_table.iter().flatten().count() as u64;
2437 hist[d].0 += 1;
2438 hist[d].1 += fanout;
2439 for child in branch.child_table.iter().flatten() {
2440 child.branch_hist(hist);
2441 }
2442 }
2443 }
2444
2445 pub(crate) fn branch_fanout_hist(&self, hist: &mut [u64; 257]) {
2448 if let BodyRef::Branch(branch) = self.body_ref() {
2449 let fanout = branch.child_table.iter().flatten().count();
2450 hist[fanout.min(256)] += 1;
2451 for child in branch.child_table.iter().flatten() {
2452 child.branch_fanout_hist(hist);
2453 }
2454 }
2455 }
2456
2457 pub(crate) fn intersect(&self, other: &Self, at_depth: usize) -> Option<Self> {
2461 if self.is_archive_singleton_pair(other) {
2462 return if self.first_divergence(other, at_depth).is_none() {
2463 Some(self.clone())
2464 } else {
2465 None
2466 };
2467 }
2468
2469 if self.local_leaf_cardinality_allows_equality(other) && self.hash() == other.hash() {
2470 return Some(self.clone());
2471 }
2472
2473 if self.first_divergence(other, at_depth).is_some() {
2474 return None;
2475 }
2476
2477 let self_depth = self.end_depth();
2478 let other_depth = other.end_depth();
2479 if self_depth < other_depth {
2480 let BodyRef::Branch(branch) = self.body_ref() else {
2483 unreachable!();
2484 };
2485 return branch
2486 .child_table
2487 .table_get(other.childleaf_key()[O::TREE_TO_KEY[self_depth]])
2488 .and_then(|self_child| other.intersect(self_child, self_depth));
2489 }
2490
2491 if other_depth < self_depth {
2492 let BodyRef::Branch(other_branch) = other.body_ref() else {
2496 unreachable!();
2497 };
2498 return other_branch
2499 .child_table
2500 .table_get(self.childleaf_key()[O::TREE_TO_KEY[other_depth]])
2501 .and_then(|other_child| self.intersect(other_child, other_depth));
2502 }
2503
2504 let BodyRef::Branch(self_branch) = self.body_ref() else {
2510 unreachable!();
2511 };
2512 let BodyRef::Branch(other_branch) = other.body_ref() else {
2513 unreachable!();
2514 };
2515
2516 let mut intersected_children = self_branch
2517 .child_table
2518 .iter()
2519 .filter_map(Option::as_ref)
2520 .filter_map(|self_child| {
2521 let other_child = other_branch.child_table.table_get(self_child.key())?;
2522 self_child.intersect(other_child, self_depth)
2523 });
2524 let first_child = intersected_children.next()?;
2525 let Some(second_child) = intersected_children.next() else {
2526 return Some(first_child);
2527 };
2528 let new_branch = Branch::new(
2529 self_depth,
2530 first_child.with_start(self_depth),
2531 second_child.with_start(self_depth),
2532 );
2533 let mut head_for_branch = Head::new(0, new_branch);
2538 {
2539 let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
2540 for child in intersected_children {
2541 let inserted = child.with_start(self_depth);
2542 let k = inserted.key();
2543 ed.modify_child(k, |_opt| Some(inserted));
2544 }
2545 }
2547 Some(head_for_branch)
2548 }
2549
2550 pub(crate) fn difference(&self, other: &Self, at_depth: usize) -> Option<Self> {
2554 if self.is_archive_singleton_pair(other) {
2555 return if self.first_divergence(other, at_depth).is_none() {
2556 None
2557 } else {
2558 Some(self.clone())
2559 };
2560 }
2561
2562 if self.local_leaf_cardinality_allows_equality(other) && self.hash() == other.hash() {
2563 return None;
2564 }
2565
2566 if self.first_divergence(other, at_depth).is_some() {
2567 return Some(self.clone());
2568 }
2569
2570 let self_depth = self.end_depth();
2571 let other_depth = other.end_depth();
2572 if self_depth < other_depth {
2573 let mut new_branch = self.clone();
2580 let other_byte_key = other.childleaf_key()[O::TREE_TO_KEY[self_depth]];
2581 {
2582 let mut ed = crate::patch::branch::BranchMut::from_head(&mut new_branch);
2583 ed.modify_child(other_byte_key, |opt| {
2584 opt.and_then(|child| child.difference(other, self_depth))
2585 });
2586
2587 let child_count = ed
2591 .child_table
2592 .iter()
2593 .filter(|child| child.is_some())
2594 .take(2)
2595 .count();
2596 if child_count <= 1 {
2597 let mut remaining = None;
2598 for slot in &mut ed.child_table {
2599 if let Some(child) = slot.take() {
2600 remaining = Some(child.with_start(at_depth));
2601 break;
2602 }
2603 }
2604 drop(ed);
2605 return remaining;
2606 }
2607 }
2608 return Some(new_branch);
2609 }
2610
2611 if other_depth < self_depth {
2612 let BodyRef::Branch(other_branch) = other.body_ref() else {
2619 unreachable!();
2620 };
2621 let self_byte_key = self.childleaf_key()[O::TREE_TO_KEY[other_depth]];
2622 if let Some(other_child) = other_branch.child_table.table_get(self_byte_key) {
2623 return self.difference(other_child, at_depth);
2624 } else {
2625 return Some(self.clone());
2626 }
2627 }
2628
2629 let BodyRef::Branch(self_branch) = self.body_ref() else {
2635 unreachable!();
2636 };
2637 let BodyRef::Branch(other_branch) = other.body_ref() else {
2638 unreachable!();
2639 };
2640
2641 let mut differenced_children = self_branch
2642 .child_table
2643 .iter()
2644 .filter_map(Option::as_ref)
2645 .filter_map(|self_child| {
2646 if let Some(other_child) = other_branch.child_table.table_get(self_child.key()) {
2647 self_child.difference(other_child, self_depth)
2648 } else {
2649 Some(self_child.clone())
2650 }
2651 });
2652
2653 let first_child = differenced_children.next()?;
2654 let second_child = match differenced_children.next() {
2655 Some(sc) => sc,
2656 None => return Some(first_child),
2657 };
2658
2659 let new_branch = Branch::new(
2660 self_depth,
2661 first_child.with_start(self_depth),
2662 second_child.with_start(self_depth),
2663 );
2664 let mut head_for_branch = Head::new(0, new_branch);
2665 {
2666 let mut ed = crate::patch::branch::BranchMut::from_head(&mut head_for_branch);
2667 for child in differenced_children {
2668 let inserted = child.with_start(self_depth);
2669 let k = inserted.key();
2670 ed.modify_child(k, |_opt| Some(inserted));
2671 }
2672 }
2674 Some(head_for_branch)
2678 }
2679
2680 pub(crate) fn inclusion(&self, other: &Self, at_depth: usize) -> Option<Ordering> {
2688 if self.is_archive_singleton_pair(other) {
2689 return self
2690 .first_divergence(other, at_depth)
2691 .is_none()
2692 .then_some(Ordering::Equal);
2693 }
2694
2695 if self.local_leaf_cardinality_allows_equality(other) && self.hash() == other.hash() {
2696 return Some(Ordering::Equal);
2697 }
2698
2699 if self.first_divergence(other, at_depth).is_some() {
2700 return None;
2702 }
2703
2704 let self_depth = self.end_depth();
2705 let other_depth = other.end_depth();
2706 if self_depth < other_depth {
2707 let BodyRef::Branch(self_branch) = self.body_ref() else {
2710 unreachable!();
2711 };
2712 let other_byte_key = other.childleaf_key()[O::TREE_TO_KEY[self_depth]];
2713 return match self_branch.child_table.table_get(other_byte_key) {
2714 Some(self_child) => match self_child.inclusion(other, at_depth) {
2715 Some(Ordering::Equal | Ordering::Greater) => Some(Ordering::Greater),
2716 _ => None,
2717 },
2718 None => None,
2719 };
2720 }
2721
2722 if other_depth < self_depth {
2723 let BodyRef::Branch(other_branch) = other.body_ref() else {
2724 unreachable!();
2725 };
2726 let self_byte_key = self.childleaf_key()[O::TREE_TO_KEY[other_depth]];
2727 return match other_branch.child_table.table_get(self_byte_key) {
2728 Some(other_child) => match self.inclusion(other_child, at_depth) {
2729 Some(Ordering::Equal | Ordering::Less) => Some(Ordering::Less),
2730 _ => None,
2731 },
2732 None => None,
2733 };
2734 }
2735
2736 let BodyRef::Branch(self_branch) = self.body_ref() else {
2742 unreachable!();
2743 };
2744 let BodyRef::Branch(other_branch) = other.body_ref() else {
2745 unreachable!();
2746 };
2747 let mut order = Some(Ordering::Equal);
2748 for self_child in self_branch.child_table.iter().filter_map(Option::as_ref) {
2749 let child_order = match other_branch.child_table.table_get(self_child.key()) {
2750 Some(other_child) => self_child.inclusion(other_child, self_depth),
2751 None => Some(Ordering::Greater),
2752 };
2753 order = meet(order, child_order)?;
2754 }
2755 for other_child in other_branch.child_table.iter().filter_map(Option::as_ref) {
2756 if self_branch.child_table.table_get(other_child.key()).is_none() {
2757 order = meet(order, Some(Ordering::Less))?;
2758 }
2759 }
2760 order
2761 }
2762}
2763
2764fn meet(left: Option<Ordering>, right: Option<Ordering>) -> Option<Option<Ordering>> {
2768 match (left?, right?) {
2769 (Ordering::Equal, order) | (order, Ordering::Equal) => Some(Some(order)),
2770 (Ordering::Less, Ordering::Less) => Some(Some(Ordering::Less)),
2771 (Ordering::Greater, Ordering::Greater) => Some(Some(Ordering::Greater)),
2772 _ => None,
2773 }
2774}
2775
2776unsafe impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> ByteEntry
2777 for Head<KEY_LEN, O, V, H>
2778{
2779 fn key(&self) -> u8 {
2780 self.key()
2781 }
2782}
2783
2784impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> fmt::Debug
2785 for Head<KEY_LEN, O, V, H>
2786{
2787 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2788 self.tag().fmt(f)
2789 }
2790}
2791
2792impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Clone
2793 for Head<KEY_LEN, O, V, H>
2794{
2795 fn clone(&self) -> Self {
2796 unsafe {
2797 match self.body() {
2798 BodyPtr::Leaf(leaf) => Self::new(self.key(), Leaf::rc_inc(leaf)),
2799 BodyPtr::LocalLeaf(ptr) => {
2800 Self::new_local_leaf(self.key(), ptr)
2803 }
2804 BodyPtr::Branch(branch) => Self::new(self.key(), Branch::rc_inc(branch)),
2805 }
2806 }
2807 }
2808}
2809
2810impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Drop for Head<KEY_LEN, O, V, H> {
2815 fn drop(&mut self) {
2816 unsafe {
2817 match self.body() {
2818 BodyPtr::Leaf(leaf) => Leaf::rc_dec(leaf),
2819 BodyPtr::LocalLeaf(_) => {
2820 }
2823 BodyPtr::Branch(branch) => Branch::rc_dec(branch),
2824 }
2825 }
2826 }
2827}
2828
2829#[derive(Debug)]
2869pub struct PATCH<const KEY_LEN: usize, O = IdentitySchema, V = (), H = XorSip128>
2870where
2871 O: KeySchema<KEY_LEN>,
2872 H: PatchHash,
2873{
2874 root: Option<Head<KEY_LEN, O, V, H>>,
2876 owners: Option<Arc<OwnerCover>>,
2882}
2883
2884#[must_use = "call for_each to enumerate the bounded infixes"]
2890pub struct PATCHBoundedInfixes<
2891 'a,
2892 const KEY_LEN: usize,
2893 const PREFIX_LEN: usize,
2894 const INFIX_LEN: usize,
2895 O: KeySchema<KEY_LEN>,
2896 V,
2897 H: PatchHash = XorSip128,
2898> {
2899 located: Option<&'a Head<KEY_LEN, O, V, H>>,
2900 count: u64,
2901}
2902
2903pub struct PATCHMerkleNode<'a, const KEY_LEN: usize, V> {
2911 head: &'a Head<KEY_LEN, IdentitySchema, V, Blake3Merkle>,
2912}
2913
2914impl<const KEY_LEN: usize, V> Copy for PATCHMerkleNode<'_, KEY_LEN, V> {}
2915
2916impl<const KEY_LEN: usize, V> Clone for PATCHMerkleNode<'_, KEY_LEN, V> {
2917 fn clone(&self) -> Self {
2918 *self
2919 }
2920}
2921
2922impl<'a, const KEY_LEN: usize, V> PATCHMerkleNode<'a, KEY_LEN, V> {
2923 fn new(head: &'a Head<KEY_LEN, IdentitySchema, V, Blake3Merkle>) -> Self {
2924 Self { head }
2925 }
2926
2927 pub fn digest(&self) -> [u8; 32] {
2929 self.head.hash()
2930 }
2931
2932 pub fn leaf_count(&self) -> u64 {
2937 self.head.count()
2938 }
2939
2940 pub fn end_depth(&self) -> usize {
2945 self.head.end_depth()
2946 }
2947
2948 pub fn representative(&self) -> &'a [u8; KEY_LEN] {
2955 let mut node = self.head;
2956 loop {
2957 match node.body_ref() {
2958 BodyRef::Leaf(leaf) => return &leaf.key,
2959 BodyRef::LocalLeaf(key) => return key,
2960 BodyRef::Branch(branch) => {
2961 node = branch
2962 .child_table
2963 .iter()
2964 .flatten()
2965 .min_by_key(|child| child.key())
2966 .expect("a PATCH branch has at least two children");
2967 }
2968 }
2969 }
2970 }
2971
2972 pub fn prefix(&self) -> &'a [u8] {
2977 &self.representative()[..self.end_depth()]
2978 }
2979
2980 pub fn is_leaf(&self) -> bool {
2982 self.end_depth() == KEY_LEN
2983 }
2984
2985 pub fn children(&self) -> PATCHMerkleChildren<'a, KEY_LEN, V> {
2987 PATCHMerkleChildren::new(*self)
2988 }
2989
2990 pub fn items_after(
2998 &self,
2999 after: Option<&[u8; KEY_LEN]>,
3000 limit: usize,
3001 ) -> PATCHMerkleItems<'a, KEY_LEN, V> {
3002 PATCHMerkleItems::new(*self, after.copied(), limit)
3003 }
3004
3005 fn may_contain_after(&self, after: &[u8; KEY_LEN]) -> bool {
3006 let end_depth = self.end_depth();
3007 self.representative()[..end_depth] >= after[..end_depth]
3008 }
3009}
3010
3011impl<const KEY_LEN: usize, V> core::fmt::Debug for PATCHMerkleNode<'_, KEY_LEN, V> {
3012 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
3013 f.debug_struct("PATCHMerkleNode")
3014 .field("prefix", &self.prefix())
3015 .field("digest", &self.digest())
3016 .field("leaf_count", &self.leaf_count())
3017 .field("end_depth", &self.end_depth())
3018 .field("representative", self.representative())
3019 .finish()
3020 }
3021}
3022
3023pub struct PATCHMerkleChildren<'a, const KEY_LEN: usize, V> {
3029 node: Option<PATCHMerkleNode<'a, KEY_LEN, V>>,
3030 edges: ByteSet,
3031}
3032
3033impl<'a, const KEY_LEN: usize, V> PATCHMerkleChildren<'a, KEY_LEN, V> {
3034 fn new(node: PATCHMerkleNode<'a, KEY_LEN, V>) -> Self {
3035 let mut edges = ByteSet::new_empty();
3036 if let BodyRef::Branch(branch) = node.head.body_ref() {
3037 for child in branch.child_table.iter().flatten() {
3038 edges.insert(child.key());
3039 }
3040 }
3041 Self {
3042 node: (!node.is_leaf()).then_some(node),
3043 edges,
3044 }
3045 }
3046}
3047
3048impl<'a, const KEY_LEN: usize, V> Iterator for PATCHMerkleChildren<'a, KEY_LEN, V> {
3049 type Item = (u8, PATCHMerkleNode<'a, KEY_LEN, V>);
3050
3051 fn next(&mut self) -> Option<Self::Item> {
3052 let edge = self.edges.drain_next_ascending()?;
3053 let node = self.node.expect("a child edge requires a branch node");
3054 let BodyRef::Branch(branch) = node.head.body_ref() else {
3055 unreachable!("a leaf cannot carry child edges");
3056 };
3057 let child = branch
3058 .child_table
3059 .table_get(edge)
3060 .expect("an enumerated PATCH child remains present");
3061 Some((edge, PATCHMerkleNode::new(child)))
3062 }
3063
3064 fn size_hint(&self) -> (usize, Option<usize>) {
3065 let remaining = self.edges.popcount() as usize;
3066 (remaining, Some(remaining))
3067 }
3068}
3069
3070impl<const KEY_LEN: usize, V> ExactSizeIterator for PATCHMerkleChildren<'_, KEY_LEN, V> {}
3071impl<const KEY_LEN: usize, V> std::iter::FusedIterator for PATCHMerkleChildren<'_, KEY_LEN, V> {}
3072
3073pub struct PATCHMerkleItems<'a, const KEY_LEN: usize, V> {
3079 pending: Option<PATCHMerkleNode<'a, KEY_LEN, V>>,
3080 stack: Vec<PATCHMerkleChildren<'a, KEY_LEN, V>>,
3081 after: Option<[u8; KEY_LEN]>,
3082 remaining: usize,
3083}
3084
3085impl<'a, const KEY_LEN: usize, V> PATCHMerkleItems<'a, KEY_LEN, V> {
3086 fn new(
3087 node: PATCHMerkleNode<'a, KEY_LEN, V>,
3088 after: Option<[u8; KEY_LEN]>,
3089 limit: usize,
3090 ) -> Self {
3091 Self {
3092 pending: (limit != 0).then_some(node),
3093 stack: Vec::new(),
3094 after,
3095 remaining: limit,
3096 }
3097 }
3098
3099 fn next_node(&mut self) -> Option<PATCHMerkleNode<'a, KEY_LEN, V>> {
3100 if let Some(node) = self.pending.take() {
3101 return Some(node);
3102 }
3103 loop {
3104 let children = self.stack.last_mut()?;
3105 if let Some((_, node)) = children.next() {
3106 return Some(node);
3107 }
3108 self.stack.pop();
3109 }
3110 }
3111}
3112
3113impl<'a, const KEY_LEN: usize, V> Iterator for PATCHMerkleItems<'a, KEY_LEN, V> {
3114 type Item = [u8; KEY_LEN];
3115
3116 fn next(&mut self) -> Option<Self::Item> {
3117 while self.remaining != 0 {
3118 let node = self.next_node()?;
3119 if self
3120 .after
3121 .as_ref()
3122 .is_some_and(|after| !node.may_contain_after(after))
3123 {
3124 continue;
3125 }
3126 if node.is_leaf() {
3127 let key = *node.representative();
3128 if self.after.as_ref().is_some_and(|after| key <= *after) {
3129 continue;
3130 }
3131 self.remaining -= 1;
3132 return Some(key);
3133 }
3134 self.stack.push(node.children());
3135 }
3136 None
3137 }
3138
3139 fn size_hint(&self) -> (usize, Option<usize>) {
3140 (0, Some(self.remaining))
3141 }
3142}
3143
3144impl<const KEY_LEN: usize, V> std::iter::FusedIterator for PATCHMerkleItems<'_, KEY_LEN, V> {}
3145
3146impl<
3147 'a,
3148 const KEY_LEN: usize,
3149 const PREFIX_LEN: usize,
3150 const INFIX_LEN: usize,
3151 O: KeySchema<KEY_LEN>,
3152 V,
3153 H: PatchHash,
3154 > PATCHBoundedInfixes<'a, KEY_LEN, PREFIX_LEN, INFIX_LEN, O, V, H>
3155{
3156 pub fn len(&self) -> u64 {
3158 self.count
3159 }
3160
3161 pub fn is_empty(&self) -> bool {
3163 self.count == 0
3164 }
3165
3166 pub fn for_each<F>(self, mut for_each: F)
3169 where
3170 F: FnMut(&[u8; INFIX_LEN]),
3171 {
3172 if let Some(located) = self.located {
3173 located.infixes_from_matched_prefix::<PREFIX_LEN, INFIX_LEN, F>(&mut for_each);
3174 }
3175 }
3176}
3177
3178impl<const KEY_LEN: usize, O, V, H> Clone for PATCH<KEY_LEN, O, V, H>
3179where
3180 O: KeySchema<KEY_LEN>,
3181 H: PatchHash,
3182{
3183 fn clone(&self) -> Self {
3184 Self {
3185 root: self.root.clone(),
3186 owners: self.owners.clone(),
3187 }
3188 }
3189}
3190
3191impl<const KEY_LEN: usize, O, V, H> Default for PATCH<KEY_LEN, O, V, H>
3192where
3193 O: KeySchema<KEY_LEN>,
3194 H: PatchHash,
3195{
3196 fn default() -> Self {
3197 Self::new()
3198 }
3199}
3200
3201impl<const KEY_LEN: usize, O, V, H> PATCH<KEY_LEN, O, V, H>
3202where
3203 O: KeySchema<KEY_LEN>,
3204 H: PatchHash,
3205{
3206 pub fn new() -> Self {
3208 H::init();
3209 PATCH {
3210 root: None,
3211 owners: None,
3212 }
3213 }
3214
3215 pub fn insert(&mut self, entry: &Entry<KEY_LEN, V, H>) {
3222 if self.root.is_some() {
3223 let this = self.root.take().expect("root should not be empty");
3224 let new_head = Head::insert_leaf(this, entry.leaf(), 0);
3225 self.root.replace(new_head);
3226 } else {
3227 self.root.replace(entry.leaf());
3228 }
3229 self.debug_check_owner_invariant();
3230 }
3231
3232 pub fn replace(&mut self, entry: &Entry<KEY_LEN, V, H>) {
3237 let retired_leaf = if self.root.is_some() {
3238 let this = self.root.take().expect("root should not be empty");
3239 let (new_head, retired_leaf) = Head::replace_leaf(this, entry.leaf(), 0);
3240 self.root.replace(new_head);
3241 retired_leaf
3242 } else {
3243 self.root.replace(entry.leaf());
3244 None
3245 };
3246 self.debug_check_owner_invariant();
3247
3248 drop(retired_leaf);
3251 }
3252
3253 pub fn remove(&mut self, key: &[u8; KEY_LEN]) {
3262 let retired_leaf = Head::remove_leaf(&mut self.root, key, 0);
3263 let retired_owners = if self.root.is_none() {
3264 self.owners.take()
3265 } else {
3266 None
3267 };
3268 self.debug_check_owner_invariant();
3269
3270 drop(retired_owners);
3274 drop(retired_leaf);
3275 }
3276
3277 pub fn len(&self) -> u64 {
3279 if let Some(root) = &self.root {
3280 root.count()
3281 } else {
3282 0
3283 }
3284 }
3285
3286 pub fn node_stats(&self) -> (u64, u64, u64, u64) {
3292 let mut acc = (0u64, 0u64, 0u64, 0u64);
3293 if let Some(root) = &self.root {
3294 root.node_stats(&mut acc);
3295 }
3296 acc
3297 }
3298
3299 #[cfg(debug_assertions)]
3300 fn debug_check_owner_invariant(&self) {
3301 debug_assert!(
3302 self.root.as_ref().map(|root| root.tag()) != Some(HeadTag::LocalLeaf)
3303 || self.owners.is_some(),
3304 "a root LocalLeaf must retain its archive owner",
3305 );
3306 }
3307
3308 #[cfg(not(debug_assertions))]
3309 #[inline]
3310 fn debug_check_owner_invariant(&self) {}
3311
3312 pub fn total_table_slots(&self) -> u64 {
3317 self.node_stats().1
3318 }
3319
3320 pub fn branch_header_bytes() -> usize {
3322 std::mem::size_of::<Branch<KEY_LEN, O, [Option<Head<KEY_LEN, O, V, H>>; 0], V, H>>()
3323 }
3324
3325 pub fn branch_histogram(&self) -> [(u64, u64); 65] {
3329 let mut hist = [(0u64, 0u64); 65];
3330 if let Some(root) = &self.root {
3331 root.branch_hist(&mut hist);
3332 }
3333 hist
3334 }
3335
3336 pub fn branch_fanout_histogram(&self) -> [u64; 257] {
3339 let mut hist = [0u64; 257];
3340 if let Some(root) = &self.root {
3341 root.branch_fanout_hist(&mut hist);
3342 }
3343 hist
3344 }
3345
3346 #[cfg(test)]
3348 pub(crate) fn archive_owner_guard_stats(&self) -> (bool, u64) {
3349 (self.owners.is_some(), self.node_stats().3)
3350 }
3351
3352 pub fn is_empty(&self) -> bool {
3354 self.len() == 0
3355 }
3356
3357 pub(crate) fn root_hash(&self) -> Option<H::Digest> {
3363 self.root.as_ref().map(|root| root.hash())
3364 }
3365
3366 pub(crate) fn shares_root(&self, other: &Self) -> bool {
3373 match (&self.root, &other.root) {
3374 (None, None) => true,
3375 (Some(left), Some(right)) => left.tptr == right.tptr,
3376 _ => false,
3377 }
3378 }
3379
3380 pub(crate) fn shares_prefix<const PREFIX_LEN: usize>(
3393 &self,
3394 other: &Self,
3395 prefix: &[u8; PREFIX_LEN],
3396 ) -> bool {
3397 const {
3398 assert!(PREFIX_LEN <= KEY_LEN);
3399 }
3400 let left = self
3401 .root
3402 .as_ref()
3403 .and_then(|root| root.locate_prefix(0, prefix));
3404 let right = other
3405 .root
3406 .as_ref()
3407 .and_then(|root| root.locate_prefix(0, prefix));
3408 match (left, right) {
3409 (None, None) => true,
3410 (Some(left), Some(right)) => {
3411 let mask = !(Head::<KEY_LEN, O, V, H>::KEY_MASK as usize);
3412 (left.tptr.as_ptr().addr() & mask) == (right.tptr.as_ptr().addr() & mask)
3413 }
3414 _ => false,
3415 }
3416 }
3417
3418 pub(crate) fn owner_guard(&self) -> PATCHOwnerGuard {
3420 PATCHOwnerGuard(self.owners.clone())
3421 }
3422
3423 pub(crate) fn shares_owner_guard<OO, VV, HH>(&self, other: &PATCH<KEY_LEN, OO, VV, HH>) -> bool
3425 where
3426 OO: KeySchema<KEY_LEN>,
3427 HH: PatchHash,
3428 {
3429 match (&self.owners, &other.owners) {
3430 (None, None) => true,
3431 (Some(left), Some(right)) => Arc::ptr_eq(left, right),
3432 _ => false,
3433 }
3434 }
3435
3436 pub(crate) fn owner_guard_latest_is(&self, owner: &Arc<dyn ArchiveOwner>) -> bool {
3438 self.owners
3439 .as_ref()
3440 .is_some_and(|cover| cover.latest_address == OwnerCover::address(owner))
3441 }
3442
3443 pub(crate) unsafe fn set_owner_guard(&mut self, guard: &PATCHOwnerGuard) {
3452 #[cfg(debug_assertions)]
3453 debug_assert!(
3454 guard.covers(&self.owners),
3455 "a PATCH owner guard may only be replaced by an owner-cover superset",
3456 );
3457 let already_installed = match (&self.owners, &guard.0) {
3458 (None, None) => true,
3459 (Some(current), Some(replacement)) => Arc::ptr_eq(current, replacement),
3460 _ => false,
3461 };
3462 if !already_installed {
3463 self.owners = guard.0.clone();
3464 }
3465 self.debug_check_owner_invariant();
3466 }
3467
3468 pub fn get(&self, key: &[u8; KEY_LEN]) -> Option<&V> {
3470 self.root.as_ref().and_then(|root| root.get(0, key))
3471 }
3472
3473 pub fn infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
3487 &self,
3488 prefix: &[u8; PREFIX_LEN],
3489 mut for_each: F,
3490 ) where
3491 F: FnMut(&[u8; INFIX_LEN]),
3492 {
3493 const {
3494 assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
3495 }
3496 assert!(
3497 O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
3498 && (PREFIX_LEN + INFIX_LEN == KEY_LEN
3499 || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
3500 "INFIX_LEN must cover a whole segment"
3501 );
3502 if let Some(root) = &self.root {
3503 root.infixes(prefix, 0, &mut for_each);
3504 }
3505 }
3506
3507 pub fn bounded_infixes<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
3521 &self,
3522 prefix: &[u8; PREFIX_LEN],
3523 limit: u64,
3524 ) -> Option<PATCHBoundedInfixes<'_, KEY_LEN, PREFIX_LEN, INFIX_LEN, O, V, H>> {
3525 const {
3526 assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
3527 }
3528 assert!(
3529 O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
3530 && (PREFIX_LEN + INFIX_LEN == KEY_LEN
3531 || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
3532 "INFIX_LEN must cover a whole segment"
3533 );
3534 const {
3535 if PREFIX_LEN > 0 && PREFIX_LEN < KEY_LEN {
3536 assert!(
3537 <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
3538 [O::TREE_TO_KEY[PREFIX_LEN - 1]]
3539 != <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
3540 [O::TREE_TO_KEY[PREFIX_LEN]],
3541 "PREFIX_LEN must align to segment boundary",
3542 );
3543 }
3544 }
3545
3546 let Some(root) = &self.root else {
3547 return Some(PATCHBoundedInfixes {
3548 located: None,
3549 count: 0,
3550 });
3551 };
3552 let Some(located) = root.locate_prefix(0, prefix) else {
3553 return Some(PATCHBoundedInfixes {
3554 located: None,
3555 count: 0,
3556 });
3557 };
3558 let count = located.count_segment(PREFIX_LEN);
3559 if count > limit {
3560 return None;
3561 }
3562 Some(PATCHBoundedInfixes {
3563 located: Some(located),
3564 count,
3565 })
3566 }
3567
3568 pub fn infixes_range<const PREFIX_LEN: usize, const INFIX_LEN: usize, F>(
3575 &self,
3576 prefix: &[u8; PREFIX_LEN],
3577 min_infix: &[u8; INFIX_LEN],
3578 max_infix: &[u8; INFIX_LEN],
3579 mut for_each: F,
3580 ) where
3581 F: FnMut(&[u8; INFIX_LEN]),
3582 {
3583 const {
3584 assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
3585 }
3586 assert!(
3587 O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
3588 && (PREFIX_LEN + INFIX_LEN == KEY_LEN
3589 || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
3590 "INFIX_LEN must cover a whole segment"
3591 );
3592 if let Some(root) = &self.root {
3593 root.infixes_range(prefix, 0, min_infix, max_infix, &mut for_each);
3594 }
3595 }
3596
3597 pub fn first_infix_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
3604 &self,
3605 prefix: &[u8; PREFIX_LEN],
3606 min_infix: &[u8; INFIX_LEN],
3607 max_infix: &[u8; INFIX_LEN],
3608 ) -> Option<[u8; INFIX_LEN]> {
3609 const {
3610 assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
3611 }
3612 assert!(
3613 O::same_segment_tree(PREFIX_LEN, PREFIX_LEN + INFIX_LEN - 1)
3614 && (PREFIX_LEN + INFIX_LEN == KEY_LEN
3615 || !O::same_segment_tree(PREFIX_LEN + INFIX_LEN - 1, PREFIX_LEN + INFIX_LEN)),
3616 "INFIX_LEN must cover a whole segment"
3617 );
3618 if min_infix > max_infix {
3619 return None;
3620 }
3621 self.root
3622 .as_ref()
3623 .and_then(|root| root.first_infix_range(prefix, 0, min_infix, max_infix))
3624 }
3625
3626 pub fn next_infix_after<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
3633 &self,
3634 prefix: &[u8; PREFIX_LEN],
3635 after: &[u8; INFIX_LEN],
3636 max_infix: &[u8; INFIX_LEN],
3637 ) -> Option<[u8; INFIX_LEN]> {
3638 let mut lower = *after;
3639 let mut cursor = INFIX_LEN;
3640 loop {
3641 if cursor == 0 {
3642 return None;
3643 }
3644 cursor -= 1;
3645 if lower[cursor] != u8::MAX {
3646 lower[cursor] += 1;
3647 for byte in &mut lower[cursor + 1..] {
3648 *byte = u8::MIN;
3649 }
3650 break;
3651 }
3652 }
3653 self.first_infix_range(prefix, &lower, max_infix)
3654 }
3655
3656 pub fn count_range<const PREFIX_LEN: usize, const INFIX_LEN: usize>(
3662 &self,
3663 prefix: &[u8; PREFIX_LEN],
3664 min_infix: &[u8; INFIX_LEN],
3665 max_infix: &[u8; INFIX_LEN],
3666 ) -> u64 {
3667 const {
3668 assert!(PREFIX_LEN + INFIX_LEN <= KEY_LEN);
3669 }
3670 match &self.root {
3671 Some(root) => root.count_range(prefix, 0, min_infix, max_infix),
3672 None => 0,
3673 }
3674 }
3675
3676 pub fn has_prefix<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> bool {
3681 const {
3682 assert!(PREFIX_LEN <= KEY_LEN);
3683 }
3684 if let Some(root) = &self.root {
3685 root.has_prefix(0, prefix)
3686 } else {
3687 PREFIX_LEN == 0
3688 }
3689 }
3690
3691 pub fn traversal_depth<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> usize {
3697 const {
3698 assert!(PREFIX_LEN <= KEY_LEN);
3699 }
3700 self.root
3701 .as_ref()
3702 .map(|root| root.traversal_depth(0, prefix))
3703 .unwrap_or(0)
3704 }
3705
3706 pub fn segmented_len<const PREFIX_LEN: usize>(&self, prefix: &[u8; PREFIX_LEN]) -> u64 {
3708 const {
3709 assert!(PREFIX_LEN <= KEY_LEN);
3710 if PREFIX_LEN > 0 && PREFIX_LEN < KEY_LEN {
3711 assert!(
3712 <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
3713 [O::TREE_TO_KEY[PREFIX_LEN - 1]]
3714 != <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
3715 [O::TREE_TO_KEY[PREFIX_LEN]],
3716 "PREFIX_LEN must align to segment boundary",
3717 );
3718 }
3719 }
3720 if let Some(root) = &self.root {
3721 root.segmented_len(0, prefix)
3722 } else {
3723 0
3724 }
3725 }
3726
3727 pub fn iter<'a>(&'a self) -> PATCHIterator<'a, KEY_LEN, O, V, H> {
3730 PATCHIterator::new(self)
3731 }
3732
3733 pub fn iter_ordered<'a>(&'a self) -> PATCHOrderedIterator<'a, KEY_LEN, O, V, H> {
3739 PATCHOrderedIterator::new(self)
3740 }
3741
3742 pub fn iter_prefix_count<'a, const PREFIX_LEN: usize>(
3746 &'a self,
3747 ) -> PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H> {
3748 PATCHPrefixIterator::new(self)
3749 }
3750
3751 pub fn prefix_set<const PREFIX_LEN: usize>(
3757 &self,
3758 ) -> PATCHPrefixSet<'_, KEY_LEN, PREFIX_LEN, O, V, H> {
3759 PATCHPrefixSet::new(self)
3760 }
3761
3762 pub fn union(&mut self, mut other: Self)
3770 where
3771 O: Send + Sync,
3772 V: Send + Sync,
3773 {
3774 if let Some(other_root) = other.root.take() {
3775 if self.root.is_some() {
3776 OwnerCover::merge_into(&mut self.owners, &other.owners);
3780 let this = self.root.take().expect("root should not be empty");
3781 #[cfg(feature = "parallel")]
3782 let merged = Head::par_union(this, other_root, 0);
3783 #[cfg(not(feature = "parallel"))]
3784 let merged = Head::union(this, other_root, 0);
3785 self.root.replace(merged);
3786 } else {
3787 self.root.replace(other_root);
3788 self.owners = other.owners.take();
3789 }
3790 }
3791 self.debug_check_owner_invariant();
3792 }
3793
3794 pub fn intersect(&self, other: &Self) -> Self
3798 where
3799 O: Send + Sync,
3800 V: Send + Sync,
3801 {
3802 let guard = self.owner_guard().join(other.owner_guard());
3803 unsafe { self.intersect_with_guard(other, &guard) }
3805 }
3806
3807 pub(crate) unsafe fn intersect_with_guard(&self, other: &Self, guard: &PATCHOwnerGuard) -> Self
3814 where
3815 O: Send + Sync,
3816 V: Send + Sync,
3817 {
3818 #[cfg(debug_assertions)]
3819 debug_assert!(
3820 guard.covers(&self.owners) && guard.covers(&other.owners),
3821 "an intersection guard must cover both source PATCHes",
3822 );
3823 let root = match (&self.root, &other.root) {
3824 (Some(root), Some(other_root)) => {
3825 #[cfg(feature = "parallel")]
3826 let result = root.par_intersect(other_root, 0);
3827 #[cfg(not(feature = "parallel"))]
3828 let result = root.intersect(other_root, 0);
3829 result.map(|root| root.with_start(0))
3830 }
3831 _ => None,
3832 };
3833 let owners = root.as_ref().and(guard.0.clone());
3834 let result = Self { root, owners };
3835 result.debug_check_owner_invariant();
3836 result
3837 }
3838
3839 pub fn difference(&self, other: &Self) -> Self
3844 where
3845 O: Send + Sync,
3846 V: Send + Sync,
3847 {
3848 let guard = self.owner_guard();
3849 unsafe { self.difference_with_guard(other, &guard) }
3851 }
3852
3853
3854 pub(crate) unsafe fn difference_with_guard(&self, other: &Self, guard: &PATCHOwnerGuard) -> Self
3861 where
3862 O: Send + Sync,
3863 V: Send + Sync,
3864 {
3865 #[cfg(debug_assertions)]
3866 debug_assert!(
3867 guard.covers(&self.owners),
3868 "a difference guard must cover its left source PATCH",
3869 );
3870 let root = match (&self.root, &other.root) {
3871 (Some(root), Some(other_root)) => {
3872 #[cfg(feature = "parallel")]
3873 let result = root.par_difference(other_root, 0);
3874 #[cfg(not(feature = "parallel"))]
3875 let result = root.difference(other_root, 0);
3876 result
3877 }
3878 (Some(root), None) => Some(root.clone()),
3879 (None, _) => None,
3880 };
3881 let owners = root.as_ref().and(guard.0.clone());
3882 let result = Self { root, owners };
3883 result.debug_check_owner_invariant();
3884 result
3885 }
3886
3887 pub fn debug_branch_fill(&self) -> [f32; 8] {
3892 let mut counts = [0u64; 8];
3893 let mut used = [0u64; 8];
3894
3895 if let Some(root) = &self.root {
3896 let mut stack = Vec::new();
3897 stack.push(root);
3898
3899 while let Some(head) = stack.pop() {
3900 match head.body_ref() {
3901 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => {}
3902 BodyRef::Branch(b) => {
3903 let size = b.child_table.len();
3904 let idx = size.trailing_zeros() as usize - 1;
3905 counts[idx] += 1;
3906 used[idx] += b.child_table.iter().filter(|c| c.is_some()).count() as u64;
3907 for child in b.child_table.iter().filter_map(|c| c.as_ref()) {
3908 stack.push(child);
3909 }
3910 }
3911 }
3912 }
3913 }
3914
3915 let mut avg = [0f32; 8];
3916 for i in 0..8 {
3917 if counts[i] > 0 {
3918 let size = 1u64 << (i + 1);
3919 avg[i] = used[i] as f32 / (counts[i] as f32 * size as f32);
3920 }
3921 }
3922 avg
3923 }
3924}
3925
3926impl<const KEY_LEN: usize, O, V> PATCH<KEY_LEN, O, V, Blake3Merkle>
3927where
3928 O: KeySchema<KEY_LEN>,
3929{
3930 pub fn merkle_root(&self) -> Option<[u8; 32]> {
3937 self.root_hash()
3938 }
3939}
3940
3941impl<const KEY_LEN: usize, V> PATCH<KEY_LEN, IdentitySchema, V, Blake3Merkle> {
3942 pub fn merkle_node(&self, prefix: &[u8]) -> Option<PATCHMerkleNode<'_, KEY_LEN, V>> {
3951 if prefix.len() > KEY_LEN {
3952 return None;
3953 }
3954
3955 let mut node = self.root.as_ref()?;
3956 let mut at_depth = 0;
3957 loop {
3958 let end_depth = node.end_depth();
3959 let limit = prefix.len().min(end_depth);
3960 if node.childleaf_key()[at_depth..limit] != prefix[at_depth..limit] {
3961 return None;
3962 }
3963 if prefix.len() <= end_depth {
3964 return Some(PATCHMerkleNode::new(node));
3965 }
3966
3967 let BodyRef::Branch(branch) = node.body_ref() else {
3968 unreachable!("a leaf covers every raw-key byte");
3969 };
3970 node = branch.child_table.table_get(prefix[end_depth])?;
3971 at_depth = end_depth;
3972 }
3973 }
3974}
3975
3976impl<const KEY_LEN: usize> PATCH<KEY_LEN, IdentitySchema, (), Blake3Merkle> {
3977 pub fn from_keys(keys: impl IntoIterator<Item = [u8; KEY_LEN]>) -> Self {
3991 Self::from_owned_keys(keys.into_iter().collect())
3992 }
3993}
3994
3995impl<const KEY_LEN: usize, H: PatchHash> PATCH<KEY_LEN, IdentitySchema, (), H> {
3996 fn from_owned_keys(mut keys: Vec<[u8; KEY_LEN]>) -> Self {
3997 H::init();
3998 if !keys.windows(2).all(|pair| pair[0] < pair[1]) {
3999 #[cfg(feature = "parallel")]
4000 {
4001 use rayon::prelude::*;
4002 keys.par_sort_unstable();
4003 }
4004 #[cfg(not(feature = "parallel"))]
4005 keys.sort_unstable();
4006 keys.dedup();
4007 }
4008
4009 let root = (!keys.is_empty()).then(|| Self::build_owned_sorted_head(&keys, 0).0);
4010 let result = Self { root, owners: None };
4011 result.debug_check_owner_invariant();
4012 result
4013 }
4014
4015 fn build_owned_sorted_head(
4019 keys: &[[u8; KEY_LEN]],
4020 depth: usize,
4021 ) -> (Head<KEY_LEN, IdentitySchema, (), H>, H::Digest) {
4022 debug_assert!(!keys.is_empty());
4023 if keys.len() == 1 {
4024 let leaf = unsafe { Leaf::<KEY_LEN, (), H>::new(&keys[0], ()) };
4027 let digest = unsafe { leaf.as_ref().hash };
4028 return (Head::new(0, leaf), digest);
4029 }
4030
4031 let first = &keys[0];
4034 let last = &keys[keys.len() - 1];
4035 let mut end_depth = depth;
4036 while end_depth < KEY_LEN && first[end_depth] == last[end_depth] {
4037 end_depth += 1;
4038 }
4039 debug_assert!(
4040 end_depth < KEY_LEN,
4041 "deduplicated keys must diverge before their end"
4042 );
4043
4044 let mut groups = Vec::with_capacity(256.min(keys.len()));
4045 let mut start = 0;
4046 while start < keys.len() {
4047 let edge = keys[start][end_depth];
4048 let width = keys[start..].partition_point(|key| key[end_depth] == edge);
4049 let end = start + width;
4050 groups.push((edge, &keys[start..end]));
4051 start = end;
4052 }
4053 debug_assert!(groups.len() >= 2);
4054 let initial_slots = if groups.len() == 2 {
4055 2
4056 } else {
4057 groups.len().next_power_of_two()
4058 };
4059
4060 #[cfg(feature = "parallel")]
4061 let children = if keys.len() >= Self::PARALLEL_PARTITION_THRESHOLD {
4062 use rayon::prelude::*;
4063 groups
4064 .into_par_iter()
4065 .map(|(edge, child_keys)| {
4066 let (head, digest) = Self::build_owned_sorted_head(child_keys, end_depth + 1);
4067 (edge, head, digest)
4068 })
4069 .collect()
4070 } else {
4071 groups
4072 .into_iter()
4073 .map(|(edge, child_keys)| {
4074 let (head, digest) = Self::build_owned_sorted_head(child_keys, end_depth + 1);
4075 (edge, head, digest)
4076 })
4077 .collect()
4078 };
4079 #[cfg(not(feature = "parallel"))]
4080 let children = groups
4081 .into_iter()
4082 .map(|(edge, child_keys)| {
4083 let (head, digest) = Self::build_owned_sorted_head(child_keys, end_depth + 1);
4084 (edge, head, digest)
4085 })
4086 .collect();
4087
4088 Self::assemble_partition_branch(end_depth, initial_slots, children)
4089 }
4090}
4091
4092impl<const KEY_LEN: usize, O, H> PATCH<KEY_LEN, O, (), H>
4097where
4098 O: KeySchema<KEY_LEN>,
4099 H: PatchHash,
4100{
4101 pub fn insert_archive(&mut self, entry: &ArchiveEntry<'_, KEY_LEN, H>) {
4104 let (leaf_head, leaf_owner, leaf_hash) = entry.leaf::<O>();
4105 OwnerCover::retain(&mut self.owners, leaf_owner);
4106 if let Some(this) = self.root.take() {
4107 let new_head = Head::insert_archive_leaf(this, leaf_head, leaf_hash, 0);
4108 self.root.replace(new_head);
4109 } else {
4110 self.root.replace(leaf_head);
4111 }
4112 self.debug_check_owner_invariant();
4113 }
4114
4115 #[cfg(test)]
4131 pub(crate) unsafe fn from_archive_partition(
4132 keys: &[[u8; KEY_LEN]],
4133 hashes: &[H::Digest],
4134 rows: &mut [u32],
4135 owner: &std::sync::Arc<dyn ArchiveOwner>,
4136 ) -> Self {
4137 unsafe {
4138 Self::from_archive_partition_with_guard(
4139 keys,
4140 hashes,
4141 rows,
4142 owner,
4143 &PATCHOwnerGuard::default(),
4144 )
4145 }
4146 }
4147
4148 #[cfg(any(test, feature = "parallel"))]
4152 pub(crate) unsafe fn from_archive_partition_with_guard(
4153 keys: &[[u8; KEY_LEN]],
4154 hashes: &[H::Digest],
4155 rows: &mut [u32],
4156 owner: &std::sync::Arc<dyn ArchiveOwner>,
4157 guard: &PATCHOwnerGuard,
4158 ) -> Self {
4159 H::init();
4163 assert_eq!(keys.len(), hashes.len());
4164 assert_eq!(keys.len(), rows.len());
4165 assert!(
4166 u32::try_from(rows.len()).is_ok(),
4167 "archive row ordinals must fit the partition metadata",
4168 );
4169 if rows.is_empty() {
4170 return Self::new();
4171 }
4172 let mut guard = guard.clone();
4173 guard.retain_archive_owner(owner);
4174 let owners = guard.0;
4175 if rows.len() == 1 {
4176 let row = rows[0] as usize;
4177 let ptr = NonNull::from(&keys[row]);
4178 let root = unsafe { Head::new_local_leaf(0, ptr) };
4181 let result = Self {
4182 root: Some(root),
4183 owners,
4184 };
4185 result.debug_check_owner_invariant();
4186 return result;
4187 }
4188
4189 let (root, _) = unsafe { Self::build_archive_partition_head(keys, hashes, rows, 0) };
4190 let result = Self {
4191 root: Some(root.with_start(0)),
4192 owners,
4193 };
4194 result.debug_check_owner_invariant();
4195 result
4196 }
4197
4198 #[cfg(feature = "parallel")]
4206 pub(crate) const PARALLEL_PARTITION_THRESHOLD: usize = 1 << 12;
4207
4208 #[cfg(feature = "parallel")]
4215 pub(crate) const PARTITION_ROWS_PER_WORKER: usize = 1 << 13;
4216
4217 #[cfg(feature = "parallel")]
4220 pub(crate) fn partition_workers(rows: usize) -> usize {
4221 (rows / Self::PARTITION_ROWS_PER_WORKER)
4222 .min(rayon::current_num_threads().max(1))
4223 .max(1)
4224 }
4225
4226 #[cfg(any(test, feature = "parallel"))]
4247 unsafe fn build_archive_partition_head(
4248 keys: &[[u8; KEY_LEN]],
4249 hashes: &[H::Digest],
4250 rows: &mut [u32],
4251 depth: usize,
4252 ) -> (Head<KEY_LEN, O, (), H>, H::Digest) {
4253 debug_assert!(!rows.is_empty());
4254 if rows.len() == 1 {
4255 let row = rows[0] as usize;
4256 let ptr = NonNull::from(&keys[row]);
4257 let head = unsafe { Head::new_local_leaf(0, ptr) };
4260 return (head, hashes[row]);
4261 }
4262
4263 #[cfg(feature = "parallel")]
4268 if Self::partition_workers(rows.len()) > 1 {
4269 let (plan, mut permuted) = Self::partition_archive_rows_parallel(keys, rows, depth);
4270 return unsafe {
4273 Self::build_archive_partition_children(keys, hashes, &mut permuted, &plan)
4274 };
4275 }
4276
4277 let plan = Self::partition_archive_rows(keys, rows, depth);
4278 let end_depth = plan.end_depth;
4279
4280 #[cfg(feature = "parallel")]
4281 if rows.len() >= Self::PARALLEL_PARTITION_THRESHOLD {
4282 return unsafe { Self::build_archive_partition_children(keys, hashes, rows, &plan) };
4284 }
4285
4286 let first_bucket = plan.buckets[0];
4287 let second_bucket = plan.buckets[1];
4288 let first_end = plan.ends[first_bucket as usize] as usize;
4289 let (first_head, first_hash) = unsafe {
4290 Self::build_archive_partition_head(keys, hashes, &mut rows[..first_end], end_depth + 1)
4291 };
4292 let second_end = plan.ends[second_bucket as usize] as usize;
4293 let (second_head, second_hash) = unsafe {
4294 Self::build_archive_partition_head(
4295 keys,
4296 hashes,
4297 &mut rows[first_end..second_end],
4298 end_depth + 1,
4299 )
4300 };
4301 let first_count = first_head.count();
4302 let second_count = second_head.count();
4303
4304 let body = if plan.initial_slots == 2 {
4305 Branch::new_with_child_hashes(
4306 end_depth,
4307 first_head.with_key(first_bucket),
4308 second_head.with_key(second_bucket),
4309 first_hash,
4310 second_hash,
4311 )
4312 } else {
4313 Branch::new_with_child_hashes_capacity(
4314 end_depth,
4315 first_head.with_key(first_bucket),
4316 second_head.with_key(second_bucket),
4317 first_hash,
4318 second_hash,
4319 plan.initial_slots,
4320 )
4321 };
4322 let mut root = Head::new(0, body);
4323 let representative = &keys[rows[0] as usize];
4324 let mut hash_state = H::begin_branch(
4325 representative,
4326 &O::TREE_TO_KEY,
4327 end_depth,
4328 plan.fanout,
4329 rows.len() as u64,
4330 );
4331 H::push_child(&mut hash_state, first_bucket, first_count, first_hash);
4332 H::push_child(&mut hash_state, second_bucket, second_count, second_hash);
4333 if plan.fanout == 2 {
4334 debug_assert_eq!(second_end, rows.len());
4335 return (root, H::finish_branch(hash_state));
4336 }
4337
4338 let mut editor = BranchMut::from_head(&mut root);
4339 let mut range_start = second_end;
4340 for &byte in &plan.buckets[2..plan.fanout] {
4341 let range_end = plan.ends[byte as usize] as usize;
4342 let (child, child_hash) = unsafe {
4343 Self::build_archive_partition_head(
4344 keys,
4345 hashes,
4346 &mut rows[range_start..range_end],
4347 end_depth + 1,
4348 )
4349 };
4350 let child_count = child.count();
4351 H::push_child(&mut hash_state, byte, child_count, child_hash);
4352 editor.install_child_growing(child.with_key(byte));
4353 range_start = range_end;
4354 }
4355 debug_assert_eq!(range_start, rows.len());
4356
4357 let hash = H::finish_branch(hash_state);
4361 editor.finish_bulk_aggregates(hash);
4362 drop(editor);
4363 (root, hash)
4364 }
4365
4366 #[cfg(feature = "parallel")]
4378 unsafe fn build_archive_partition_children(
4379 keys: &[[u8; KEY_LEN]],
4380 hashes: &[H::Digest],
4381 rows: &mut [u32],
4382 plan: &ArchivePartitionPlan,
4383 ) -> (Head<KEY_LEN, O, (), H>, H::Digest) {
4384 use rayon::prelude::*;
4385
4386 let end_depth = plan.end_depth;
4387 let mut remaining: &mut [u32] = rows;
4388 let mut intervals: Vec<(u8, &mut [u32])> = Vec::with_capacity(plan.fanout);
4389 let mut previous_end = 0usize;
4390 for &byte in &plan.buckets[..plan.fanout] {
4391 let end = plan.ends[byte as usize] as usize;
4392 let (child, rest) = remaining.split_at_mut(end - previous_end);
4393 intervals.push((byte, child));
4394 remaining = rest;
4395 previous_end = end;
4396 }
4397 debug_assert!(remaining.is_empty());
4398
4399 let children: Vec<(u8, Head<KEY_LEN, O, (), H>, H::Digest)> = intervals
4400 .into_par_iter()
4401 .map(|(byte, child_rows)| {
4402 let (head, hash) = unsafe {
4405 Self::build_archive_partition_head(keys, hashes, child_rows, end_depth + 1)
4406 };
4407 (byte, head, hash)
4408 })
4409 .collect();
4410
4411 Self::assemble_partition_branch(end_depth, plan.initial_slots, children)
4412 }
4413
4414 #[cfg(feature = "parallel")]
4428 fn partition_archive_rows_parallel(
4429 keys: &[[u8; KEY_LEN]],
4430 rows: &[u32],
4431 depth: usize,
4432 ) -> (ArchivePartitionPlan, Vec<u32>) {
4433 use rayon::prelude::*;
4434
4435 let workers = Self::partition_workers(rows.len());
4436 let stride = rows.len().div_ceil(workers).max(1);
4437
4438 let representative = &keys[rows[0] as usize];
4442 let end_depth = rows[1..]
4443 .par_chunks(stride)
4444 .map(|chunk| {
4445 let mut shortest = KEY_LEN;
4446 for &row in chunk {
4447 let key = &keys[row as usize];
4448 let mut candidate_depth = depth;
4449 while candidate_depth < shortest {
4450 let key_index = O::TREE_TO_KEY[candidate_depth];
4451 if representative[key_index] != key[key_index] {
4452 shortest = candidate_depth;
4453 break;
4454 }
4455 candidate_depth += 1;
4456 }
4457 if shortest == depth {
4458 break;
4459 }
4460 }
4461 shortest
4462 })
4463 .min()
4464 .unwrap_or(KEY_LEN);
4465 assert!(
4466 end_depth < KEY_LEN,
4467 "duplicate archive keys cannot form a finite trie",
4468 );
4469
4470 let key_index = O::TREE_TO_KEY[end_depth];
4471 let histograms: Vec<[u32; 256]> = rows
4472 .par_chunks(stride)
4473 .map(|chunk| {
4474 let mut counts = [0u32; 256];
4475 for &row in chunk {
4476 counts[keys[row as usize][key_index] as usize] += 1;
4477 }
4478 counts
4479 })
4480 .collect();
4481
4482 let mut totals = [0u32; 256];
4483 for counts in &histograms {
4484 for (total, count) in totals.iter_mut().zip(counts.iter()) {
4485 *total += count;
4486 }
4487 }
4488
4489 let mut buckets = [0u8; 256];
4490 let mut fanout = 0usize;
4491 let mut ends = [0u32; 256];
4492 let mut bases = [0u32; 256];
4493 let mut offset = 0u32;
4494 for (byte, &total) in totals.iter().enumerate() {
4495 if total == 0 {
4496 continue;
4497 }
4498 buckets[fanout] = byte as u8;
4499 fanout += 1;
4500 bases[byte] = offset;
4501 offset += total;
4502 ends[byte] = offset;
4503 }
4504 debug_assert_eq!(offset as usize, rows.len());
4505 debug_assert!((2..=256).contains(&fanout));
4506 let initial_slots = if fanout == 2 {
4507 2
4508 } else {
4509 fanout.next_power_of_two()
4510 };
4511
4512 let mut cursors: Vec<[u32; 256]> = vec![[0u32; 256]; histograms.len()];
4515 let mut running = bases;
4516 for (cursor, counts) in cursors.iter_mut().zip(histograms.iter()) {
4517 for &byte in &buckets[..fanout] {
4518 let byte = byte as usize;
4519 cursor[byte] = running[byte];
4520 running[byte] += counts[byte];
4521 }
4522 }
4523
4524 let mut permuted: Vec<u32> = Vec::with_capacity(rows.len());
4525 let scatter = parallel_union::ScatterPtr(permuted.as_mut_ptr());
4526 rows.par_chunks(stride)
4527 .zip(cursors.into_par_iter())
4528 .for_each(|(chunk, mut cursor)| {
4529 for &row in chunk {
4530 let byte = keys[row as usize][key_index] as usize;
4531 let slot = cursor[byte] as usize;
4532 unsafe { scatter.write_at(slot, row) };
4536 cursor[byte] += 1;
4537 }
4538 });
4539 unsafe { permuted.set_len(rows.len()) };
4542
4543 (
4544 ArchivePartitionPlan {
4545 end_depth,
4546 ends,
4547 buckets,
4548 fanout,
4549 initial_slots,
4550 },
4551 permuted,
4552 )
4553 }
4554
4555 fn assemble_partition_branch(
4563 end_depth: usize,
4564 initial_slots: usize,
4565 children: Vec<(u8, Head<KEY_LEN, O, (), H>, H::Digest)>,
4566 ) -> (Head<KEY_LEN, O, (), H>, H::Digest) {
4567 debug_assert!(children.len() >= 2);
4568 debug_assert!(children.windows(2).all(|pair| pair[0].0 < pair[1].0));
4569 let child_count = children.len();
4570 let leaf_count = children.iter().map(|(_, child, _)| child.count()).sum();
4571 let mut hash_state = H::begin_branch(
4572 children[0].1.childleaf_key(),
4573 &O::TREE_TO_KEY,
4574 end_depth,
4575 child_count,
4576 leaf_count,
4577 );
4578 for &(edge, ref child, digest) in &children {
4579 H::push_child(&mut hash_state, edge, child.count(), digest);
4580 }
4581 let hash = H::finish_branch(hash_state);
4582
4583 let mut drain = children.into_iter();
4584 let (first_bucket, first_head, _) = drain.next().expect("two children");
4585 let (second_bucket, second_head, _) = drain.next().expect("two children");
4586 let body = if initial_slots == 2 {
4587 Branch::new_with_known_hash(
4588 end_depth,
4589 first_head.with_key(first_bucket),
4590 second_head.with_key(second_bucket),
4591 hash,
4592 )
4593 } else {
4594 Branch::new_with_known_hash_capacity(
4595 end_depth,
4596 first_head.with_key(first_bucket),
4597 second_head.with_key(second_bucket),
4598 hash,
4599 initial_slots,
4600 )
4601 };
4602 let mut root = Head::new(0, body);
4603 let mut extra = drain.peekable();
4604 if extra.peek().is_none() {
4605 return (root, hash);
4606 }
4607 let mut editor = BranchMut::from_head(&mut root);
4608 for (byte, child, _) in extra {
4609 editor.install_child_growing(child.with_key(byte));
4610 }
4611 editor.finish_bulk_aggregates(hash);
4612 drop(editor);
4613 (root, hash)
4614 }
4615
4616 #[cfg(any(test, feature = "parallel"))]
4622 fn partition_archive_rows(
4623 keys: &[[u8; KEY_LEN]],
4624 rows: &mut [u32],
4625 depth: usize,
4626 ) -> ArchivePartitionPlan {
4627 let representative = &keys[rows[0] as usize];
4630 let mut end_depth = KEY_LEN;
4631 for &row in &rows[1..] {
4632 let key = &keys[row as usize];
4633 let mut candidate_depth = depth;
4634 while candidate_depth < end_depth {
4635 let key_index = O::TREE_TO_KEY[candidate_depth];
4636 if representative[key_index] != key[key_index] {
4637 end_depth = candidate_depth;
4638 break;
4639 }
4640 candidate_depth += 1;
4641 }
4642 if end_depth == depth {
4643 break;
4644 }
4645 }
4646 assert!(
4647 end_depth < KEY_LEN,
4648 "duplicate archive keys cannot form a finite trie",
4649 );
4650
4651 let key_index = O::TREE_TO_KEY[end_depth];
4652 let mut ends = [0u32; 256];
4653 let mut occupied = ByteSet::new_empty();
4654 for &row in rows.iter() {
4655 let byte = keys[row as usize][key_index];
4656 let count = &mut ends[byte as usize];
4657 if *count == 0 {
4658 occupied.insert(byte);
4659 }
4660 *count += 1;
4661 }
4662
4663 let mut buckets = [0u8; 256];
4664 let mut fanout = 0usize;
4665 let mut listing = occupied;
4666 while let Some(byte) = listing.drain_next_ascending() {
4667 buckets[fanout] = byte;
4668 fanout += 1;
4669 }
4670 debug_assert!((2..=256).contains(&fanout));
4671 let initial_slots = if fanout == 2 {
4672 2
4673 } else {
4674 fanout.next_power_of_two()
4675 };
4676
4677 let mut next = [0u32; 256];
4680 let mut offset = 0u32;
4681 for &byte in &buckets[..fanout] {
4682 let count = ends[byte as usize];
4683 next[byte as usize] = offset;
4684 offset += count;
4685 ends[byte as usize] = offset;
4686 }
4687 debug_assert_eq!(offset as usize, rows.len());
4688
4689 for &byte in &buckets[..fanout] {
4692 let bucket = byte as usize;
4693 while next[bucket] < ends[bucket] {
4694 let position = next[bucket] as usize;
4695 let row = rows[position] as usize;
4696 let destination = keys[row][key_index] as usize;
4697 if destination == bucket {
4698 next[bucket] += 1;
4699 } else {
4700 let destination_slot = next[destination] as usize;
4701 debug_assert!(destination_slot < ends[destination] as usize);
4702 rows.swap(position, destination_slot);
4703 next[destination] += 1;
4704 }
4705 }
4706 }
4707
4708 ArchivePartitionPlan {
4709 end_depth,
4710 ends,
4711 buckets,
4712 fanout,
4713 initial_slots,
4714 }
4715 }
4716}
4717
4718#[cfg(any(test, feature = "parallel"))]
4720struct ArchivePartitionPlan {
4721 end_depth: usize,
4723 ends: [u32; 256],
4725 buckets: [u8; 256],
4727 fanout: usize,
4728 initial_slots: usize,
4730}
4731
4732impl<const KEY_LEN: usize, O, V, H> PartialEq for PATCH<KEY_LEN, O, V, H>
4736where
4737 O: KeySchema<KEY_LEN>,
4738 H: PatchHash,
4739{
4740 fn eq(&self, other: &Self) -> bool {
4741 self.root.as_ref().map(|root| root.hash()) == other.root.as_ref().map(|root| root.hash())
4742 }
4743}
4744
4745impl<const KEY_LEN: usize, O, V, H> PartialOrd for PATCH<KEY_LEN, O, V, H>
4754where
4755 O: KeySchema<KEY_LEN>,
4756 H: PatchHash,
4757{
4758 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
4759 match (&self.root, &other.root) {
4760 (None, None) => Some(Ordering::Equal),
4761 (None, Some(_)) => Some(Ordering::Less),
4762 (Some(_), None) => Some(Ordering::Greater),
4763 (Some(root), Some(other_root)) => root.inclusion(other_root, 0),
4764 }
4765 }
4766}
4767
4768impl<const KEY_LEN: usize, O, V, H> Eq for PATCH<KEY_LEN, O, V, H>
4769where
4770 O: KeySchema<KEY_LEN>,
4771 H: PatchHash,
4772{
4773}
4774
4775impl<'a, const KEY_LEN: usize, O, V, H> IntoIterator for &'a PATCH<KEY_LEN, O, V, H>
4776where
4777 O: KeySchema<KEY_LEN>,
4778 H: PatchHash,
4779{
4780 type Item = &'a [u8; KEY_LEN];
4781 type IntoIter = PATCHIterator<'a, KEY_LEN, O, V, H>;
4782
4783 fn into_iter(self) -> Self::IntoIter {
4784 PATCHIterator::new(self)
4785 }
4786}
4787
4788pub struct PATCHIterator<
4791 'a,
4792 const KEY_LEN: usize,
4793 O: KeySchema<KEY_LEN>,
4794 V,
4795 H: PatchHash = XorSip128,
4796> {
4797 stack: ArrayVec<std::slice::Iter<'a, Option<Head<KEY_LEN, O, V, H>>>, KEY_LEN>,
4800 pending_leaf: Option<&'a [u8; KEY_LEN]>,
4802 remaining: usize,
4803}
4804
4805impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
4806 PATCHIterator<'a, KEY_LEN, O, V, H>
4807{
4808 pub fn new(patch: &'a PATCH<KEY_LEN, O, V, H>) -> Self {
4810 let mut r = PATCHIterator {
4811 stack: ArrayVec::new(),
4812 pending_leaf: None,
4813 remaining: patch.len().min(usize::MAX as u64) as usize,
4814 };
4815 if let Some(root) = &patch.root {
4816 match root.body_ref() {
4817 BodyRef::Leaf(leaf) => r.pending_leaf = Some(&leaf.key),
4818 BodyRef::LocalLeaf(key) => r.pending_leaf = Some(key),
4819 BodyRef::Branch(branch) => r.stack.push(branch.child_table.iter()),
4820 }
4821 }
4822 r
4823 }
4824}
4825
4826impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Iterator
4827 for PATCHIterator<'a, KEY_LEN, O, V, H>
4828{
4829 type Item = &'a [u8; KEY_LEN];
4830
4831 fn next(&mut self) -> Option<Self::Item> {
4832 if let Some(key) = self.pending_leaf.take() {
4833 self.remaining = self.remaining.saturating_sub(1);
4834 return Some(key);
4835 }
4836 let mut iter = self.stack.last_mut()?;
4837 loop {
4838 if let Some(child) = iter.next() {
4839 if let Some(child) = child {
4840 match child.body_ref() {
4841 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => {
4842 self.remaining = self.remaining.saturating_sub(1);
4843 return Some(child.childleaf_key());
4845 }
4846 BodyRef::Branch(branch) => {
4847 self.stack.push(branch.child_table.iter());
4848 iter = self.stack.last_mut()?;
4849 }
4850 }
4851 }
4852 } else {
4853 self.stack.pop();
4854 iter = self.stack.last_mut()?;
4855 }
4856 }
4857 }
4858
4859 fn size_hint(&self) -> (usize, Option<usize>) {
4860 (self.remaining, Some(self.remaining))
4861 }
4862}
4863
4864impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> ExactSizeIterator
4865 for PATCHIterator<'a, KEY_LEN, O, V, H>
4866{
4867}
4868
4869impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> std::iter::FusedIterator
4870 for PATCHIterator<'a, KEY_LEN, O, V, H>
4871{
4872}
4873
4874pub struct PATCHOrderedIterator<
4881 'a,
4882 const KEY_LEN: usize,
4883 O: KeySchema<KEY_LEN>,
4884 V,
4885 H: PatchHash = XorSip128,
4886> {
4887 stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V, H>, 256>>,
4888 remaining: usize,
4889}
4890
4891impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
4892 PATCHOrderedIterator<'a, KEY_LEN, O, V, H>
4893{
4894 pub fn new(patch: &'a PATCH<KEY_LEN, O, V, H>) -> Self {
4895 let mut r = PATCHOrderedIterator {
4896 stack: Vec::with_capacity(KEY_LEN),
4897 remaining: patch.len().min(usize::MAX as u64) as usize,
4898 };
4899 if let Some(root) = &patch.root {
4900 r.stack.push(ArrayVec::new());
4901 match root.body_ref() {
4902 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => {
4903 r.stack[0].push(root);
4904 }
4905 BodyRef::Branch(branch) => {
4906 let first_level = &mut r.stack[0];
4907 first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
4908 first_level.sort_unstable_by_key(|&k| Reverse(k.key())); }
4910 }
4911 }
4912 r
4913 }
4914}
4915
4916pub struct PATCHIntoIterator<
4920 const KEY_LEN: usize,
4921 O: KeySchema<KEY_LEN>,
4922 V,
4923 H: PatchHash = XorSip128,
4924> {
4925 queue: Vec<Head<KEY_LEN, O, V, H>>,
4927 remaining: usize,
4928 _owners: Option<Arc<OwnerCover>>,
4929}
4930
4931impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
4932 PATCHIntoIterator<KEY_LEN, O, V, H>
4933{
4934}
4935
4936impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Iterator
4937 for PATCHIntoIterator<KEY_LEN, O, V, H>
4938{
4939 type Item = [u8; KEY_LEN];
4940
4941 fn next(&mut self) -> Option<Self::Item> {
4942 let q = &mut self.queue;
4943 while let Some(mut head) = q.pop() {
4944 match head.body_mut() {
4949 BodyMut::Leaf(leaf) => {
4950 self.remaining = self.remaining.saturating_sub(1);
4951 return Some(leaf.key);
4952 }
4953 BodyMut::LocalLeaf(bytes) => {
4954 self.remaining = self.remaining.saturating_sub(1);
4955 return Some(*bytes);
4956 }
4957 BodyMut::Branch(branch) => {
4958 for slot in branch.child_table.iter_mut().rev() {
4959 if let Some(c) = slot.take() {
4960 q.push(c);
4961 }
4962 }
4963 }
4964 }
4965 }
4966 None
4967 }
4968}
4969
4970pub struct PATCHIntoOrderedIterator<
4972 const KEY_LEN: usize,
4973 O: KeySchema<KEY_LEN>,
4974 V,
4975 H: PatchHash = XorSip128,
4976> {
4977 queue: Vec<Head<KEY_LEN, O, V, H>>,
4979 remaining: usize,
4980 _owners: Option<Arc<OwnerCover>>,
4981}
4982
4983impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Iterator
4984 for PATCHIntoOrderedIterator<KEY_LEN, O, V, H>
4985{
4986 type Item = [u8; KEY_LEN];
4987
4988 fn next(&mut self) -> Option<Self::Item> {
4989 let q = &mut self.queue;
4990 while let Some(mut head) = q.pop() {
4991 match head.body_mut() {
4995 BodyMut::Leaf(leaf) => {
4996 self.remaining = self.remaining.saturating_sub(1);
4997 return Some(leaf.key);
4998 }
4999 BodyMut::LocalLeaf(bytes) => {
5000 self.remaining = self.remaining.saturating_sub(1);
5001 return Some(*bytes);
5002 }
5003 BodyMut::Branch(branch) => {
5004 let slice: &mut [Option<Head<KEY_LEN, O, V, H>>] = &mut branch.child_table;
5005 slice
5013 .sort_unstable_by_key(|opt| (opt.is_none(), opt.as_ref().map(|h| h.key())));
5014 for slot in slice.iter_mut().rev() {
5015 if let Some(c) = slot.take() {
5016 q.push(c);
5017 }
5018 }
5019 }
5020 }
5021 }
5022 None
5023 }
5024}
5025
5026impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> IntoIterator
5027 for PATCH<KEY_LEN, O, V, H>
5028{
5029 type Item = [u8; KEY_LEN];
5030 type IntoIter = PATCHIntoIterator<KEY_LEN, O, V, H>;
5031
5032 fn into_iter(self) -> Self::IntoIter {
5033 let remaining = self.len().min(usize::MAX as u64) as usize;
5034 let PATCH { root, owners } = self;
5035 let mut q = Vec::new();
5036 if let Some(root) = root {
5037 q.push(root);
5038 }
5039 PATCHIntoIterator {
5040 queue: q,
5041 remaining,
5042 _owners: owners,
5043 }
5044 }
5045}
5046
5047impl<const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> PATCH<KEY_LEN, O, V, H> {
5048 pub fn into_iter_ordered(self) -> PATCHIntoOrderedIterator<KEY_LEN, O, V, H> {
5050 let remaining = self.len().min(usize::MAX as u64) as usize;
5051 let PATCH { root, owners } = self;
5052 let mut q = Vec::new();
5053 if let Some(root) = root {
5054 q.push(root);
5055 }
5056 PATCHIntoOrderedIterator {
5057 queue: q,
5058 remaining,
5059 _owners: owners,
5060 }
5061 }
5062
5063 pub fn into_prefixes<const PREFIX_LEN: usize>(
5069 self,
5070 ) -> PATCHIntoPrefixSetIterator<KEY_LEN, PREFIX_LEN, O, V, H> {
5071 const {
5072 assert!(PREFIX_LEN > 0, "a prefix set needs at least one byte");
5073 assert!(PREFIX_LEN <= KEY_LEN);
5074 if PREFIX_LEN < KEY_LEN {
5075 assert!(
5076 <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
5077 [O::TREE_TO_KEY[PREFIX_LEN - 1]]
5078 != <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
5079 [O::TREE_TO_KEY[PREFIX_LEN]],
5080 "PREFIX_LEN must align to a segment boundary",
5081 );
5082 }
5083 }
5084
5085 let PATCH { root, owners } = self;
5086 let mut queue = Vec::new();
5087 if let Some(root) = root {
5088 queue.push(root);
5089 }
5090 PATCHIntoPrefixSetIterator {
5091 queue,
5092 _owners: owners,
5093 }
5094 }
5095}
5096
5097pub struct PATCHIntoPrefixSetIterator<
5103 const KEY_LEN: usize,
5104 const PREFIX_LEN: usize,
5105 O: KeySchema<KEY_LEN>,
5106 V,
5107 H: PatchHash = XorSip128,
5108> {
5109 queue: Vec<Head<KEY_LEN, O, V, H>>,
5111 _owners: Option<Arc<OwnerCover>>,
5112}
5113
5114impl<const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Iterator
5115 for PATCHIntoPrefixSetIterator<KEY_LEN, PREFIX_LEN, O, V, H>
5116{
5117 type Item = [u8; PREFIX_LEN];
5118
5119 fn next(&mut self) -> Option<Self::Item> {
5120 while let Some(head) = self.queue.pop() {
5121 if head.end_depth() >= PREFIX_LEN {
5122 let key = O::tree_ordered(head.childleaf_key());
5123 return Some(key[..PREFIX_LEN].try_into().unwrap());
5124 }
5125
5126 let BodyRef::Branch(branch) = head.body_ref() else {
5127 unreachable!("a leaf cannot end before a valid prefix boundary");
5128 };
5129 let mut children = ArrayVec::<&Head<KEY_LEN, O, V, H>, 256>::new();
5133 children.extend(branch.child_table.iter().filter_map(Option::as_ref));
5134 children.sort_unstable_by_key(|child| child.key());
5135 for child in children.into_iter().rev() {
5136 self.queue.push((*child).clone());
5137 }
5138 }
5139 None
5140 }
5141}
5142
5143impl<const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
5144 std::iter::FusedIterator for PATCHIntoPrefixSetIterator<KEY_LEN, PREFIX_LEN, O, V, H>
5145{
5146}
5147
5148impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> Iterator
5149 for PATCHOrderedIterator<'a, KEY_LEN, O, V, H>
5150{
5151 type Item = &'a [u8; KEY_LEN];
5152
5153 fn next(&mut self) -> Option<Self::Item> {
5154 let mut level = self.stack.last_mut()?;
5155 loop {
5156 if let Some(child) = level.pop() {
5157 match child.body_ref() {
5158 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => {
5159 self.remaining = self.remaining.saturating_sub(1);
5160 return Some(child.childleaf_key());
5161 }
5162 BodyRef::Branch(branch) => {
5163 self.stack.push(ArrayVec::new());
5164 level = self.stack.last_mut()?;
5165 level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
5166 level.sort_unstable_by_key(|&k| Reverse(k.key())); }
5168 }
5169 } else {
5170 self.stack.pop();
5171 level = self.stack.last_mut()?;
5172 }
5173 }
5174 }
5175
5176 fn size_hint(&self) -> (usize, Option<usize>) {
5177 (self.remaining, Some(self.remaining))
5178 }
5179}
5180
5181impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> ExactSizeIterator
5182 for PATCHOrderedIterator<'a, KEY_LEN, O, V, H>
5183{
5184}
5185
5186impl<'a, const KEY_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash> std::iter::FusedIterator
5187 for PATCHOrderedIterator<'a, KEY_LEN, O, V, H>
5188{
5189}
5190
5191#[derive(Clone, Copy)]
5197pub struct PATCHPrefixSet<
5198 'a,
5199 const KEY_LEN: usize,
5200 const PREFIX_LEN: usize,
5201 O: KeySchema<KEY_LEN>,
5202 V,
5203 H: PatchHash = XorSip128,
5204> {
5205 patch: &'a PATCH<KEY_LEN, O, V, H>,
5206}
5207
5208impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
5209 PATCHPrefixSet<'a, KEY_LEN, PREFIX_LEN, O, V, H>
5210{
5211 fn new(patch: &'a PATCH<KEY_LEN, O, V, H>) -> Self {
5212 const {
5213 assert!(PREFIX_LEN > 0, "a prefix set needs at least one byte");
5214 assert!(PREFIX_LEN <= KEY_LEN);
5215 if PREFIX_LEN < KEY_LEN {
5216 assert!(
5217 <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
5218 [O::TREE_TO_KEY[PREFIX_LEN - 1]]
5219 != <O as KeySchema<KEY_LEN>>::Segmentation::SEGMENTS
5220 [O::TREE_TO_KEY[PREFIX_LEN]],
5221 "PREFIX_LEN must align to a segment boundary",
5222 );
5223 }
5224 }
5225 Self { patch }
5226 }
5227
5228 pub fn contains(&self, prefix: &[u8; PREFIX_LEN]) -> bool {
5230 self.patch.has_prefix(prefix)
5231 }
5232
5233 pub fn iter(&self) -> PATCHPrefixSetIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H> {
5235 PATCHPrefixSetIterator {
5236 inner: self.patch.iter_prefix_count(),
5237 }
5238 }
5239
5240 pub fn is_empty(&self) -> bool {
5242 self.patch.is_empty()
5243 }
5244
5245 pub fn intersection<OH: PatchHash>(
5250 &self,
5251 other: &PATCH<PREFIX_LEN, IdentitySchema, (), OH>,
5252 ) -> PATCH<PREFIX_LEN, IdentitySchema, (), OH> {
5253 let keys = other
5254 .iter_ordered()
5255 .filter(|key| self.contains(key))
5256 .copied()
5257 .collect();
5258 PATCH::from_owned_keys(keys)
5259 }
5260}
5261
5262pub struct PATCHPrefixSetIterator<
5264 'a,
5265 const KEY_LEN: usize,
5266 const PREFIX_LEN: usize,
5267 O: KeySchema<KEY_LEN>,
5268 V,
5269 H: PatchHash = XorSip128,
5270> {
5271 inner: PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H>,
5272}
5273
5274impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
5275 Iterator for PATCHPrefixSetIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H>
5276{
5277 type Item = [u8; PREFIX_LEN];
5278
5279 fn next(&mut self) -> Option<Self::Item> {
5280 self.inner.next().map(|(prefix, _count)| prefix)
5281 }
5282}
5283
5284impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
5285 std::iter::FusedIterator for PATCHPrefixSetIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H>
5286{
5287}
5288
5289pub struct PATCHPrefixIterator<
5292 'a,
5293 const KEY_LEN: usize,
5294 const PREFIX_LEN: usize,
5295 O: KeySchema<KEY_LEN>,
5296 V,
5297 H: PatchHash = XorSip128,
5298> {
5299 stack: Vec<ArrayVec<&'a Head<KEY_LEN, O, V, H>, 256>>,
5300}
5301
5302impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
5303 PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H>
5304{
5305 fn new(patch: &'a PATCH<KEY_LEN, O, V, H>) -> Self {
5306 const {
5307 assert!(PREFIX_LEN <= KEY_LEN);
5308 }
5309 let mut r = PATCHPrefixIterator {
5310 stack: Vec::with_capacity(PREFIX_LEN),
5311 };
5312 if let Some(root) = &patch.root {
5313 r.stack.push(ArrayVec::new());
5314 if root.end_depth() >= PREFIX_LEN {
5315 r.stack[0].push(root);
5316 } else {
5317 let BodyRef::Branch(branch) = root.body_ref() else {
5318 unreachable!();
5319 };
5320 let first_level = &mut r.stack[0];
5321 first_level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
5322 first_level.sort_unstable_by_key(|&k| Reverse(k.key())); }
5324 }
5325 r
5326 }
5327}
5328
5329impl<'a, const KEY_LEN: usize, const PREFIX_LEN: usize, O: KeySchema<KEY_LEN>, V, H: PatchHash>
5330 Iterator for PATCHPrefixIterator<'a, KEY_LEN, PREFIX_LEN, O, V, H>
5331{
5332 type Item = ([u8; PREFIX_LEN], u64);
5333
5334 fn next(&mut self) -> Option<Self::Item> {
5335 let mut level = self.stack.last_mut()?;
5336 loop {
5337 if let Some(child) = level.pop() {
5338 if child.end_depth() >= PREFIX_LEN {
5339 let key = O::tree_ordered(child.childleaf_key());
5340 let suffix_count = child.count();
5341 return Some((key[0..PREFIX_LEN].try_into().unwrap(), suffix_count));
5342 } else {
5343 let BodyRef::Branch(branch) = child.body_ref() else {
5344 unreachable!();
5345 };
5346 self.stack.push(ArrayVec::new());
5347 level = self.stack.last_mut()?;
5348 level.extend(branch.child_table.iter().filter_map(|c| c.as_ref()));
5349 level.sort_unstable_by_key(|&k| Reverse(k.key())); }
5351 } else {
5352 self.stack.pop();
5353 level = self.stack.last_mut()?;
5354 }
5355 }
5356 }
5357}
5358
5359#[cfg(test)]
5360mod tests {
5361 use super::*;
5362 use itertools::Itertools;
5363 use proptest::prelude::*;
5364 use std::collections::HashSet;
5365 use std::convert::TryInto;
5366 use std::iter::FromIterator;
5367 use std::mem;
5368 use std::sync::atomic::{AtomicUsize, Ordering};
5369
5370 #[repr(C, align(16))]
5371 struct AlignedArchivePair([[u8; 16]; 2]);
5372
5373 #[repr(C, align(16))]
5374 struct AlignedArchiveKey<const KEY_LEN: usize>([u8; KEY_LEN]);
5375
5376 fn blake_patch<const KEY_LEN: usize>(
5377 keys: &[[u8; KEY_LEN]],
5378 ) -> PATCH<KEY_LEN, IdentitySchema, (), Blake3Merkle> {
5379 let mut patch = PATCH::new();
5380 for key in keys {
5381 patch.insert(&Entry::<KEY_LEN, (), Blake3Merkle>::new(key));
5382 }
5383 patch
5384 }
5385
5386 fn inventory_keys<const KEY_LEN: usize>(len: usize) -> Vec<[u8; KEY_LEN]> {
5387 assert!(KEY_LEN >= 8);
5388 (0..len)
5389 .map(|index| {
5390 let mut key = [0u8; KEY_LEN];
5391 key[..8].copy_from_slice(&(index as u64).to_be_bytes());
5392 let mut state = (index as u64) ^ 0x243f_6a88_85a3_08d3;
5393 for byte in &mut key[8..] {
5394 state ^= state >> 12;
5395 state ^= state << 25;
5396 state ^= state >> 27;
5397 *byte = state.wrapping_mul(0x2545_f491_4f6c_dd1d) as u8;
5398 }
5399 key
5400 })
5401 .collect()
5402 }
5403
5404 #[test]
5405 fn bulk_owned_build_canonicalizes_order_duplicates_and_edit_history() {
5406 let keys = inventory_keys::<16>(4_097);
5407 let mut noisy = keys.clone();
5408 noisy.reverse();
5409 noisy.extend(keys.iter().step_by(7).copied());
5410 noisy.rotate_left(997);
5411
5412 let bulk = PATCH::<16, IdentitySchema, (), Blake3Merkle>::from_keys(noisy.clone());
5413 let bulk_reversed =
5414 PATCH::<16, IdentitySchema, (), Blake3Merkle>::from_keys(noisy.into_iter().rev());
5415 let inserted = blake_patch(&keys);
5416 let mut edited = blake_patch(&keys.iter().rev().copied().collect::<Vec<_>>());
5417 for key in keys.iter().step_by(5) {
5418 edited.remove(key);
5419 }
5420 for key in keys.iter().step_by(5).rev() {
5421 edited.insert(&Entry::new(key));
5422 }
5423
5424 let expected_root = inserted.merkle_root();
5425 assert_eq!(bulk.len(), keys.len() as u64);
5426 assert_eq!(bulk.merkle_root(), expected_root);
5427 assert_eq!(bulk_reversed.merkle_root(), expected_root);
5428 assert_eq!(edited.merkle_root(), expected_root);
5429 assert_eq!(bulk, inserted);
5430 assert_eq!(
5431 bulk.merkle_node(&[])
5432 .unwrap()
5433 .items_after(None, usize::MAX)
5434 .collect::<Vec<_>>(),
5435 keys
5436 );
5437 }
5438
5439 #[test]
5440 fn bulk_owned_build_handles_empty_singleton_and_already_canonical_input() {
5441 let empty = PATCH::<16, IdentitySchema, (), Blake3Merkle>::from_keys([]);
5442 assert!(empty.is_empty());
5443 assert_eq!(empty.merkle_root(), None);
5444
5445 let key = [42; 16];
5446 let singleton = PATCH::<16, IdentitySchema, (), Blake3Merkle>::from_keys([key]);
5447 assert_eq!(singleton.len(), 1);
5448 assert_eq!(singleton.merkle_node(&[]).unwrap().representative(), &key);
5449
5450 let canonical = inventory_keys::<16>(1_024);
5451 let bulk = PATCH::<16, IdentitySchema, (), Blake3Merkle>::from_keys(canonical.clone());
5452 assert_eq!(
5453 bulk.merkle_node(&[])
5454 .unwrap()
5455 .items_after(None, usize::MAX)
5456 .collect::<Vec<_>>(),
5457 canonical
5458 );
5459 }
5460
5461 static BULK_LEAF_HASHES: AtomicUsize = AtomicUsize::new(0);
5462 static BULK_BRANCH_HASHES: AtomicUsize = AtomicUsize::new(0);
5463
5464 struct CountingBlake3;
5465 impl sealed::Sealed for CountingBlake3 {}
5466 impl PatchHash for CountingBlake3 {
5467 type Digest = [u8; 32];
5468 type BranchState = blake3::Hasher;
5469 const COMMUTATIVE_BRANCH: bool = false;
5470 const INCREMENTAL_BRANCH: bool = false;
5471
5472 fn init() {
5473 Blake3Merkle::init();
5474 }
5475
5476 fn leaf(bytes: &[u8]) -> Self::Digest {
5477 BULK_LEAF_HASHES.fetch_add(1, Ordering::Relaxed);
5478 Blake3Merkle::leaf(bytes)
5479 }
5480
5481 fn begin_branch(
5482 representative: &[u8],
5483 tree_to_key: &[usize],
5484 end_depth: usize,
5485 child_count: usize,
5486 leaf_count: u64,
5487 ) -> Self::BranchState {
5488 Blake3Merkle::begin_branch(
5489 representative,
5490 tree_to_key,
5491 end_depth,
5492 child_count,
5493 leaf_count,
5494 )
5495 }
5496
5497 fn push_child(
5498 state: &mut Self::BranchState,
5499 edge: u8,
5500 leaf_count: u64,
5501 digest: Self::Digest,
5502 ) {
5503 Blake3Merkle::push_child(state, edge, leaf_count, digest);
5504 }
5505
5506 fn finish_branch(state: Self::BranchState) -> Self::Digest {
5507 BULK_BRANCH_HASHES.fetch_add(1, Ordering::Relaxed);
5508 Blake3Merkle::finish_branch(state)
5509 }
5510
5511 fn edit_branch(
5512 _current: Self::Digest,
5513 _edge: u8,
5514 _old: Option<Self::Digest>,
5515 _new: Option<Self::Digest>,
5516 ) -> Self::Digest {
5517 unreachable!("the counting Merkle policy is not incremental")
5518 }
5519 }
5520
5521 #[test]
5522 fn bulk_owned_build_hashes_each_final_node_once_plus_debug_audit() {
5523 BULK_LEAF_HASHES.store(0, Ordering::Relaxed);
5524 BULK_BRANCH_HASHES.store(0, Ordering::Relaxed);
5525 let keys = inventory_keys::<16>(10_000);
5526 let patch = PATCH::<16, IdentitySchema, (), CountingBlake3>::from_owned_keys(keys.clone());
5527 let (branches, _, heap_leaves, archive_leaves) = patch.node_stats();
5528
5529 assert_eq!(patch.len(), keys.len() as u64);
5530 assert_eq!(heap_leaves, keys.len() as u64);
5531 assert_eq!(archive_leaves, 0);
5532 assert_eq!(BULK_LEAF_HASHES.load(Ordering::Relaxed), keys.len());
5533 let expected_branch_hashes = branches as usize * if cfg!(debug_assertions) { 2 } else { 1 };
5537 assert_eq!(
5538 BULK_BRANCH_HASHES.load(Ordering::Relaxed),
5539 expected_branch_hashes
5540 );
5541 }
5542
5543 struct BulkUnwindProbe(Arc<AtomicUsize>);
5544
5545 impl Drop for BulkUnwindProbe {
5546 fn drop(&mut self) {
5547 self.0.fetch_add(1, Ordering::Relaxed);
5548 }
5549 }
5550
5551 #[test]
5552 fn wider_known_hash_branch_owns_every_child_during_unwind() {
5553 let drops = Arc::new(AtomicUsize::new(0));
5554 let keys = [[1, 0], [2, 0], [3, 0]];
5555 let digests = keys.map(|key| Blake3Merkle::leaf(&key));
5556 let mut state = Blake3Merkle::begin_branch(
5557 &keys[0],
5558 &<IdentitySchema as KeySchema<2>>::TREE_TO_KEY,
5559 0,
5560 keys.len(),
5561 keys.len() as u64,
5562 );
5563 for (edge, digest) in [1, 2, 3].into_iter().zip(digests) {
5564 Blake3Merkle::push_child(&mut state, edge, 1, digest);
5565 }
5566 let final_hash = Blake3Merkle::finish_branch(state);
5567
5568 let leaf = |key: &[u8; 2]| {
5569 unsafe {
5572 Leaf::<2, BulkUnwindProbe, Blake3Merkle>::new(key, BulkUnwindProbe(drops.clone()))
5573 }
5574 };
5575 type ProbeHead = Head<2, IdentitySchema, BulkUnwindProbe, Blake3Merkle>;
5576 let first = ProbeHead::new(0, leaf(&keys[0])).with_key(1);
5577 let second = ProbeHead::new(0, leaf(&keys[1])).with_key(2);
5578 let third = ProbeHead::new(0, leaf(&keys[2])).with_key(3);
5579 let body = Branch::new_with_known_hash_capacity(0, first, second, final_hash, 4);
5580 let mut root = Head::new(0, body);
5581
5582 let panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
5583 let mut editor = BranchMut::from_head(&mut root);
5584 editor.install_child_growing(third);
5585 panic!("interrupt wider bottom-up assembly");
5590 }));
5591 assert!(panic.is_err());
5592 drop(root);
5593 assert_eq!(drops.load(Ordering::Relaxed), keys.len());
5594 }
5595
5596 fn merkle_inventory<const KEY_LEN: usize, V>(
5597 node: PATCHMerkleNode<'_, KEY_LEN, V>,
5598 out: &mut Vec<(Vec<u8>, [u8; 32], u64, usize, [u8; KEY_LEN], Vec<u8>)>,
5599 ) {
5600 let child_edges = node.children().map(|(edge, _)| edge).collect::<Vec<_>>();
5601 out.push((
5602 node.prefix().to_vec(),
5603 node.digest(),
5604 node.leaf_count(),
5605 node.end_depth(),
5606 *node.representative(),
5607 child_edges,
5608 ));
5609 for (_, child) in node.children() {
5610 merkle_inventory(child, out);
5611 }
5612 }
5613
5614 #[test]
5615 fn merkle_prefix_lookup_canonicalizes_compressed_paths_and_orders_children() {
5616 let patch = blake_patch(&[[1, 2, 3, 255], [1, 2, 3, 0]]);
5617 let root = patch.merkle_node(&[]).expect("nonempty PATCH");
5618 assert_eq!(root.end_depth(), 3);
5619 assert_eq!(root.prefix(), &[1, 2, 3]);
5620 assert_eq!(root.leaf_count(), 2);
5621 assert!(!root.is_leaf());
5622
5623 for request in [&[][..], &[1][..], &[1, 2][..], &[1, 2, 3][..]] {
5624 let located = patch.merkle_node(request).expect("compressed prefix");
5625 assert_eq!(located.digest(), root.digest());
5626 assert_eq!(located.prefix(), &[1, 2, 3]);
5627 }
5628 assert!(patch.merkle_node(&[1, 2, 4]).is_none());
5629 assert!(patch.merkle_node(&[1, 2, 3, 0, 0]).is_none());
5630
5631 let children = root.children().collect::<Vec<_>>();
5632 assert_eq!(
5633 children.iter().map(|(edge, _)| *edge).collect::<Vec<_>>(),
5634 [0, 255]
5635 );
5636 for (edge, child) in children {
5637 assert!(child.is_leaf());
5638 assert_eq!(child.leaf_count(), 1);
5639 assert_eq!(child.end_depth(), 4);
5640 assert_eq!(child.representative()[3], edge);
5641 assert_eq!(child.prefix(), child.representative());
5642 assert_eq!(child.children().len(), 0);
5643 }
5644
5645 let debug = format!("{root:?}");
5646 assert!(debug.contains("PATCHMerkleNode"));
5647 assert!(!debug.contains("child_table"));
5648 assert!(!debug.contains("Branch"));
5649 }
5650
5651 #[test]
5652 fn merkle_prefix_lookup_reports_compressed_shape_mismatches_without_aliasing_nodes() {
5653 let compressed = blake_patch(&[[1, 2, 3, 0], [1, 2, 3, 255]]);
5654 let split_earlier = blake_patch(&[[1, 2, 3, 0], [1, 2, 4, 0]]);
5655
5656 let compressed_root = compressed.merkle_node(&[]).expect("root");
5657 assert_eq!(compressed_root.prefix(), &[1, 2, 3]);
5658 let corresponding = split_earlier
5659 .merkle_node(compressed_root.prefix())
5660 .expect("the shared key still exists");
5661 assert!(corresponding.is_leaf());
5662 assert_eq!(corresponding.prefix(), &[1, 2, 3, 0]);
5663 assert_ne!(corresponding.digest(), compressed_root.digest());
5664 assert_ne!(corresponding.leaf_count(), compressed_root.leaf_count());
5665
5666 let earlier_root = split_earlier.merkle_node(&[]).expect("root");
5667 assert_eq!(earlier_root.prefix(), &[1, 2]);
5668 let covered = compressed
5669 .merkle_node(earlier_root.prefix())
5670 .expect("request ends inside compressed path");
5671 assert_eq!(covered.prefix(), &[1, 2, 3]);
5672 assert_eq!(covered.digest(), compressed_root.digest());
5673 }
5674
5675 #[test]
5676 fn merkle_traversal_is_history_independent() {
5677 let keys: Vec<[u8; 4]> = (0u8..64)
5678 .map(|i| [i.wrapping_mul(73), i / 4, i.wrapping_mul(11), 255 - i])
5679 .collect();
5680 let forward = blake_patch(&keys);
5681 let mut reversed_keys = keys.clone();
5682 reversed_keys.reverse();
5683 let reversed = blake_patch(&reversed_keys);
5684 let mut edited = reversed.clone();
5685 for key in keys.iter().step_by(3) {
5686 edited.remove(key);
5687 }
5688 for key in keys.iter().step_by(3).rev() {
5689 edited.insert(&Entry::<4, (), Blake3Merkle>::new(key));
5690 }
5691
5692 let inventory = |patch: &PATCH<4, IdentitySchema, (), Blake3Merkle>| {
5693 let mut out = Vec::new();
5694 merkle_inventory(patch.merkle_node(&[]).expect("root"), &mut out);
5695 out
5696 };
5697 assert_eq!(inventory(&forward), inventory(&reversed));
5698 assert_eq!(inventory(&forward), inventory(&edited));
5699
5700 let mut expected = keys.clone();
5701 expected.sort_unstable();
5702 for patch in [&forward, &reversed, &edited] {
5703 let root = patch.merkle_node(&[]).expect("root");
5704 let mut paged = Vec::new();
5705 let mut after = None;
5706 loop {
5707 let page = root.items_after(after.as_ref(), 7).collect::<Vec<_>>();
5708 if page.is_empty() {
5709 break;
5710 }
5711 after = page.last().copied();
5712 paged.extend(page);
5713 }
5714 assert_eq!(paged, expected);
5715 }
5716 }
5717
5718 #[test]
5719 fn merkle_items_are_prefix_scoped_exclusive_and_hard_bounded() {
5720 let mut keys = Vec::new();
5721 for i in 0u8..32 {
5722 keys.push([7, i, i.wrapping_mul(17), 255 - i]);
5723 keys.push([8, i, 0, 0]);
5724 }
5725 let patch = blake_patch(&keys);
5726 let node = patch.merkle_node(&[7]).expect("prefix seven");
5727
5728 let mut empty = node.items_after(None, 0);
5729 assert_eq!(empty.size_hint(), (0, Some(0)));
5730 assert_eq!(empty.next(), None);
5731 assert_eq!(empty.next(), None);
5732
5733 let first_five = node.items_after(None, 5).collect::<Vec<_>>();
5734 assert_eq!(first_five.len(), 5);
5735 assert!(first_five.windows(2).all(|pair| pair[0] < pair[1]));
5736 assert!(first_five.iter().all(|key| key[0] == 7));
5737
5738 let cursor = [7, 4, 128, 0];
5739 let after = node.items_after(Some(&cursor), 3).collect::<Vec<_>>();
5740 assert_eq!(after.len(), 3);
5741 assert!(after.iter().all(|key| key > &cursor && key[0] == 7));
5742
5743 let exact = keys
5744 .iter()
5745 .copied()
5746 .filter(|key| key[0] == 7)
5747 .nth(12)
5748 .unwrap();
5749 let exclusive = node
5750 .items_after(Some(&exact), usize::MAX)
5751 .collect::<Vec<_>>();
5752 assert!(exclusive.iter().all(|key| key > &exact && key[0] == 7));
5753 assert!(!exclusive.contains(&exact));
5754 assert_eq!(exclusive.len(), 19);
5755
5756 assert_eq!(node.items_after(Some(&[255; 4]), 10).next(), None);
5757 let mut one = node.items_after(None, 1);
5758 assert_eq!(one.size_hint(), (0, Some(1)));
5759 assert!(one.next().is_some());
5760 assert_eq!(one.size_hint(), (0, Some(0)));
5761 assert_eq!(one.next(), None);
5762 }
5763
5764 #[test]
5765 fn merkle_views_do_not_require_or_expose_values() {
5766 struct NotDebug(u8);
5767
5768 let key = [9, 8, 7, 6];
5769 let entry = Entry::<4, NotDebug, Blake3Merkle>::with_value(&key, NotDebug(42));
5770 let mut patch = PATCH::<4, IdentitySchema, NotDebug, Blake3Merkle>::new();
5771 patch.insert(&entry);
5772 let node = patch.merkle_node(&[]).expect("root");
5773 assert_eq!(node.items_after(None, 1).collect::<Vec<_>>(), [key]);
5774 assert!(format!("{node:?}").contains("PATCHMerkleNode"));
5775 assert_eq!(entry.value().0, 42);
5776 }
5777
5778 #[test]
5779 fn blake3_merkle_authenticates_reconciliation_descriptor() {
5780 fn framed(representative: [u8; 16], leaf_count: u64, child_counts: [u64; 2]) -> [u8; 32] {
5781 let mut state = Blake3Merkle::begin_branch(
5782 &representative,
5783 &<IdentitySchema as KeySchema<16>>::TREE_TO_KEY,
5784 4,
5785 2,
5786 leaf_count,
5787 );
5788 Blake3Merkle::push_child(&mut state, 3, child_counts[0], [7; 32]);
5789 Blake3Merkle::push_child(&mut state, 9, child_counts[1], [11; 32]);
5790 Blake3Merkle::finish_branch(state)
5791 }
5792
5793 let representative = [5; 16];
5794 let canonical = framed(representative, 4, [1, 3]);
5795 assert_ne!(canonical, framed(representative, 5, [1, 3]));
5796 assert_ne!(canonical, framed(representative, 4, [2, 2]));
5797
5798 let mut different_prefix = representative;
5799 different_prefix[2] ^= 1;
5800 assert_ne!(canonical, framed(different_prefix, 4, [1, 3]));
5801
5802 let mut different_suffix = representative;
5803 different_suffix[7] ^= 1;
5804 assert_eq!(canonical, framed(different_suffix, 4, [1, 3]));
5805 }
5806
5807 #[test]
5808 fn blake3_merkle_is_history_independent_across_edits_and_set_operations() {
5809 let keys = [
5810 [0, 0, 0, 0],
5811 [0, 0, 1, 0],
5812 [0, 2, 0, 0],
5813 [3, 0, 0, 0],
5814 [3, 0, 0, 9],
5815 [255, 1, 2, 3],
5816 ];
5817
5818 let forward = blake_patch(&keys);
5819 let mut reversed_keys = keys;
5820 reversed_keys.reverse();
5821 let reversed = blake_patch(&reversed_keys);
5822 assert_eq!(forward.merkle_root(), reversed.merkle_root());
5823 assert_eq!(forward, reversed);
5824
5825 let mut edited = forward.clone();
5826 edited.remove(&keys[2]);
5827 edited.insert(&Entry::<4, (), Blake3Merkle>::new(&keys[2]));
5828 assert_eq!(edited.merkle_root(), forward.merkle_root());
5829
5830 let left = blake_patch(&keys[..4]);
5831 let right = blake_patch(&keys[2..]);
5832 let mut union = left.clone();
5833 union.union(right.clone());
5834 assert_eq!(union.merkle_root(), forward.merkle_root());
5835
5836 let expected_intersection = blake_patch(&keys[2..4]);
5837 assert_eq!(
5838 left.intersect(&right).merkle_root(),
5839 expected_intersection.merkle_root()
5840 );
5841
5842 let expected_difference = blake_patch(&keys[..2]);
5843 assert_eq!(
5844 left.difference(&right).merkle_root(),
5845 expected_difference.merkle_root()
5846 );
5847 }
5848
5849 #[test]
5850 fn blake3_merkle_heap_and_archive_construction_have_the_same_root() {
5851 #[repr(C, align(16))]
5852 struct AlignedBlakeArchive([[u8; 16]; 6]);
5853
5854 let storage = Arc::new(AlignedBlakeArchive([
5855 [0; 16], [1; 16], [2; 16], [3; 16], [17; 16], [255; 16],
5856 ]));
5857 let owner: Arc<dyn ArchiveOwner> = storage.clone();
5858 let hashes = storage.0.map(|key| Blake3Merkle::leaf(&key));
5859 let mut rows = [5, 3, 1, 4, 0, 2];
5860
5861 let archive = unsafe {
5865 PATCH::<16, IdentitySchema, (), Blake3Merkle>::from_archive_partition(
5866 &storage.0, &hashes, &mut rows, &owner,
5867 )
5868 };
5869 let heap = blake_patch(&storage.0);
5870
5871 assert_eq!(archive.merkle_root(), heap.merkle_root());
5872 assert_eq!(archive, heap);
5873 let archive_root = archive.merkle_node(&[]).expect("archive root");
5874 assert_eq!(archive_root.leaf_count(), 6);
5875 assert_eq!(
5876 archive_root
5877 .items_after(None, usize::MAX)
5878 .collect::<Vec<_>>(),
5879 storage.0
5880 );
5881 }
5882
5883 crate::key_segmentation!(PermutedInfixSegments, 12, [4, 4, 4]);
5884 crate::key_schema!(PermutedInfixSchema, PermutedInfixSegments, 12, [1, 2, 0]);
5885 crate::key_segmentation!(PrefixProjectionSegments, 6, [4, 2]);
5886 crate::key_schema!(PrefixProjectionSchema, PrefixProjectionSegments, 6, [0, 1]);
5887 crate::key_segmentation!(PrefixSharingBlobSegments, 40, [32, 8]);
5888 crate::key_schema!(
5889 PrefixSharingBlobSchema,
5890 PrefixSharingBlobSegments,
5891 40,
5892 [0, 1]
5893 );
5894
5895 #[test]
5896 fn shares_prefix_handles_empty_and_full_prefixes() {
5897 let empty = PATCH::<4, IdentitySchema>::new();
5898 let key = [1, 2, 3, 4];
5899 assert!(empty.shares_prefix(&empty.clone(), &[]));
5900 assert!(empty.shares_prefix(&empty.clone(), &key));
5901
5902 let mut populated = empty.clone();
5903 populated.insert(&Entry::new(&key));
5904 assert!(!empty.shares_prefix(&populated, &[]));
5905 assert!(!empty.shares_prefix(&populated, &key));
5906 assert!(!populated.shares_prefix(&empty, &[1, 2]));
5907 assert!(populated.shares_prefix(&empty, &[1, 9]));
5908 assert!(populated.shares_prefix(&populated.clone(), &[]));
5909 assert!(populated.shares_prefix(&populated.clone(), &key));
5910
5911 let mut rebuilt = PATCH::<4, IdentitySchema>::new();
5912 rebuilt.insert(&Entry::new(&key));
5913 assert_eq!(populated, rebuilt);
5914 assert!(!populated.shares_prefix(&rebuilt, &[]));
5915 assert!(!populated.shares_prefix(&rebuilt, &key));
5916 }
5917
5918 #[test]
5919 fn shares_prefix_retains_compressed_subtrees_after_unrelated_insertions() {
5920 let mut original = PATCH::<4, IdentitySchema>::new();
5921 original.insert(&Entry::new(&[1, 2, 3, 0]));
5922 original.insert(&Entry::new(&[1, 2, 3, 255]));
5923 assert_eq!(original.root.as_ref().unwrap().end_depth(), 3);
5924
5925 let mut outside = original.clone();
5926 outside.insert(&Entry::new(&[9, 8, 7, 6]));
5927 assert!(!original.shares_prefix(&outside, &[]));
5929 assert!(original.shares_prefix(&outside, &[1]));
5930 assert!(original.shares_prefix(&outside, &[1, 2]));
5931 assert!(original.shares_prefix(&outside, &[1, 2, 3]));
5932 assert!(original.shares_prefix(&outside, &[1, 2, 3, 0]));
5933 assert!(original.shares_prefix(&outside, &[1, 2, 4]));
5934
5935 let mut split = outside.clone();
5936 split.insert(&Entry::new(&[1, 2, 4, 0]));
5937 assert!(!outside.shares_prefix(&split, &[1]));
5938 assert!(!outside.shares_prefix(&split, &[1, 2]));
5939 assert!(!outside.shares_prefix(&split, &[1, 2, 4]));
5940 assert!(outside.shares_prefix(&split, &[1, 2, 3]));
5941 assert!(outside.shares_prefix(&split, &[9]));
5942
5943 let mut inside = split.clone();
5944 inside.insert(&Entry::new(&[1, 2, 3, 127]));
5945 assert!(!split.shares_prefix(&inside, &[1, 2, 3]));
5946 assert!(split.shares_prefix(&inside, &[1, 2, 3, 0]));
5947 assert!(split.shares_prefix(&inside, &[1, 2, 4]));
5948 }
5949
5950 #[test]
5951 fn shares_prefix_detects_an_additional_physical_blob_occurrence() {
5952 let physical_key = |hash: [u8; 32], offset: u64| {
5953 let mut key = [0; 40];
5954 key[..32].copy_from_slice(&hash);
5955 key[32..].copy_from_slice(&offset.to_be_bytes());
5956 key
5957 };
5958 let hash = [7; 32];
5959 let other_hash = [9; 32];
5960 let first = physical_key(hash, 512);
5961 let mut before = PATCH::<40, PrefixSharingBlobSchema>::new();
5962 before.insert(&Entry::new(&first));
5963 before.insert(&Entry::new(&physical_key(other_hash, 1024)));
5964 let mut after = before.clone();
5965 after.insert(&Entry::new(&physical_key(hash, 2048)));
5966
5967 assert_eq!(
5968 before.prefix_set::<32>().iter().collect::<Vec<_>>(),
5969 after.prefix_set::<32>().iter().collect::<Vec<_>>()
5970 );
5971 assert!(!before.shares_prefix(&after, &hash));
5972 assert!(before.shares_prefix(&after, &first));
5973 assert!(before.shares_prefix(&after, &other_hash));
5974 }
5975
5976 #[test]
5977 fn shares_prefix_observes_replaced_values_with_unchanged_keys() {
5978 let key = [1, 2, 3, 4];
5979 let sibling = [1, 2, 3, 9];
5980 let unrelated = [9, 8, 7, 6];
5981 let mut before = PATCH::<4, IdentitySchema, u64>::new();
5982 for key in [key, sibling, unrelated] {
5983 before.insert(&Entry::with_value(&key, 10));
5984 }
5985 let mut after = before.clone();
5986 after.replace(&Entry::with_value(&key, 11));
5987
5988 assert_eq!(before, after);
5989 assert_eq!(before.get(&key), Some(&10));
5990 assert_eq!(after.get(&key), Some(&11));
5991 assert!(!before.shares_prefix(&after, &key));
5992 assert!(!before.shares_prefix(&after, &[1, 2, 3]));
5993 assert!(before.shares_prefix(&after, &sibling));
5994 assert!(before.shares_prefix(&after, &[9]));
5995 }
5996
5997 #[test]
5998 fn shares_prefix_uses_tree_order_inside_permuted_segments() {
5999 let first = [30, 31, 32, 33, 1, 2, 3, 4, 5, 6, 7, 8];
6000 let mut sibling = first;
6001 sibling[0] = 40;
6002 let mut before = PATCH::<12, PermutedInfixSchema>::new();
6003 before.insert(&Entry::new(&first));
6004 before.insert(&Entry::new(&sibling));
6005
6006 let mut unrelated = first;
6007 unrelated[4..8].copy_from_slice(&[9, 8, 7, 6]);
6008 let mut after = before.clone();
6009 after.insert(&Entry::new(&unrelated));
6010 assert!(before.shares_prefix(&after, &[1, 2]));
6011 assert!(before.shares_prefix(&after, &[1, 2, 3, 4]));
6012 assert!(before.shares_prefix(
6013 &after,
6014 &<PermutedInfixSchema as KeySchema<12>>::tree_ordered(&first)
6015 ));
6016 assert!(!before.shares_prefix(&after, &[9, 8]));
6017
6018 let mut added = first;
6019 added[6] = 8;
6020 let mut split = after.clone();
6021 split.insert(&Entry::new(&added));
6022 assert!(!after.shares_prefix(&split, &[1, 2]));
6023 assert!(after.shares_prefix(&split, &[1, 2, 3, 4]));
6024 }
6025
6026 #[test]
6027 fn prefix_set_projects_away_suffix_multiplicity_and_order() {
6028 let first = [1, 2, 3, 4];
6029 let second = [5, 6, 7, 8];
6030 let physical_key = |prefix: [u8; 4], suffix: [u8; 2]| {
6031 let mut key = [0; 6];
6032 key[..4].copy_from_slice(&prefix);
6033 key[4..].copy_from_slice(&suffix);
6034 key
6035 };
6036
6037 let mut left = PATCH::<6, PrefixProjectionSchema>::new();
6038 for key in [
6039 physical_key(first, [0, 2]),
6040 physical_key(second, [0, 9]),
6041 physical_key(first, [0, 1]),
6042 ] {
6043 left.insert(&Entry::new(&key));
6044 }
6045 let mut right = PATCH::<6, PrefixProjectionSchema>::new();
6046 for key in [physical_key(second, [7, 7]), physical_key(first, [8, 8])] {
6047 right.insert(&Entry::new(&key));
6048 }
6049
6050 assert_eq!(
6051 left.clone().into_prefixes::<4>().collect::<Vec<_>>(),
6052 vec![first, second]
6053 );
6054 let left = left.prefix_set::<4>();
6055 let right = right.prefix_set::<4>();
6056 assert_eq!(left.iter().collect::<Vec<_>>(), vec![first, second]);
6057 assert_eq!(right.iter().collect::<Vec<_>>(), vec![first, second]);
6058 assert!(left.contains(&first));
6059 assert!(left.contains(&second));
6060 assert!(!left.contains(&[9; 4]));
6061 assert_eq!(
6062 left.iter().collect::<Vec<_>>(),
6063 right.iter().collect::<Vec<_>>()
6064 );
6065 }
6066
6067 #[test]
6068 fn prefix_set_intersection_retains_the_other_patch_policy() {
6069 let physical_key = |prefix: [u8; 4], suffix: [u8; 2]| {
6070 let mut key = [0; 6];
6071 key[..4].copy_from_slice(&prefix);
6072 key[4..].copy_from_slice(&suffix);
6073 key
6074 };
6075 let resident = [[1; 4], [3; 4], [5; 4]];
6076 let mut physical = PATCH::<6, PrefixProjectionSchema>::new();
6077 for (prefix, suffix) in [
6078 (resident[0], [0, 1]),
6079 (resident[0], [0, 2]),
6080 (resident[1], [0, 3]),
6081 (resident[2], [0, 4]),
6082 ] {
6083 physical.insert(&Entry::new(&physical_key(prefix, suffix)));
6084 }
6085
6086 let requested = PATCH::<4, IdentitySchema, (), Blake3Merkle>::from_keys([
6087 [0; 4],
6088 resident[0],
6089 [2; 4],
6090 resident[1],
6091 [4; 4],
6092 resident[2],
6093 [6; 4],
6094 ]);
6095 let actual = physical.prefix_set::<4>().intersection(&requested);
6096 let expected = PATCH::<4, IdentitySchema, (), Blake3Merkle>::from_keys(resident);
6097 assert_eq!(actual, expected);
6098 assert_eq!(actual.merkle_root(), expected.merkle_root());
6099 }
6100
6101 struct PanicOnDrop(bool);
6102
6103 impl Drop for PanicOnDrop {
6104 fn drop(&mut self) {
6105 if self.0 {
6106 panic!("intentional value drop panic");
6107 }
6108 }
6109 }
6110
6111 fn owned_archive_pair(
6116 keys: [[u8; 16]; 2],
6117 ) -> (
6118 PATCH<16, IdentitySchema>,
6119 std::sync::Weak<AlignedArchivePair>,
6120 ) {
6121 let storage = std::sync::Arc::new(AlignedArchivePair(keys));
6122 let weak = std::sync::Arc::downgrade(&storage);
6123 let owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6124 let hashes = [hash_key(&storage.0[0]), hash_key(&storage.0[1])];
6125 let mut rows = [0, 1];
6126 let patch =
6130 unsafe { PATCH::from_archive_partition(&storage.0, &hashes, &mut rows, &owner) };
6131 assert_eq!(patch.node_stats(), (1, 2, 0, 2));
6132 drop(owner);
6133 drop(storage);
6134 (patch, weak)
6135 }
6136
6137 #[cfg(feature = "parallel")]
6146 #[test]
6147 fn parallel_partition_pass_agrees_with_the_in_place_pass() {
6148 type Subject = PATCH<16, IdentitySchema>;
6149 let len = 4 * Subject::PARTITION_ROWS_PER_WORKER;
6150 let mut keys: Vec<[u8; 16]> = Vec::with_capacity(len);
6151 let mut state = 0x243f_6a88_85a3_08d3u64;
6152 for index in 0..len {
6153 state = state.wrapping_add(0x9e37_79b9_7f4a_7c15);
6154 let mut mixed = state;
6155 mixed = (mixed ^ (mixed >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
6156 mixed = (mixed ^ (mixed >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
6157 mixed ^= mixed >> 31;
6158 let mut key = [0u8; 16];
6159 key[0] = if index % 10 == 0 {
6163 (mixed & 0xff) as u8
6164 } else {
6165 0x5a
6166 };
6167 key[1..8].copy_from_slice(&[0x5a; 7]);
6168 key[8..16].copy_from_slice(&(index as u64).to_be_bytes());
6169 keys.push(key);
6170 }
6171 keys.sort_unstable();
6172 keys.dedup();
6173 assert!(
6174 keys.len() > 2 * Subject::PARTITION_ROWS_PER_WORKER,
6175 "the fixture must be wide enough for the out-of-place pass",
6176 );
6177 assert!(Subject::partition_workers(keys.len()) > 1);
6178
6179 let rows: Vec<u32> = (0..keys.len() as u32).collect();
6180 let mut in_place = rows.clone();
6181 let ordered = Subject::partition_archive_rows(&keys, &mut in_place, 0);
6182 let (concurrent, permuted) = Subject::partition_archive_rows_parallel(&keys, &rows, 0);
6183
6184 assert_eq!(ordered.end_depth, concurrent.end_depth);
6185 assert_eq!(ordered.fanout, concurrent.fanout);
6186 assert_eq!(ordered.initial_slots, concurrent.initial_slots);
6187 assert_eq!(
6188 ordered.buckets[..ordered.fanout],
6189 concurrent.buckets[..concurrent.fanout],
6190 );
6191 assert_eq!(ordered.ends, concurrent.ends);
6192
6193 let mut start = 0usize;
6194 for &byte in &ordered.buckets[..ordered.fanout] {
6195 let end = ordered.ends[byte as usize] as usize;
6196 let mut ordered_rows: Vec<u32> = in_place[start..end].to_vec();
6197 let mut concurrent_rows: Vec<u32> = permuted[start..end].to_vec();
6198 ordered_rows.sort_unstable();
6199 concurrent_rows.sort_unstable();
6200 assert_eq!(ordered_rows, concurrent_rows, "bucket {byte:#04x}");
6201 start = end;
6202 }
6203 assert_eq!(start, keys.len());
6204 }
6205
6206 fn key(byte: u8) -> [u8; 16] {
6207 [byte; 16]
6208 }
6209
6210 fn singleton_patch(key: [u8; 16]) -> PATCH<16, IdentitySchema> {
6211 let mut patch = PATCH::new();
6212 let entry = Entry::new(&key);
6213 patch.insert(&entry);
6214 patch
6215 }
6216
6217 #[test]
6218 fn exported_fingerprint_blinding_is_not_xor_homomorphic() {
6219 let key = [0x5au8; 16];
6220 let left = 0x0123_4567_89ab_cdef_fedc_ba98_7654_3210u128;
6221 let right = 0xfedc_ba98_7654_3210_0123_4567_89ab_cdefu128;
6222 let blind_left = blind_root_hash_with_key(left, &key);
6223 let blind_right = blind_root_hash_with_key(right, &key);
6224
6225 assert_ne!(blind_left, left);
6226 assert_ne!(
6227 blind_root_hash_with_key(left ^ right, &key),
6228 blind_left ^ blind_right
6229 );
6230 }
6231
6232 #[test]
6233 fn owner_cover_shape_is_canonical_and_membership_is_exact() {
6234 let owners: Vec<Arc<dyn ArchiveOwner>> = (0u8..8)
6235 .map(|byte| Arc::new([byte]) as Arc<dyn ArchiveOwner>)
6236 .collect();
6237 let build = |order: &[usize]| {
6238 let mut cover = None;
6239 for &index in order {
6240 OwnerCover::retain(&mut cover, &owners[index]);
6241 }
6242 cover.unwrap()
6243 };
6244
6245 let forward = build(&[0, 1, 2, 3, 4, 5, 6, 7]);
6246 let shuffled = build(&[6, 2, 7, 0, 5, 1, 4, 3]);
6247 assert_eq!(forward.len, owners.len());
6248 assert_eq!(shuffled.len, owners.len());
6249 assert!(forward.root.same_shape(&shuffled.root));
6250 for owner in &owners {
6251 assert!(forward.root.contains(OwnerCover::address(owner)));
6252 }
6253 let unrelated: Arc<dyn ArchiveOwner> = Arc::new([0xff]);
6254 assert!(!forward.root.contains(OwnerCover::address(&unrelated)));
6255 }
6256
6257 #[test]
6258 fn owner_cover_overlapping_diamond_does_not_accumulate_duplicates() {
6259 let first_backing = Arc::new([0x11]);
6260 let second_backing = Arc::new([0x22]);
6261 let first_weak = Arc::downgrade(&first_backing);
6262 let second_weak = Arc::downgrade(&second_backing);
6263 let first: Arc<dyn ArchiveOwner> = first_backing.clone();
6264 let second: Arc<dyn ArchiveOwner> = second_backing.clone();
6265
6266 let mut left = Some(OwnerCover::singleton(&first));
6267 OwnerCover::retain(&mut left, &second);
6268 let mut right = Some(OwnerCover::singleton(&second));
6269 OwnerCover::retain(&mut right, &first);
6270 let left_root = match &left.as_ref().unwrap().root {
6271 OwnerNode::Branch(branch) => Arc::downgrade(branch),
6272 OwnerNode::Owner(_) => panic!("two owners require one Patricia branch"),
6273 };
6274 let right_root = match &right.as_ref().unwrap().root {
6275 OwnerNode::Branch(branch) => Arc::downgrade(branch),
6276 OwnerNode::Owner(_) => panic!("two owners require one Patricia branch"),
6277 };
6278
6279 for _ in 0..4_096 {
6280 let next_left = OwnerCover::union(left.clone(), &right);
6281 let next_right = OwnerCover::union(right.clone(), &left);
6282 left = next_left;
6283 right = next_right;
6284 assert_eq!(left.as_ref().unwrap().len, 2);
6285 assert_eq!(right.as_ref().unwrap().len, 2);
6286 assert!(matches!(
6287 &left.as_ref().unwrap().root,
6288 OwnerNode::Branch(branch) if Arc::as_ptr(branch) == left_root.as_ptr()
6289 ));
6290 assert!(matches!(
6291 &right.as_ref().unwrap().root,
6292 OwnerNode::Branch(branch) if Arc::as_ptr(branch) == right_root.as_ptr()
6293 ));
6294 }
6295
6296 drop(first);
6297 drop(second);
6298 drop(first_backing);
6299 drop(second_backing);
6300 assert!(first_weak.upgrade().is_some());
6301 assert!(second_weak.upgrade().is_some());
6302 drop(left);
6303 drop(right);
6304 assert!(first_weak.upgrade().is_none());
6305 assert!(second_weak.upgrade().is_none());
6306 }
6307
6308 #[test]
6309 fn repeated_latest_owner_retention_reuses_the_cover() {
6310 let owner: Arc<dyn ArchiveOwner> = Arc::new([0x55]);
6311 let mut cover = None;
6312 OwnerCover::retain(&mut cover, &owner);
6313 let original = cover.as_ref().unwrap().clone();
6314
6315 for _ in 0..4_096 {
6316 OwnerCover::retain(&mut cover, &owner);
6317 }
6318
6319 let cover = cover.unwrap();
6320 assert!(Arc::ptr_eq(&cover, &original));
6321 assert_eq!(cover.len, 1);
6322 assert!(matches!(&cover.root, OwnerNode::Owner(_)));
6323 }
6324
6325 proptest! {
6326 #[test]
6327 fn owner_cover_union_matches_address_set(
6328 left in prop::collection::btree_set(0usize..24, 0..24),
6329 right in prop::collection::btree_set(0usize..24, 0..24),
6330 ) {
6331 let owners: Vec<Arc<dyn ArchiveOwner>> = (0u8..24)
6332 .map(|byte| Arc::new([byte]) as Arc<dyn ArchiveOwner>)
6333 .collect();
6334 let build = |indices: Vec<usize>| {
6335 let mut cover = None;
6336 for index in indices {
6337 OwnerCover::retain(&mut cover, &owners[index]);
6338 }
6339 cover
6340 };
6341 let left_cover = build(left.iter().copied().collect());
6342 let right_cover = build(right.iter().rev().copied().collect());
6343 let joined = OwnerCover::union(left_cover, &right_cover);
6344 let expected: std::collections::BTreeSet<_> =
6345 left.union(&right).copied().collect();
6346
6347 if expected.is_empty() {
6348 prop_assert!(joined.is_none());
6349 } else {
6350 let joined = joined.unwrap();
6351 let mut actual = HashSet::new();
6352 joined.root.for_each_owner(&mut |owner| {
6353 assert!(actual.insert(OwnerCover::address(owner)));
6354 });
6355 let expected_addresses: HashSet<_> = expected
6356 .iter()
6357 .map(|&index| OwnerCover::address(&owners[index]))
6358 .collect();
6359 prop_assert_eq!(actual, expected_addresses);
6360 prop_assert_eq!(joined.len, expected.len());
6361
6362 let canonical = build(expected.iter().copied().collect()).unwrap();
6363 prop_assert!(joined.root.same_shape(&canonical.root));
6364 }
6365 }
6366 }
6367
6368 #[test]
6369 fn disjoint_cross_owner_union_retains_both_archives() {
6370 let (mut left, left_owner) = owned_archive_pair([key(0x10), key(0x20)]);
6371 let (right, right_owner) = owned_archive_pair([key(0x30), key(0x40)]);
6372
6373 left.union(right);
6374
6375 assert!(
6376 left_owner.upgrade().is_some(),
6377 "union dropped its left archive"
6378 );
6379 assert!(
6380 right_owner.upgrade().is_some(),
6381 "union dropped its consumed right archive"
6382 );
6383 assert_eq!(
6384 left.iter().copied().collect::<HashSet<_>>(),
6385 HashSet::from([key(0x10), key(0x20), key(0x30), key(0x40)])
6386 );
6387 drop(left);
6388 assert!(left_owner.upgrade().is_none());
6389 assert!(right_owner.upgrade().is_none());
6390 }
6391
6392 #[test]
6393 fn one_key_intersection_retains_both_source_archives() {
6394 let (left, left_owner) = owned_archive_pair([key(0x10), key(0x20)]);
6395 let (right, right_owner) = owned_archive_pair([key(0x10), key(0x30)]);
6396
6397 let intersection = left.intersect(&right);
6398 drop(left);
6399 drop(right);
6400
6401 assert!(
6402 left_owner.upgrade().is_some(),
6403 "intersection dropped the archive backing its surviving LocalLeaf"
6404 );
6405 assert!(
6406 right_owner.upgrade().is_some(),
6407 "intersection must conservatively retain both source covers"
6408 );
6409 assert_eq!(intersection.iter().copied().collect_vec(), vec![key(0x10)]);
6410 drop(intersection);
6411 assert!(left_owner.upgrade().is_none());
6412 assert!(right_owner.upgrade().is_none());
6413 }
6414
6415 #[test]
6416 fn one_key_difference_retains_its_left_archive() {
6417 let (left, left_owner) = owned_archive_pair([key(0x10), key(0x20)]);
6418 let (right, right_owner) = owned_archive_pair([key(0x10), key(0x30)]);
6419
6420 let difference = left.difference(&right);
6421 drop(left);
6422 drop(right);
6423
6424 assert!(
6425 left_owner.upgrade().is_some(),
6426 "difference dropped the archive backing its surviving LocalLeaf"
6427 );
6428 assert!(
6429 right_owner.upgrade().is_none(),
6430 "difference should not retain an archive used only for subtraction"
6431 );
6432 assert_eq!(difference.iter().copied().collect_vec(), vec![key(0x20)]);
6433 drop(difference);
6434 assert!(left_owner.upgrade().is_none());
6435 assert!(right_owner.upgrade().is_none());
6436 }
6437
6438 #[test]
6439 fn asymmetric_difference_collapses_its_surviving_child() {
6440 let (left, owner) = owned_archive_pair([key(0x10), key(0x20)]);
6441 assert_eq!(left.root.as_ref().map(Head::tag), Some(HeadTag::Branch2));
6442 let removed = singleton_patch(key(0x10));
6443
6444 let survivor = left.difference(&removed);
6445 drop(left);
6446 drop(removed);
6447
6448 assert_eq!(survivor.len(), 1);
6449 assert_eq!(survivor.node_stats(), (0, 0, 0, 1));
6450 assert_eq!(
6451 survivor.root.as_ref().map(Head::tag),
6452 Some(HeadTag::LocalLeaf),
6453 "Branch-minus-Leaf left a unary Branch instead of its child",
6454 );
6455 assert_eq!(survivor.iter().copied().collect_vec(), vec![key(0x20)]);
6456 assert!(owner.upgrade().is_some());
6457
6458 let final_key = singleton_patch(key(0x20));
6459 let empty = survivor.difference(&final_key);
6460 drop(survivor);
6461 drop(final_key);
6462
6463 assert!(empty.root.is_none());
6464 assert!(empty.owners.is_none());
6465 assert!(owner.upgrade().is_none());
6466 }
6467
6468 #[test]
6469 fn clone_and_consuming_iterator_retain_the_archive() {
6470 let (patch, owner) = owned_archive_pair([key(0x10), key(0x20)]);
6471 let clone = patch.clone();
6472 drop(patch);
6473 assert!(owner.upgrade().is_some(), "clone lost the archive owner");
6474
6475 let mut iter = clone.into_iter();
6476 assert!(
6477 owner.upgrade().is_some(),
6478 "consuming iterator lost the archive owner"
6479 );
6480 assert!(matches!(iter.next(), Some(value) if value == key(0x10) || value == key(0x20)));
6481 drop(iter);
6482 assert!(owner.upgrade().is_none());
6483 }
6484
6485 #[test]
6486 fn ordered_consuming_iterator_retains_the_archive() {
6487 let (patch, owner) = owned_archive_pair([key(0x10), key(0x20)]);
6488
6489 let mut iter = patch.into_iter_ordered();
6490 assert!(
6491 owner.upgrade().is_some(),
6492 "ordered consuming iterator lost the archive owner"
6493 );
6494 assert_eq!(iter.next(), Some(key(0x10)));
6495 drop(iter);
6496 assert!(owner.upgrade().is_none());
6497 }
6498
6499 #[test]
6500 fn removal_retains_collapsed_local_root_and_releases_empty_cover() {
6501 let (mut patch, owner) = owned_archive_pair([key(0x10), key(0x20)]);
6502
6503 patch.remove(&key(0x10));
6504 assert!(
6505 owner.upgrade().is_some(),
6506 "removal lost the owner of the surviving LocalLeaf"
6507 );
6508 assert_eq!(patch.iter().copied().collect_vec(), vec![key(0x20)]);
6509
6510 patch.remove(&key(0x20));
6511 assert!(patch.is_empty());
6512 assert!(owner.upgrade().is_none(), "empty PATCH retained its cover");
6513 }
6514
6515 #[test]
6516 fn head_tag() {
6517 let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(0, NonNull::dangling());
6518 assert_eq!(head.tag(), HeadTag::Leaf);
6519 mem::forget(head);
6520 }
6521
6522 #[test]
6523 fn head_key() {
6524 for k in 0..=255 {
6525 let head = Head::<64, IdentitySchema, ()>::new::<Leaf<64, ()>>(k, NonNull::dangling());
6526 assert_eq!(head.key(), k);
6527 mem::forget(head);
6528 }
6529 }
6530
6531 #[test]
6532 fn head_size() {
6533 assert_eq!(mem::size_of::<Head<64, IdentitySchema, ()>>(), 8);
6534 }
6535
6536 #[test]
6537 fn option_head_size() {
6538 assert_eq!(mem::size_of::<Option<Head<64, IdentitySchema, ()>>>(), 8);
6539 }
6540
6541 #[test]
6542 fn empty_tree() {
6543 let _tree = PATCH::<64, IdentitySchema, ()>::new();
6544 }
6545
6546 #[test]
6547 fn tree_put_one() {
6548 const KEY_SIZE: usize = 64;
6549 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
6550 let entry = Entry::new(&[0; KEY_SIZE]);
6551 tree.insert(&entry);
6552 }
6553
6554 #[test]
6555 fn tree_clone_one() {
6556 const KEY_SIZE: usize = 64;
6557 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
6558 let entry = Entry::new(&[0; KEY_SIZE]);
6559 tree.insert(&entry);
6560 let _clone = tree.clone();
6561 }
6562
6563 #[test]
6564 fn consuming_shared_leaf_does_not_mutably_alias_value() {
6565 const KEY_SIZE: usize = 4;
6566 let key = [1u8; KEY_SIZE];
6567 let mut retained = PATCH::<KEY_SIZE, IdentitySchema, String>::new();
6568 let entry = Entry::with_value(&key, String::from("still borrowed"));
6569 retained.insert(&entry);
6570 drop(entry);
6571
6572 let unordered = retained.clone();
6573 let value = retained.get(&key).expect("inserted value");
6574 assert_eq!(unordered.into_iter().collect::<Vec<_>>(), vec![key]);
6575 assert_eq!(value, "still borrowed");
6576
6577 let ordered = retained.clone();
6578 let value = retained.get(&key).expect("inserted value");
6579 assert_eq!(ordered.into_iter_ordered().collect::<Vec<_>>(), vec![key]);
6580 assert_eq!(value, "still borrowed");
6581 }
6582
6583 #[test]
6584 fn tree_put_same() {
6585 const KEY_SIZE: usize = 64;
6586 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
6587 let entry = Entry::new(&[0; KEY_SIZE]);
6588 tree.insert(&entry);
6589 tree.insert(&entry);
6590 }
6591
6592 #[test]
6593 fn ordered_infix_bounds_include_all_zero_and_all_ff() {
6594 let mut tree = PATCH::<4, IdentitySchema, ()>::new();
6595 tree.insert(&Entry::new(&[0x00; 4]));
6596 tree.insert(&Entry::new(&[0x80, 0x00, 0x00, 0x00]));
6597 tree.insert(&Entry::new(&[0xff; 4]));
6598
6599 assert_eq!(
6600 tree.first_infix_range(&[], &[0x00; 4], &[0xff; 4]),
6601 Some([0x00; 4]),
6602 );
6603 assert_eq!(
6604 tree.next_infix_after(&[], &[0x00; 4], &[0xff; 4]),
6605 Some([0x80, 0x00, 0x00, 0x00]),
6606 );
6607 assert_eq!(
6608 tree.first_infix_range(&[], &[0xff; 4], &[0xff; 4]),
6609 Some([0xff; 4]),
6610 );
6611 assert_eq!(tree.next_infix_after(&[], &[0xff; 4], &[0xff; 4]), None,);
6612 assert_eq!(tree.first_infix_range(&[], &[0xff; 4], &[0x00; 4]), None,);
6613 }
6614
6615 #[test]
6616 fn ordered_infix_descent_reads_local_leaves() {
6617 #[repr(C, align(16))]
6618 struct AlignedKey([u8; 16]);
6619
6620 let storage = std::sync::Arc::new([
6621 AlignedKey([0x10; 16]),
6622 AlignedKey([0x20; 16]),
6623 AlignedKey([0xf0; 16]),
6624 ]);
6625 let owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6626 let mut tree = PATCH::<16, IdentitySchema, ()>::new();
6627 for key in storage.iter() {
6628 let entry = unsafe { ArchiveEntry::new(NonNull::from(&key.0), &owner) };
6629 tree.insert_archive(&entry);
6630 }
6631
6632 assert!(tree.node_stats().3 > 0, "fixture must contain a LocalLeaf");
6633 assert_eq!(
6634 tree.first_infix_range(&[], &[0x11; 16], &[0xff; 16]),
6635 Some([0x20; 16]),
6636 );
6637 assert_eq!(
6638 tree.next_infix_after(&[], &[0x20; 16], &[0xff; 16]),
6639 Some([0xf0; 16]),
6640 );
6641 }
6642
6643 #[test]
6644 fn ordered_infix_descent_honors_permuted_segments_in_local_leaves() {
6645 fn physical_key(prefix: [u8; 4], infix: [u8; 4], suffix: [u8; 4]) -> [u8; 12] {
6646 let mut key = [0; 12];
6647 key[..4].copy_from_slice(&suffix);
6648 key[4..8].copy_from_slice(&prefix);
6649 key[8..].copy_from_slice(&infix);
6650 key
6651 }
6652
6653 let selected = [0x10; 4];
6654 let other = [0x20; 4];
6655 let first = [0x11; 4];
6656 let second = [0x22; 4];
6657 let storage = std::sync::Arc::new([
6658 AlignedArchiveKey(physical_key(other, [0x33; 4], [0x44; 4])),
6659 AlignedArchiveKey(physical_key(selected, second, [0x44; 4])),
6660 AlignedArchiveKey(physical_key(selected, first, [0x55; 4])),
6661 AlignedArchiveKey(physical_key(selected, first, [0x44; 4])),
6662 ]);
6663 let owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6664 let mut tree = PATCH::<12, PermutedInfixSchema, ()>::new();
6665 for key in storage.iter() {
6666 let entry = unsafe { ArchiveEntry::new(NonNull::from(&key.0), &owner) };
6669 tree.insert_archive(&entry);
6670 }
6671
6672 assert!(tree.node_stats().3 > 0, "fixture must contain a LocalLeaf");
6673 assert_eq!(
6674 tree.first_infix_range(&selected, &[u8::MIN; 4], &[u8::MAX; 4]),
6675 Some(first),
6676 );
6677 assert_eq!(
6678 tree.next_infix_after(&selected, &first, &[u8::MAX; 4]),
6679 Some(second),
6680 );
6681 assert_eq!(
6682 tree.next_infix_after(&selected, &second, &[u8::MAX; 4]),
6683 None,
6684 );
6685 }
6686
6687 #[test]
6688 fn bounded_infixes_are_atomic_over_archive_local_leaves() {
6689 #[repr(C, align(16))]
6690 struct AlignedKey([u8; 16]);
6691
6692 let storage = std::sync::Arc::new([
6693 AlignedKey([0x10; 16]),
6694 AlignedKey([0x20; 16]),
6695 AlignedKey([0xf0; 16]),
6696 ]);
6697 let owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6698 let mut tree = PATCH::<16, IdentitySchema, ()>::new();
6699 for key in storage.iter() {
6700 let entry = unsafe { ArchiveEntry::new(NonNull::from(&key.0), &owner) };
6701 tree.insert_archive(&entry);
6702 }
6703 assert!(tree.node_stats().3 > 0, "fixture must contain a LocalLeaf");
6704
6705 assert!(tree.bounded_infixes::<0, 16>(&[], 2).is_none());
6706
6707 let mut expected = Vec::new();
6708 tree.infixes(&[], |value: &[u8; 16]| expected.push(*value));
6709 let mut accepted = Vec::new();
6710 let bounded = tree
6711 .bounded_infixes::<0, 16>(&[], 3)
6712 .expect("the exact count fits");
6713 assert_eq!(bounded.len(), 3);
6714 bounded.for_each(|value: &[u8; 16]| accepted.push(*value));
6715 assert_eq!(accepted, expected);
6716 }
6717
6718 #[test]
6719 fn archive_singleton_pairs_follow_exact_key_identity() {
6720 const KEY_SIZE: usize = 64;
6721 #[repr(C, align(16))]
6722 struct AlignedKey([u8; KEY_SIZE]);
6723
6724 let key_a = [0x44; KEY_SIZE];
6725 let mut key_b = key_a;
6726 key_b[KEY_SIZE - 1] = 0x55;
6727 let storage = std::sync::Arc::new([AlignedKey(key_a), AlignedKey(key_b)]);
6728 let _owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6729
6730 let local_a = unsafe { Head::new_local_leaf(0, NonNull::from(&storage[0].0)) };
6731 let local_b = unsafe { Head::new_local_leaf(0, NonNull::from(&storage[1].0)) };
6732 let heap_a_entry = Entry::new(&key_a);
6733 let heap_b_entry = Entry::new(&key_b);
6734 let heap_a = heap_a_entry.leaf::<IdentitySchema>();
6735 let heap_b = heap_b_entry.leaf::<IdentitySchema>();
6736
6737 fn assert_pair(
6738 left: &Head<64, IdentitySchema, ()>,
6739 right: &Head<64, IdentitySchema, ()>,
6740 equal: bool,
6741 ) {
6742 let union = Head::union(left.clone(), right.clone(), 0);
6743 assert_eq!(union.count(), if equal { 1 } else { 2 });
6744 assert_eq!(
6745 left.intersect(right, 0).as_ref().map(Head::count),
6746 equal.then_some(1)
6747 );
6748 assert_eq!(
6749 left.difference(right, 0).as_ref().map(Head::count),
6750 (!equal).then_some(1)
6751 );
6752 }
6753
6754 assert_pair(&local_a, &local_a, true);
6755 assert_pair(&local_a, &local_b, false);
6756 assert_pair(&heap_a, &local_a, true);
6757 assert_pair(&local_a, &heap_a, true);
6758 assert_pair(&heap_a, &local_b, false);
6759 assert_pair(&local_a, &heap_b, false);
6760 assert_pair(&heap_a, &heap_a, true);
6761 assert_pair(&heap_a, &heap_b, false);
6762 }
6763
6764 #[test]
6765 fn local_leaf_and_unary_branch_keep_equal_fingerprint_path() {
6766 const KEY_SIZE: usize = 16;
6767 #[repr(C, align(16))]
6768 struct AlignedKey([u8; KEY_SIZE]);
6769
6770 let storage =
6771 std::sync::Arc::new([AlignedKey([0x10; KEY_SIZE]), AlignedKey([0x20; KEY_SIZE])]);
6772 let owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6773 let mut pair = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
6774 for key in storage.iter() {
6775 let entry = unsafe { ArchiveEntry::new(NonNull::from(&key.0), &owner) };
6776 pair.insert_archive(&entry);
6777 }
6778
6779 let mut unary = pair.root.as_ref().expect("pair has a root").clone();
6782 let removed_slot = match unary.body_ref() {
6783 BodyRef::Branch(branch) => branch
6784 .child_table
6785 .iter()
6786 .flatten()
6787 .find(|child| child.childleaf_key() == &storage[0].0)
6788 .expect("first archive key is present")
6789 .key(),
6790 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => panic!("pair root must be a Branch"),
6791 };
6792 {
6793 let mut editor = crate::patch::branch::BranchMut::from_head(&mut unary);
6794 editor.modify_child(removed_slot, |_| None);
6795 }
6796 assert!(matches!(unary.body_ref(), BodyRef::Branch(_)));
6797 assert_eq!(unary.count(), 1);
6798
6799 let local = match unary.body_ref() {
6800 BodyRef::Branch(branch) => branch
6801 .child_table
6802 .iter()
6803 .flatten()
6804 .next()
6805 .expect("unary Branch has one child")
6806 .clone(),
6807 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => unreachable!(),
6808 };
6809 assert_eq!(local.tag(), HeadTag::LocalLeaf);
6810 assert_eq!(local.count(), 1);
6811 assert_eq!(local.hash(), unary.hash());
6812
6813 let union = Head::union(local.clone(), unary.clone(), 0);
6817 assert_eq!(union.tag(), HeadTag::LocalLeaf);
6818 let intersection = unary
6819 .intersect(&local, 0)
6820 .expect("equal singleton sets intersect");
6821 assert!(matches!(intersection.body_ref(), BodyRef::Branch(_)));
6822 assert!(unary.difference(&local, 0).is_none());
6823
6824 #[cfg(feature = "parallel")]
6825 {
6826 let union = Head::par_union(local.clone(), unary.clone(), 0);
6827 assert_eq!(union.tag(), HeadTag::LocalLeaf);
6828 let intersection = unary
6829 .par_intersect(&local, 0)
6830 .expect("equal singleton sets intersect");
6831 assert!(matches!(intersection.body_ref(), BodyRef::Branch(_)));
6832 assert!(unary.par_difference(&local, 0).is_none());
6833 }
6834 }
6835
6836 #[test]
6837 fn archive_set_ops_retain_shared_backing() {
6838 const KEY_SIZE: usize = 16;
6839 #[repr(C, align(16))]
6840 struct AlignedKey([u8; KEY_SIZE]);
6841
6842 let key_a = [0x10; KEY_SIZE];
6843 let key_b = [0x20; KEY_SIZE];
6844 let key_c = [0x30; KEY_SIZE];
6845 let (left, right) = {
6846 let storage =
6847 std::sync::Arc::new([AlignedKey(key_a), AlignedKey(key_b), AlignedKey(key_c)]);
6848 let owner: std::sync::Arc<dyn ArchiveOwner> = storage.clone();
6849 let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
6850 let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
6851 for index in [0, 1] {
6852 let entry = unsafe { ArchiveEntry::new(NonNull::from(&storage[index].0), &owner) };
6853 left.insert_archive(&entry);
6854 }
6855 for index in [1, 2] {
6856 let entry = unsafe { ArchiveEntry::new(NonNull::from(&storage[index].0), &owner) };
6857 right.insert_archive(&entry);
6858 }
6859 assert!(left.node_stats().3 > 0);
6860 assert!(right.node_stats().3 > 0);
6861 (left, right)
6862 };
6863
6864 let mut union = left.clone();
6865 union.union(right.clone());
6866 assert_eq!(union.len(), 3);
6867 assert!(union.get(&key_a).is_some());
6868 assert!(union.get(&key_b).is_some());
6869 assert!(union.get(&key_c).is_some());
6870
6871 let intersection = left.intersect(&right);
6872 assert_eq!(intersection.len(), 1);
6873 assert!(intersection.get(&key_b).is_some());
6874
6875 let difference = left.difference(&right);
6876 assert_eq!(difference.len(), 1);
6877 assert!(difference.get(&key_a).is_some());
6878 }
6879
6880 #[test]
6881 fn tree_replace_existing() {
6882 const KEY_SIZE: usize = 64;
6883 let key = [1u8; KEY_SIZE];
6884 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
6885 let entry1 = Entry::with_value(&key, 1);
6886 tree.insert(&entry1);
6887 let entry2 = Entry::with_value(&key, 2);
6888 tree.replace(&entry2);
6889 assert_eq!(tree.get(&key), Some(&2));
6890 }
6891
6892 #[test]
6893 fn tree_replace_childleaf_updates_branch() {
6894 const KEY_SIZE: usize = 64;
6895 let key1 = [0u8; KEY_SIZE];
6896 let key2 = [1u8; KEY_SIZE];
6897 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
6898 let entry1 = Entry::with_value(&key1, 1);
6899 let entry2 = Entry::with_value(&key2, 2);
6900 tree.insert(&entry1);
6901 tree.insert(&entry2);
6902 let entry1b = Entry::with_value(&key1, 3);
6903 tree.replace(&entry1b);
6904 assert_eq!(tree.get(&key1), Some(&3));
6905 assert_eq!(tree.get(&key2), Some(&2));
6906 }
6907
6908 #[test]
6909 fn update_child_refreshes_childleaf_on_replace() {
6910 const KEY_SIZE: usize = 4;
6911 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
6912
6913 let key1 = [0u8; KEY_SIZE];
6914 let key2 = [1u8; KEY_SIZE];
6915 tree.insert(&Entry::with_value(&key1, 1));
6916 tree.insert(&Entry::with_value(&key2, 2));
6917
6918 let root_ref = tree.root.as_ref().expect("root exists");
6920 let before_childleaf = *root_ref.childleaf_key();
6921
6922 let slot_key = match root_ref.body_ref() {
6925 BodyRef::Branch(branch) => branch
6926 .child_table
6927 .iter()
6928 .filter_map(|c| c.as_ref())
6929 .find(|c| c.childleaf_key() == &before_childleaf)
6930 .expect("child exists")
6931 .key(),
6932 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => panic!("root should be a branch"),
6933 };
6934
6935 let new_key = [2u8; KEY_SIZE];
6937 {
6938 let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
6939 ed.modify_child(slot_key, |_| {
6940 Some(Entry::with_value(&new_key, 42).leaf::<IdentitySchema>())
6941 });
6942 }
6944
6945 let after = tree.root.as_ref().expect("root exists");
6946 assert_eq!(after.childleaf_key(), &new_key);
6947 }
6948
6949 #[test]
6950 fn replace_commits_nested_structure_before_value_drop_panics() {
6951 use std::panic::{catch_unwind, AssertUnwindSafe};
6952
6953 const KEY_LEN: usize = 4;
6954 let replaced = [0, 0, 0, 0];
6955 let nested_sibling = [0, 0, 0, 1];
6956 let root_sibling = [1, 0, 0, 0];
6957 let mut patch = PATCH::<KEY_LEN, IdentitySchema, PanicOnDrop>::new();
6958
6959 for (key, should_panic) in [
6960 (replaced, true),
6961 (nested_sibling, false),
6962 (root_sibling, false),
6963 ] {
6964 let entry = Entry::with_value(&key, PanicOnDrop(should_panic));
6965 patch.insert(&entry);
6966 drop(entry);
6967 }
6968 let old_hash = patch.root_hash().expect("fixture hash");
6969 let old_nodes = patch.node_stats();
6970
6971 let replacement = Entry::with_value(&replaced, PanicOnDrop(false));
6972 let result = catch_unwind(AssertUnwindSafe(|| patch.replace(&replacement)));
6973 assert!(result.is_err());
6974
6975 assert_eq!(patch.len(), 3);
6976 assert_eq!(patch.get(&replaced).map(|value| value.0), Some(false));
6977 assert_eq!(patch.get(&nested_sibling).map(|value| value.0), Some(false));
6978 assert_eq!(patch.get(&root_sibling).map(|value| value.0), Some(false));
6979 assert_eq!(patch.root_hash(), Some(old_hash));
6980 assert_eq!(patch.node_stats(), old_nodes);
6981 assert_eq!(
6982 patch.iter_ordered().copied().collect::<Vec<_>>(),
6983 vec![replaced, nested_sibling, root_sibling],
6984 );
6985 }
6986
6987 #[test]
6988 fn replace_commits_singleton_root_before_value_drop_panics() {
6989 use std::panic::{catch_unwind, AssertUnwindSafe};
6990
6991 const KEY_LEN: usize = 4;
6992 let key = [7; KEY_LEN];
6993 let mut patch = PATCH::<KEY_LEN, IdentitySchema, PanicOnDrop>::new();
6994 let original = Entry::with_value(&key, PanicOnDrop(true));
6995 patch.insert(&original);
6996 drop(original);
6997
6998 let replacement = Entry::with_value(&key, PanicOnDrop(false));
6999 let result = catch_unwind(AssertUnwindSafe(|| patch.replace(&replacement)));
7000 assert!(result.is_err());
7001
7002 assert_eq!(patch.len(), 1);
7003 assert_eq!(patch.get(&key).map(|value| value.0), Some(false));
7004 assert_eq!(patch.root_hash(), Some(hash_key(&key)));
7005 assert!(matches!(
7006 patch.root.as_ref().expect("replacement root").body_ref(),
7007 BodyRef::Leaf(_),
7008 ));
7009 }
7010
7011 #[test]
7012 fn remove_commits_nested_structure_before_value_drop_panics() {
7013 use std::panic::{catch_unwind, AssertUnwindSafe};
7014
7015 const KEY_LEN: usize = 4;
7016 let removed = [0, 0, 0, 0];
7017 let nested_sibling = [0, 0, 0, 1];
7018 let root_sibling = [1, 0, 0, 0];
7019 let mut patch = PATCH::<KEY_LEN, IdentitySchema, PanicOnDrop>::new();
7020
7021 for (key, should_panic) in [
7022 (removed, true),
7023 (nested_sibling, false),
7024 (root_sibling, false),
7025 ] {
7026 let entry = Entry::with_value(&key, PanicOnDrop(should_panic));
7027 patch.insert(&entry);
7028 drop(entry);
7029 }
7030 assert_eq!(patch.node_stats().0, 2, "fixture must contain two branches");
7031 assert_eq!(
7032 patch.root.as_ref().expect("root branch").childleaf_key(),
7033 &removed,
7034 "the removed leaf must back the ancestor representative pointer",
7035 );
7036 let old_hash = patch.root_hash().expect("fixture hash");
7037
7038 let result = catch_unwind(AssertUnwindSafe(|| patch.remove(&removed)));
7039 assert!(result.is_err());
7040
7041 assert_eq!(patch.len(), 2);
7042 assert!(patch.get(&removed).is_none());
7043 assert!(patch.get(&nested_sibling).is_some());
7044 assert!(patch.get(&root_sibling).is_some());
7045 assert_eq!(
7046 patch.iter_ordered().copied().collect::<Vec<_>>(),
7047 vec![nested_sibling, root_sibling],
7048 );
7049 assert_eq!(patch.node_stats().0, 1, "the nested unary branch collapsed");
7050 assert_ne!(
7051 patch.root.as_ref().expect("surviving root").childleaf_key(),
7052 &removed,
7053 "the surviving branch must not retain a dangling representative",
7054 );
7055 assert_eq!(patch.root_hash(), Some(old_hash ^ hash_key(&removed)));
7056 let fanout = patch.branch_fanout_histogram();
7057 assert_eq!(fanout[0], 0);
7058 assert_eq!(fanout[1], 0);
7059 }
7060
7061 #[test]
7062 fn remove_collapses_root_before_value_drop_panics() {
7063 use std::panic::{catch_unwind, AssertUnwindSafe};
7064
7065 const KEY_LEN: usize = 4;
7066 let removed = [0; KEY_LEN];
7067 let retained = [1; KEY_LEN];
7068 let mut patch = PATCH::<KEY_LEN, IdentitySchema, PanicOnDrop>::new();
7069 for (key, should_panic) in [(removed, true), (retained, false)] {
7070 let entry = Entry::with_value(&key, PanicOnDrop(should_panic));
7071 patch.insert(&entry);
7072 drop(entry);
7073 }
7074
7075 let result = catch_unwind(AssertUnwindSafe(|| patch.remove(&removed)));
7076 assert!(result.is_err());
7077 assert_eq!(patch.len(), 1);
7078 assert!(patch.get(&removed).is_none());
7079 assert!(patch.get(&retained).is_some());
7080 assert_eq!(patch.root_hash(), Some(hash_key(&retained)));
7081 assert!(matches!(
7082 patch.root.as_ref().expect("retained root").body_ref(),
7083 BodyRef::Leaf(_),
7084 ));
7085 }
7086
7087 #[test]
7088 fn remove_commits_cow_snapshot_before_deferred_value_drop_panics() {
7089 use std::panic::{catch_unwind, AssertUnwindSafe};
7090
7091 const KEY_LEN: usize = 4;
7092 let removed = [0; KEY_LEN];
7093 let retained = [1; KEY_LEN];
7094 let mut edited = PATCH::<KEY_LEN, IdentitySchema, PanicOnDrop>::new();
7095 for (key, should_panic) in [(removed, true), (retained, false)] {
7096 let entry = Entry::with_value(&key, PanicOnDrop(should_panic));
7097 edited.insert(&entry);
7098 drop(entry);
7099 }
7100 let snapshot = edited.clone();
7101
7102 edited.remove(&removed);
7105 assert!(edited.get(&removed).is_none());
7106 assert!(edited.get(&retained).is_some());
7107 assert_eq!(edited.root_hash(), Some(hash_key(&retained)));
7108 assert!(snapshot.get(&removed).is_some());
7109
7110 let result = catch_unwind(AssertUnwindSafe(|| drop(snapshot)));
7111 assert!(result.is_err());
7112 assert_eq!(edited.len(), 1);
7113 assert!(edited.get(&retained).is_some());
7114 }
7115
7116 #[test]
7117 fn remove_retains_archive_owner_until_empty_then_commits_before_drop_panics() {
7118 use std::panic::{catch_unwind, AssertUnwindSafe};
7119
7120 const KEY_LEN: usize = 16;
7121 #[repr(C, align(16))]
7122 struct PanickingOwner {
7123 keys: [AlignedArchiveKey<KEY_LEN>; 2],
7124 drops: Arc<AtomicUsize>,
7125 }
7126
7127 impl Drop for PanickingOwner {
7128 fn drop(&mut self) {
7129 self.drops.fetch_add(1, Ordering::Relaxed);
7130 panic!("intentional archive owner drop panic");
7131 }
7132 }
7133
7134 let first = [7; KEY_LEN];
7135 let second = [8; KEY_LEN];
7136 let drops = Arc::new(AtomicUsize::new(0));
7137 let owner = Arc::new(PanickingOwner {
7138 keys: [AlignedArchiveKey(first), AlignedArchiveKey(second)],
7139 drops: drops.clone(),
7140 });
7141 let erased: Arc<dyn ArchiveOwner> = owner.clone();
7142 let mut patch = PATCH::<KEY_LEN, IdentitySchema>::new();
7143 for index in 0..2 {
7144 let entry = unsafe { ArchiveEntry::new(NonNull::from(&owner.keys[index].0), &erased) };
7145 patch.insert_archive(&entry);
7146 }
7147 drop(erased);
7148 drop(owner);
7149
7150 patch.remove(&first);
7153 assert_eq!(drops.load(Ordering::Relaxed), 0);
7154 assert!(patch.owners.is_some());
7155 assert_eq!(patch.iter().copied().collect::<Vec<_>>(), vec![second]);
7156 assert!(matches!(
7157 patch.root.as_ref().expect("archive root").body_ref(),
7158 BodyRef::LocalLeaf(_),
7159 ));
7160
7161 let result = catch_unwind(AssertUnwindSafe(|| patch.remove(&second)));
7162 assert!(result.is_err());
7163 assert_eq!(drops.load(Ordering::Relaxed), 1);
7164 assert!(patch.root.is_none(), "the empty root was committed first");
7165 assert!(
7166 patch.owners.is_none(),
7167 "the owner cover was detached before reclamation"
7168 );
7169 assert!(patch.is_empty());
7170 }
7171
7172 #[test]
7173 fn remove_promotes_a_multi_leaf_only_child_subtree() {
7174 const KEY_LEN: usize = 4;
7175 let removed = [0, 0, 0, 0];
7176 let retained_a = [1, 0, 0, 0];
7177 let retained_b = [1, 1, 0, 0];
7178 let mut patch = PATCH::<KEY_LEN, IdentitySchema>::new();
7179 for key in [removed, retained_a, retained_b] {
7180 patch.insert(&Entry::new(&key));
7181 }
7182 assert_eq!(patch.node_stats().0, 2, "fixture must contain two branches");
7183
7184 patch.remove(&removed);
7185
7186 assert_eq!(patch.len(), 2);
7187 assert_eq!(patch.node_stats().0, 1, "unary root must be removed");
7188 assert_eq!(patch.branch_fanout_histogram()[1], 0);
7189 assert!(patch.get(&retained_a).is_some());
7190 assert!(patch.get(&retained_b).is_some());
7191 }
7192
7193 #[test]
7194 fn remove_childleaf_updates_branch() {
7195 const KEY_SIZE: usize = 4;
7196 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7197
7198 let key1 = [0u8; KEY_SIZE];
7199 let key2 = [1u8; KEY_SIZE];
7200 tree.insert(&Entry::with_value(&key1, 1));
7201 tree.insert(&Entry::with_value(&key2, 2));
7202
7203 let childleaf_before = *tree.root.as_ref().unwrap().childleaf_key();
7204 tree.remove(&childleaf_before);
7206
7207 let other = if childleaf_before == key1 { key2 } else { key1 };
7209 assert_eq!(tree.get(&childleaf_before), None);
7210 assert_eq!(tree.get(&other), Some(&2u32));
7211 let after_childleaf = tree.root.as_ref().unwrap().childleaf_key();
7212 assert_eq!(after_childleaf, &other);
7213 }
7214
7215 #[test]
7216 fn remove_collapses_branch_to_single_child() {
7217 const KEY_SIZE: usize = 4;
7218 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7219
7220 let key1 = [0u8; KEY_SIZE];
7221 let key2 = [1u8; KEY_SIZE];
7222 tree.insert(&Entry::with_value(&key1, 1));
7223 tree.insert(&Entry::with_value(&key2, 2));
7224
7225 tree.remove(&key1);
7227 assert_eq!(tree.get(&key1), None);
7228 assert_eq!(tree.get(&key2), Some(&2u32));
7229 let root = tree.root.as_ref().expect("root exists");
7230 match root.body_ref() {
7231 BodyRef::Leaf(_) | BodyRef::LocalLeaf(_) => {}
7232 BodyRef::Branch(_) => panic!("root should have collapsed to a leaf"),
7233 }
7234 }
7235
7236 #[test]
7237 fn branch_size() {
7238 assert_eq!(
7241 mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 2], ()>>(
7242 ),
7243 48 + 8 * 2
7244 );
7245 assert_eq!(
7246 mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 4], ()>>(
7247 ),
7248 48 + 8 * 4
7249 );
7250 assert_eq!(
7251 mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 8], ()>>(
7252 ),
7253 48 + 8 * 8
7254 );
7255 assert_eq!(
7256 mem::size_of::<
7257 Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 16], ()>,
7258 >(),
7259 48 + 8 * 16
7260 );
7261 assert_eq!(
7262 mem::size_of::<
7263 Branch<64, IdentitySchema, [Option<Head<32, IdentitySchema, ()>>; 32], ()>,
7264 >(),
7265 48 + 8 * 32
7266 );
7267 assert_eq!(
7268 mem::size_of::<
7269 Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 64], ()>,
7270 >(),
7271 48 + 8 * 64
7272 );
7273 assert_eq!(
7274 mem::size_of::<
7275 Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 128], ()>,
7276 >(),
7277 48 + 8 * 128
7278 );
7279 assert_eq!(
7280 mem::size_of::<
7281 Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 256], ()>,
7282 >(),
7283 48 + 8 * 256
7284 );
7285 }
7286
7287 #[test]
7288 fn patch_root_owner_cover_is_one_thin_arc() {
7289 assert_eq!(mem::size_of::<Entry<64, ()>>(), 8);
7293 assert_eq!(mem::size_of::<Leaf<64, ()>>(), 96);
7294 assert_eq!(mem::size_of::<Head<64, IdentitySchema, ()>>(), 8);
7295 assert_eq!(
7296 mem::size_of::<Branch<64, IdentitySchema, [Option<Head<64, IdentitySchema, ()>>; 0], ()>>(
7297 ),
7298 48
7299 );
7300 assert_eq!(mem::size_of::<Option<Arc<OwnerCover>>>(), 8);
7301 assert_eq!(mem::size_of::<PATCH<64, IdentitySchema, ()>>(), 16);
7302
7303 assert_eq!(mem::size_of::<Entry<64, (), Blake3Merkle>>(), 8);
7304 assert_eq!(mem::size_of::<Leaf<64, (), Blake3Merkle>>(), 112);
7305 assert_eq!(
7306 mem::size_of::<
7307 Branch<
7308 64,
7309 IdentitySchema,
7310 [Option<Head<64, IdentitySchema, (), Blake3Merkle>>; 0],
7311 (),
7312 Blake3Merkle,
7313 >,
7314 >(),
7315 64
7316 );
7317 assert_eq!(
7318 mem::size_of::<PATCH<64, IdentitySchema, (), Blake3Merkle>>(),
7319 16
7320 );
7321 }
7322
7323 #[test]
7326 fn tree_union_single() {
7327 const KEY_SIZE: usize = 8;
7328 let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7329 let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7330 let left_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 0]);
7331 let right_entry = Entry::new(&[0, 0, 0, 0, 0, 0, 0, 1]);
7332 left.insert(&left_entry);
7333 right.insert(&right_entry);
7334 left.union(right);
7335 assert_eq!(left.len(), 2);
7336 }
7337
7338 #[test]
7353 fn union_matches_insertion_reference() {
7354 const KEY_SIZE: usize = 8;
7355 const KEYS: u64 = 12_000;
7359
7360 let build = |start: u64, step: u64| {
7361 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7362 for index in 0..KEYS {
7363 let key = (start + index * step).to_be_bytes();
7364 tree.insert(&Entry::new(&key));
7365 }
7366 tree
7367 };
7368
7369 let mut united = build(0, 2);
7373 united.union(build(1, 2));
7374
7375 let mut reference = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7376 for index in 0..(2 * KEYS) {
7377 reference.insert(&Entry::new(&index.to_be_bytes()));
7378 }
7379
7380 assert_eq!(united.len(), 2 * KEYS);
7381 assert_eq!(united.len(), reference.len());
7382 assert_eq!(united, reference);
7383
7384 let mut united_keys = Vec::new();
7385 united.infixes(&[0u8; 0], &mut |&key: &[u8; KEY_SIZE]| {
7386 united_keys.push(key)
7387 });
7388 let mut reference_keys = Vec::new();
7389 reference.infixes(&[0u8; 0], &mut |&key: &[u8; KEY_SIZE]| {
7390 reference_keys.push(key)
7391 });
7392 united_keys.sort_unstable();
7393 reference_keys.sort_unstable();
7394 assert_eq!(united_keys, reference_keys);
7395 }
7396
7397 proptest! {
7403 #[test]
7404 fn tree_insert(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
7405 let mut tree = PATCH::<64, IdentitySchema, ()>::new();
7406 for key in keys {
7407 let key: [u8; 64] = key.try_into().unwrap();
7408 let entry = Entry::new(&key);
7409 tree.insert(&entry);
7410 }
7411 }
7412
7413 #[test]
7414 fn tree_len(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
7415 let mut tree = PATCH::<64, IdentitySchema, ()>::new();
7416 let mut set = HashSet::new();
7417 for key in keys {
7418 let key: [u8; 64] = key.try_into().unwrap();
7419 let entry = Entry::new(&key);
7420 tree.insert(&entry);
7421 set.insert(key);
7422 }
7423
7424 prop_assert_eq!(set.len() as u64, tree.len())
7425 }
7426
7427 #[test]
7428 fn tree_infixes(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
7429 let mut tree = PATCH::<64, IdentitySchema, ()>::new();
7430 let mut set = HashSet::new();
7431 for key in keys {
7432 let key: [u8; 64] = key.try_into().unwrap();
7433 let entry = Entry::new(&key);
7434 tree.insert(&entry);
7435 set.insert(key);
7436 }
7437 let mut set_vec = Vec::from_iter(set.into_iter());
7438 let mut tree_vec = vec![];
7439 tree.infixes(&[0; 0], &mut |&x: &[u8; 64]| tree_vec.push(x));
7440
7441 set_vec.sort();
7442 tree_vec.sort();
7443
7444 prop_assert_eq!(set_vec, tree_vec);
7445 }
7446
7447 #[test]
7448 fn tree_iter(keys in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 1..1024)) {
7449 let mut tree = PATCH::<64, IdentitySchema, ()>::new();
7450 let mut set = HashSet::new();
7451 for key in keys {
7452 let key: [u8; 64] = key.try_into().unwrap();
7453 let entry = Entry::new(&key);
7454 tree.insert(&entry);
7455 set.insert(key);
7456 }
7457 let mut set_vec = Vec::from_iter(set.into_iter());
7458 let mut tree_vec = vec![];
7459 for key in &tree {
7460 tree_vec.push(*key);
7461 }
7462
7463 set_vec.sort();
7464 tree_vec.sort();
7465
7466 prop_assert_eq!(set_vec, tree_vec);
7467 }
7468
7469 #[test]
7470 fn tree_union(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200),
7471 right in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 200)) {
7472 let mut set = HashSet::new();
7473
7474 let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
7475 for entry in left {
7476 let mut key = [0; 64];
7477 key.iter_mut().set_from(entry.iter().cloned());
7478 let entry = Entry::new(&key);
7479 left_tree.insert(&entry);
7480 set.insert(key);
7481 }
7482
7483 let mut right_tree = PATCH::<64, IdentitySchema, ()>::new();
7484 for entry in right {
7485 let mut key = [0; 64];
7486 key.iter_mut().set_from(entry.iter().cloned());
7487 let entry = Entry::new(&key);
7488 right_tree.insert(&entry);
7489 set.insert(key);
7490 }
7491
7492 left_tree.union(right_tree);
7493
7494 let mut set_vec = Vec::from_iter(set.into_iter());
7495 let mut tree_vec = vec![];
7496 left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
7497
7498 set_vec.sort();
7499 tree_vec.sort();
7500
7501 prop_assert_eq!(set_vec, tree_vec);
7502 }
7503
7504 #[test]
7505 fn tree_union_empty(left in prop::collection::vec(prop::collection::vec(0u8..=255, 64), 2)) {
7506 let mut set = HashSet::new();
7507
7508 let mut left_tree = PATCH::<64, IdentitySchema, ()>::new();
7509 for entry in left {
7510 let mut key = [0; 64];
7511 key.iter_mut().set_from(entry.iter().cloned());
7512 let entry = Entry::new(&key);
7513 left_tree.insert(&entry);
7514 set.insert(key);
7515 }
7516
7517 let right_tree = PATCH::<64, IdentitySchema, ()>::new();
7518
7519 left_tree.union(right_tree);
7520
7521 let mut set_vec = Vec::from_iter(set.into_iter());
7522 let mut tree_vec = vec![];
7523 left_tree.infixes(&[0; 0], &mut |&x: &[u8;64]| tree_vec.push(x));
7524
7525 set_vec.sort();
7526 tree_vec.sort();
7527
7528 prop_assert_eq!(set_vec, tree_vec);
7529 }
7530
7531 #[test]
7536 fn cow_on_insert(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
7537 new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
7538 let mut tree = PATCH::<8, IdentitySchema, ()>::new();
7543 for key in base_keys {
7544 let key: [u8; 8] = key[..].try_into().unwrap();
7545 let entry = Entry::new(&key);
7546 tree.insert(&entry);
7547 }
7548 let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
7549
7550 let mut tree_clone = tree.clone();
7551 for key in new_keys {
7552 let key: [u8; 8] = key[..].try_into().unwrap();
7553 let entry = Entry::new(&key);
7554 tree_clone.insert(&entry);
7555 }
7556
7557 let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
7558 prop_assert_eq!(base_tree_content, new_tree_content);
7559 }
7560
7561 #[test]
7562 fn cow_on_union(base_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024),
7563 new_keys in prop::collection::vec(prop::collection::vec(0u8..=255, 8), 1..1024)) {
7564 let mut tree = PATCH::<8, IdentitySchema, ()>::new();
7569 for key in base_keys {
7570 let key: [u8; 8] = key[..].try_into().unwrap();
7571 let entry = Entry::new(&key);
7572 tree.insert(&entry);
7573 }
7574 let base_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
7575
7576 let mut tree_clone = tree.clone();
7577 let mut new_tree = PATCH::<8, IdentitySchema, ()>::new();
7578 for key in new_keys {
7579 let key: [u8; 8] = key[..].try_into().unwrap();
7580 let entry = Entry::new(&key);
7581 new_tree.insert(&entry);
7582 }
7583 tree_clone.union(new_tree);
7584
7585 let new_tree_content: Vec<[u8; 8]> = tree.iter().copied().collect();
7586 prop_assert_eq!(base_tree_content, new_tree_content);
7587 }
7588 }
7589
7590 #[test]
7591 fn intersect_multiple_common_children_commits_branchmut() {
7592 const KEY_SIZE: usize = 4;
7593 let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7594 let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7595
7596 let a = [0u8, 0u8, 0u8, 1u8];
7597 let b = [0u8, 0u8, 0u8, 2u8];
7598 let c = [0u8, 0u8, 0u8, 3u8];
7599 let d = [2u8, 0u8, 0u8, 0u8];
7600 let e = [3u8, 0u8, 0u8, 0u8];
7601
7602 left.insert(&Entry::with_value(&a, 1));
7603 left.insert(&Entry::with_value(&b, 2));
7604 left.insert(&Entry::with_value(&c, 3));
7605 left.insert(&Entry::with_value(&d, 4));
7606
7607 right.insert(&Entry::with_value(&a, 10));
7608 right.insert(&Entry::with_value(&b, 11));
7609 right.insert(&Entry::with_value(&c, 12));
7610 right.insert(&Entry::with_value(&e, 13));
7611
7612 let res = left.intersect(&right);
7613 assert_eq!(res.len(), 3);
7615 assert!(res.get(&a).is_some());
7616 assert!(res.get(&b).is_some());
7617 assert!(res.get(&c).is_some());
7618 }
7619
7620 #[test]
7621 fn difference_multiple_children_commits_branchmut() {
7622 const KEY_SIZE: usize = 4;
7623 let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7624 let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7625
7626 let a = [0u8, 0u8, 0u8, 1u8];
7627 let b = [0u8, 0u8, 0u8, 2u8];
7628 let c = [0u8, 0u8, 0u8, 3u8];
7629 let d = [2u8, 0u8, 0u8, 0u8];
7630 let e = [3u8, 0u8, 0u8, 0u8];
7631
7632 left.insert(&Entry::with_value(&a, 1));
7633 left.insert(&Entry::with_value(&b, 2));
7634 left.insert(&Entry::with_value(&c, 3));
7635 left.insert(&Entry::with_value(&d, 4));
7636
7637 right.insert(&Entry::with_value(&a, 10));
7638 right.insert(&Entry::with_value(&b, 11));
7639 right.insert(&Entry::with_value(&c, 12));
7640 right.insert(&Entry::with_value(&e, 13));
7641
7642 let res = left.difference(&right);
7643 assert_eq!(res.len(), 1);
7645 assert!(res.get(&d).is_some());
7646 }
7647
7648 #[test]
7649 fn difference_equal_singleton_after_survivor_collapse_is_empty() {
7650 const KEY_SIZE: usize = 16;
7651 let removed_key = [0x10; KEY_SIZE];
7652 let survivor_key = [0x20; KEY_SIZE];
7653
7654 let mut pair = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7655 pair.insert(&Entry::with_value(&removed_key, 1));
7656 pair.insert(&Entry::with_value(&survivor_key, 2));
7657
7658 let mut removed = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7659 removed.insert(&Entry::with_value(&removed_key, 1));
7660 let collapsed_survivor = pair.difference(&removed);
7661 assert_eq!(collapsed_survivor.len(), 1);
7662 assert_eq!(
7663 collapsed_survivor.root.as_ref().map(Head::tag),
7664 Some(HeadTag::Leaf),
7665 );
7666
7667 let mut survivor = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7668 survivor.insert(&Entry::with_value(&survivor_key, 2));
7669 assert_eq!(collapsed_survivor, survivor);
7670 assert!(collapsed_survivor.difference(&survivor).root.is_none());
7671 }
7672
7673 #[test]
7674 fn difference_empty_left_is_empty() {
7675 const KEY_SIZE: usize = 4;
7676 let left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7677 let mut right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7678 let key = [1u8, 2u8, 3u8, 4u8];
7679 right.insert(&Entry::with_value(&key, 7));
7680
7681 let res = left.difference(&right);
7682 assert_eq!(res.len(), 0);
7683 }
7684
7685 fn inclusion_agrees_with_difference<const KEY_SIZE: usize>(
7686 left: &PATCH<KEY_SIZE, IdentitySchema, ()>,
7687 right: &PATCH<KEY_SIZE, IdentitySchema, ()>,
7688 ) {
7689 let left_inside = left.difference(right).is_empty();
7690 let right_inside = right.difference(left).is_empty();
7691 let expected = match (left_inside, right_inside) {
7692 (true, true) => Some(std::cmp::Ordering::Equal),
7693 (true, false) => Some(std::cmp::Ordering::Less),
7694 (false, true) => Some(std::cmp::Ordering::Greater),
7695 (false, false) => None,
7696 };
7697 assert_eq!(left.partial_cmp(right), expected);
7698 assert_eq!(right.partial_cmp(left), expected.map(std::cmp::Ordering::reverse));
7699 assert_eq!(left <= right, left_inside);
7700 assert_eq!(right <= left, right_inside);
7701 }
7702
7703 #[test]
7704 fn inclusion_matches_the_difference_oracle_on_wide_random_keys() {
7705 use rand::RngCore;
7706 const KEY_SIZE: usize = 32;
7707 let mut rng = thread_rng();
7708 for _ in 0..64 {
7709 let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7710 let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7711 for _ in 0..(rng.next_u32() % 48) {
7712 let mut key = [0u8; KEY_SIZE];
7713 rng.fill_bytes(&mut key);
7714 match rng.next_u32() % 3 {
7716 0 => {
7717 left.insert(&Entry::new(&key));
7718 right.insert(&Entry::new(&key));
7719 }
7720 1 => left.insert(&Entry::new(&key)),
7721 _ => right.insert(&Entry::new(&key)),
7722 }
7723 }
7724 inclusion_agrees_with_difference(&left, &right);
7725 let mut union = left.clone();
7726 union.union(right.clone());
7727 assert!(left <= union);
7728 assert!(right <= union);
7729 assert_eq!(union <= left, right <= left);
7730 assert_eq!(union == left, right <= left);
7731 }
7732 }
7733
7734 #[test]
7735 fn inclusion_matches_the_difference_oracle_on_narrow_alphabets() {
7736 use rand::RngCore;
7737 const KEY_SIZE: usize = 8;
7741 let mut rng = thread_rng();
7742 for _ in 0..256 {
7743 let mut left = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7744 let mut right = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7745 for _ in 0..(rng.next_u32() % 24) {
7746 let mut key = [0u8; KEY_SIZE];
7747 for byte in &mut key {
7748 *byte = (rng.next_u32() % 3) as u8;
7749 }
7750 match rng.next_u32() % 3 {
7751 0 => {
7752 left.insert(&Entry::new(&key));
7753 right.insert(&Entry::new(&key));
7754 }
7755 1 => left.insert(&Entry::new(&key)),
7756 _ => right.insert(&Entry::new(&key)),
7757 }
7758 }
7759 inclusion_agrees_with_difference(&left, &right);
7760 let empty = PATCH::<KEY_SIZE, IdentitySchema, ()>::new();
7761 assert!(empty <= left);
7762 assert_eq!(left <= empty, left.is_empty());
7763 assert_eq!(left.partial_cmp(&left), Some(std::cmp::Ordering::Equal));
7764 }
7765 }
7766
7767 #[test]
7768 fn difference_empty_right_returns_left() {
7769 const KEY_SIZE: usize = 4;
7770 let mut left = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7771 let right = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7772 let key = [1u8, 2u8, 3u8, 4u8];
7773 left.insert(&Entry::with_value(&key, 7));
7774
7775 let res = left.difference(&right);
7776 assert_eq!(res.len(), 1);
7777 assert!(res.get(&key).is_some());
7778 }
7779
7780 #[test]
7781 fn slot_edit_branchmut_insert_update() {
7782 const KEY_SIZE: usize = 8;
7784 let mut tree = PATCH::<KEY_SIZE, IdentitySchema, u32>::new();
7785
7786 let entry1 = Entry::with_value(&[0u8; KEY_SIZE], 1u32);
7787 let entry2 = Entry::with_value(&[1u8; KEY_SIZE], 2u32);
7788 tree.insert(&entry1);
7789 tree.insert(&entry2);
7790 assert_eq!(tree.len(), 2);
7791
7792 {
7794 let mut ed = crate::patch::branch::BranchMut::from_slot(&mut tree.root);
7795
7796 let start_depth = ed.end_depth as usize;
7798 let inserted = Entry::with_value(&[2u8; KEY_SIZE], 3u32)
7799 .leaf::<IdentitySchema>()
7800 .with_start(start_depth);
7801 let key = inserted.key();
7802
7803 ed.modify_child(key, |opt| match opt {
7804 Some(old) => Some(Head::insert_leaf(old, inserted, start_depth)),
7805 None => Some(inserted),
7806 });
7807 }
7809
7810 assert_eq!(tree.len(), 3);
7811 assert_eq!(tree.get(&[2u8; KEY_SIZE]), Some(&3u32));
7812 }
7813}