1mod search;
4
5use std::cmp::Ordering;
6use std::collections::{BTreeMap, BTreeSet};
7use std::future::Future;
8use std::pin::Pin;
9use std::sync::Arc;
10
11use hashtree_core::{
12 Cid, DirEntry, HashTree, HashTreeConfig, HashTreeError, LinkType, Store, TreeEntry,
13};
14pub use search::{
15 SearchError, SearchIndex, SearchIndexOptions, SearchLinkResult, SearchOptions, SearchResult,
16};
17
18const DEFAULT_ORDER: usize = 32;
19
20#[derive(Debug, Clone, Default)]
21pub struct BTreeOptions {
22 pub order: Option<usize>,
23}
24
25#[derive(Debug, thiserror::Error)]
26pub enum BTreeError {
27 #[error("hash tree error: {0}")]
28 HashTree(#[from] HashTreeError),
29 #[error("value was not valid utf-8: {0}")]
30 Utf8(#[from] std::string::FromUtf8Error),
31}
32
33#[derive(Debug, Clone)]
34struct SplitResult {
35 left: Cid,
36 right: Cid,
37 left_first_key: String,
38 right_first_key: String,
39 left_count: u64,
40 right_count: u64,
41}
42
43#[derive(Debug, Clone)]
44enum InsertValue {
45 String(String),
46 Link(Cid),
47}
48
49type BTreeFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T, BTreeError>> + 'a>>;
50
51pub struct BTree<S: Store> {
52 tree: HashTree<S>,
53 max_keys: usize,
54}
55
56#[derive(Debug, Clone)]
57struct BuiltNode {
58 first_key: String,
59 cid: Cid,
60 count: u64,
61}
62
63impl<S: Store> BTree<S> {
64 pub fn new(store: Arc<S>, options: BTreeOptions) -> Self {
65 let order = options.order.unwrap_or(DEFAULT_ORDER).max(2);
66 Self {
67 tree: HashTree::new(HashTreeConfig::new(store)),
68 max_keys: order - 1,
69 }
70 }
71
72 pub async fn insert(
73 &self,
74 root: Option<&Cid>,
75 key: &str,
76 value: &str,
77 ) -> Result<Cid, BTreeError> {
78 if let Some(root) = root {
79 if self.get(Some(root), key).await?.as_deref() == Some(value) {
80 return Ok(root.clone());
81 }
82
83 let result = self
84 .insert_recursive(
85 root.clone(),
86 key.to_string(),
87 InsertValue::String(value.to_string()),
88 )
89 .await?;
90 return self.finish_insert(result).await;
91 }
92
93 self.create_leaf(&[(key.to_string(), value.to_string())])
94 .await
95 }
96
97 pub async fn get(&self, root: Option<&Cid>, key: &str) -> Result<Option<String>, BTreeError> {
98 let Some(root) = root else {
99 return Ok(None);
100 };
101 self.get_recursive(root.clone(), key.to_string()).await
102 }
103
104 pub async fn insert_link(
105 &self,
106 root: Option<&Cid>,
107 key: &str,
108 target_cid: &Cid,
109 ) -> Result<Cid, BTreeError> {
110 if let Some(root) = root {
111 if self
112 .get_link(Some(root), key)
113 .await?
114 .is_some_and(|existing| cid_equals(&existing, target_cid))
115 {
116 return Ok(root.clone());
117 }
118
119 let result = self
120 .insert_recursive(
121 root.clone(),
122 key.to_string(),
123 InsertValue::Link(target_cid.clone()),
124 )
125 .await?;
126 return self.finish_insert(result).await;
127 }
128
129 self.create_leaf_with_links(&[(key.to_string(), target_cid.clone())])
130 .await
131 }
132
133 pub async fn insert_link_unchecked(
134 &self,
135 root: Option<&Cid>,
136 key: &str,
137 target_cid: &Cid,
138 ) -> Result<Cid, BTreeError> {
139 if let Some(root) = root {
140 let result = self
141 .insert_recursive(
142 root.clone(),
143 key.to_string(),
144 InsertValue::Link(target_cid.clone()),
145 )
146 .await?;
147 return self.finish_insert(result).await;
148 }
149
150 self.create_leaf_with_links(&[(key.to_string(), target_cid.clone())])
151 .await
152 }
153
154 pub async fn get_link(&self, root: Option<&Cid>, key: &str) -> Result<Option<Cid>, BTreeError> {
155 let Some(root) = root else {
156 return Ok(None);
157 };
158 self.get_link_recursive(root.clone(), key.to_string()).await
159 }
160
161 pub async fn get_links<I>(
164 &self,
165 root: Option<&Cid>,
166 keys: I,
167 ) -> Result<BTreeMap<String, Cid>, BTreeError>
168 where
169 I: IntoIterator<Item = String>,
170 {
171 let keys = keys.into_iter().collect::<BTreeSet<_>>();
172 let Some(root) = root else {
173 return Ok(BTreeMap::new());
174 };
175 if keys.is_empty() {
176 return Ok(BTreeMap::new());
177 }
178 self.get_links_recursive(root.clone(), &keys.into_iter().collect::<Vec<_>>())
179 .await
180 }
181
182 pub async fn entries(&self, root: Option<&Cid>) -> Result<Vec<(String, String)>, BTreeError> {
183 let Some(root) = root else {
184 return Ok(Vec::new());
185 };
186 self.traverse_in_order(root.clone()).await
187 }
188
189 pub async fn links_entries(
190 &self,
191 root: Option<&Cid>,
192 ) -> Result<Vec<(String, Cid)>, BTreeError> {
193 let Some(root) = root else {
194 return Ok(Vec::new());
195 };
196 self.traverse_links_in_order(root.clone()).await
197 }
198
199 pub async fn links_entries_limited(
200 &self,
201 root: Option<&Cid>,
202 limit: usize,
203 ) -> Result<Vec<(String, Cid)>, BTreeError> {
204 if limit == 0 {
205 return Ok(Vec::new());
206 }
207 let Some(root) = root else {
208 return Ok(Vec::new());
209 };
210 self.range_link_traverse_limited(root.clone(), None, None, limit)
211 .await
212 }
213
214 pub async fn count_links(&self, root: Option<&Cid>) -> Result<u64, BTreeError> {
219 self.scan_links(root).await
220 }
221
222 pub async fn scan_links(&self, root: Option<&Cid>) -> Result<u64, BTreeError> {
224 let Some(root) = root else {
225 return Ok(0);
226 };
227 self.count_links_recursive(root.clone()).await
228 }
229
230 pub async fn count_stored_links(&self, root: Option<&Cid>) -> Result<Option<u64>, BTreeError> {
235 let Some(root) = root else {
236 return Ok(Some(0));
237 };
238
239 let entries = self.tree.list_directory(root).await?;
240 if is_leaf_node(&entries) {
241 return Ok(Some(count_link_entries(&entries)));
242 }
243
244 let mut count = 0;
245 for entry in &entries {
246 let Some(child_count) = stored_link_subtree_count(entry) else {
247 return Ok(None);
248 };
249 count += child_count;
250 }
251 Ok(Some(count))
252 }
253
254 pub async fn range(
255 &self,
256 root: &Cid,
257 start: Option<&str>,
258 end: Option<&str>,
259 ) -> Result<Vec<(String, String)>, BTreeError> {
260 self.range_traverse(
261 root.clone(),
262 start.map(ToOwned::to_owned),
263 end.map(ToOwned::to_owned),
264 )
265 .await
266 }
267
268 pub async fn prefix(
269 &self,
270 root: &Cid,
271 prefix: &str,
272 ) -> Result<Vec<(String, String)>, BTreeError> {
273 let end = increment_prefix(prefix);
274 self.range(root, Some(prefix), end.as_deref()).await
275 }
276
277 pub async fn prefix_links(
278 &self,
279 root: &Cid,
280 prefix: &str,
281 ) -> Result<Vec<(String, Cid)>, BTreeError> {
282 let end = increment_prefix(prefix);
283 self.range_link_traverse(root.clone(), Some(prefix.to_string()), end)
284 .await
285 }
286
287 pub async fn prefix_links_limited(
288 &self,
289 root: &Cid,
290 prefix: &str,
291 limit: usize,
292 ) -> Result<Vec<(String, Cid)>, BTreeError> {
293 if limit == 0 {
294 return Ok(Vec::new());
295 }
296 let end = increment_prefix(prefix);
297 self.range_link_traverse_limited(root.clone(), Some(prefix.to_string()), end, limit)
298 .await
299 }
300
301 pub async fn delete(&self, root: &Cid, key: &str) -> Result<Option<Cid>, BTreeError> {
302 self.delete_recursive(root.clone(), key.to_string()).await
303 }
304
305 pub async fn merge(
306 &self,
307 base: Option<&Cid>,
308 other: Option<&Cid>,
309 prefer_other: bool,
310 ) -> Result<Option<Cid>, BTreeError> {
311 let Some(other) = other else {
312 return Ok(base.cloned());
313 };
314 let Some(mut result) = base.cloned().or_else(|| Some(other.clone())) else {
315 return Ok(None);
316 };
317 if base.is_none() {
318 return Ok(Some(result));
319 }
320
321 for (key, value) in self.entries(Some(other)).await? {
322 let existing = self.get(Some(&result), &key).await?;
323 if existing.is_none() || prefer_other {
324 result = self.insert(Some(&result), &key, &value).await?;
325 }
326 }
327
328 Ok(Some(result))
329 }
330
331 pub async fn merge_links(
332 &self,
333 base: Option<&Cid>,
334 other: Option<&Cid>,
335 prefer_other: bool,
336 ) -> Result<Option<Cid>, BTreeError> {
337 let Some(other) = other else {
338 return Ok(base.cloned());
339 };
340 let Some(mut result) = base.cloned().or_else(|| Some(other.clone())) else {
341 return Ok(None);
342 };
343 if base.is_none() {
344 return Ok(Some(result));
345 }
346
347 for (key, value) in self.links_entries(Some(other)).await? {
348 let existing = self.get_link(Some(&result), &key).await?;
349 if existing.is_none() || prefer_other {
350 result = self.insert_link(Some(&result), &key, &value).await?;
351 }
352 }
353
354 Ok(Some(result))
355 }
356
357 pub async fn build<I>(&self, items: I) -> Result<Option<Cid>, BTreeError>
358 where
359 I: IntoIterator<Item = (String, String)>,
360 {
361 let mut sorted: Vec<(String, String)> = items.into_iter().collect();
362 if sorted.is_empty() {
363 return Ok(None);
364 }
365
366 sorted.sort_by(|left, right| left.0.cmp(&right.0));
367
368 let mut deduped = Vec::with_capacity(sorted.len());
369 for (key, value) in sorted {
370 if let Some((last_key, last_value)) = deduped.last_mut() {
371 if *last_key == key {
372 *last_value = value;
373 continue;
374 }
375 }
376 deduped.push((key, value));
377 }
378
379 let mut level = Vec::with_capacity(deduped.len().div_ceil(self.max_keys));
380 for chunk in deduped.chunks(self.max_keys) {
381 let cid = self.create_leaf(chunk).await?;
382 level.push(BuiltNode {
383 first_key: chunk[0].0.clone(),
384 cid,
385 count: chunk.len() as u64,
386 });
387 }
388
389 while level.len() > 1 {
390 let mut next_level = Vec::with_capacity(level.len().div_ceil(self.max_keys));
391 for chunk in level.chunks(self.max_keys) {
392 let cid = self.create_internal_node(chunk).await?;
393 next_level.push(BuiltNode {
394 first_key: chunk[0].first_key.clone(),
395 cid,
396 count: chunk.iter().map(|child| child.count).sum(),
397 });
398 }
399 level = next_level;
400 }
401
402 Ok(level.pop().map(|node| node.cid))
403 }
404
405 pub async fn update<I>(&self, root: Option<&Cid>, changes: I) -> Result<Option<Cid>, BTreeError>
409 where
410 I: IntoIterator<Item = (String, Option<String>)>,
411 {
412 let changes = changes.into_iter().collect::<BTreeMap<_, _>>();
413 if changes.is_empty() {
414 return Ok(root.cloned());
415 }
416
417 let changes = changes.into_iter().collect::<Vec<_>>();
418 let Some(root) = root else {
419 return self
420 .build(
421 changes
422 .into_iter()
423 .filter_map(|(key, value)| value.map(|value| (key, value))),
424 )
425 .await;
426 };
427
428 let nodes = self.update_string_node(root.clone(), &changes).await?;
429 self.finish_link_node_updates(nodes).await
430 }
431
432 fn update_string_node<'a>(
433 &'a self,
434 node: Cid,
435 changes: &'a [(String, Option<String>)],
436 ) -> BTreeFuture<'a, Vec<BuiltNode>> {
437 Box::pin(async move {
438 let entries = sort_entries(self.tree.list_directory(&node).await?);
439 if is_leaf_node(&entries) {
440 return self.update_string_leaf(entries, changes).await;
441 }
442
443 let mut children = Vec::new();
444 let mut change_start = 0;
445 for (child_index, entry) in entries.iter().enumerate() {
446 let change_end = entries
447 .get(child_index + 1)
448 .map(|next| {
449 let next_key = unescape_key(&next.name);
450 change_start
451 + changes[change_start..].partition_point(|(key, _)| key < &next_key)
452 })
453 .unwrap_or(changes.len());
454 if change_start == change_end {
455 let cid = entry_cid(entry);
456 let count = match stored_link_subtree_count(entry) {
457 Some(count) => count,
458 None => self.count_entries_recursive(cid.clone()).await?,
459 };
460 children.push(BuiltNode {
461 first_key: unescape_key(&entry.name),
462 cid,
463 count,
464 });
465 } else {
466 children.extend(
467 self.update_string_node(
468 entry_cid(entry),
469 &changes[change_start..change_end],
470 )
471 .await?,
472 );
473 }
474 change_start = change_end;
475 }
476
477 self.create_link_node_level(children).await
478 })
479 }
480
481 async fn update_string_leaf(
482 &self,
483 entries: Vec<TreeEntry>,
484 changes: &[(String, Option<String>)],
485 ) -> Result<Vec<BuiltNode>, BTreeError> {
486 let mut final_entries = BTreeMap::new();
487 for entry in entries {
488 if entry.link_type != LinkType::Blob {
489 continue;
490 }
491 let Some(data) = self.tree.get(&entry_cid(&entry), None).await? else {
492 continue;
493 };
494 final_entries.insert(unescape_key(&entry.name), String::from_utf8(data)?);
495 }
496 for (key, value) in changes {
497 match value {
498 Some(value) => {
499 final_entries.insert(key.clone(), value.clone());
500 }
501 None => {
502 final_entries.remove(key);
503 }
504 }
505 }
506
507 let final_entries = final_entries.into_iter().collect::<Vec<_>>();
508 let mut nodes = Vec::with_capacity(final_entries.len().div_ceil(self.max_keys));
509 for chunk in final_entries.chunks(self.max_keys) {
510 let cid = self.create_leaf(chunk).await?;
511 nodes.push(BuiltNode {
512 first_key: chunk[0].0.clone(),
513 cid,
514 count: chunk.len() as u64,
515 });
516 }
517 Ok(nodes)
518 }
519
520 pub async fn build_links<I>(&self, items: I) -> Result<Option<Cid>, BTreeError>
521 where
522 I: IntoIterator<Item = (String, Cid)>,
523 {
524 let mut sorted: Vec<(String, Cid)> = items.into_iter().collect();
525 if sorted.is_empty() {
526 return Ok(None);
527 }
528
529 sorted.sort_by(|left, right| left.0.cmp(&right.0));
530
531 let mut deduped = Vec::with_capacity(sorted.len());
532 for (key, cid) in sorted {
533 if let Some((last_key, last_cid)) = deduped.last_mut() {
534 if *last_key == key {
535 *last_cid = cid;
536 continue;
537 }
538 }
539 deduped.push((key, cid));
540 }
541
542 let mut level = Vec::with_capacity(deduped.len().div_ceil(self.max_keys));
543 for chunk in deduped.chunks(self.max_keys) {
544 let cid = self.create_leaf_with_links(chunk).await?;
545 level.push(BuiltNode {
546 first_key: chunk[0].0.clone(),
547 cid,
548 count: chunk.len() as u64,
549 });
550 }
551
552 while level.len() > 1 {
553 let mut next_level = Vec::with_capacity(level.len().div_ceil(self.max_keys));
554 for chunk in level.chunks(self.max_keys) {
555 let cid = self.create_internal_node(chunk).await?;
556 next_level.push(BuiltNode {
557 first_key: chunk[0].first_key.clone(),
558 cid,
559 count: chunk.iter().map(|child| child.count).sum(),
560 });
561 }
562 level = next_level;
563 }
564
565 Ok(level.pop().map(|node| node.cid))
566 }
567
568 pub async fn update_links<I>(
572 &self,
573 root: Option<&Cid>,
574 changes: I,
575 ) -> Result<Option<Cid>, BTreeError>
576 where
577 I: IntoIterator<Item = (String, Option<Cid>)>,
578 {
579 let changes = changes.into_iter().collect::<BTreeMap<_, _>>();
580 if changes.is_empty() {
581 return Ok(root.cloned());
582 }
583
584 let changes = changes.into_iter().collect::<Vec<_>>();
585 let Some(root) = root else {
586 return self
587 .build_links(
588 changes
589 .into_iter()
590 .filter_map(|(key, cid)| cid.map(|cid| (key, cid))),
591 )
592 .await;
593 };
594
595 let nodes = self.update_link_node(root.clone(), &changes).await?;
596 self.finish_link_node_updates(nodes).await
597 }
598
599 fn update_link_node<'a>(
600 &'a self,
601 node: Cid,
602 changes: &'a [(String, Option<Cid>)],
603 ) -> BTreeFuture<'a, Vec<BuiltNode>> {
604 Box::pin(async move {
605 let entries = sort_entries(self.tree.list_directory(&node).await?);
606 if is_leaf_node(&entries) {
607 return self.update_link_leaf(entries, changes).await;
608 }
609
610 let mut children = Vec::new();
611 let mut change_start = 0;
612 for (child_index, entry) in entries.iter().enumerate() {
613 let change_end = entries
614 .get(child_index + 1)
615 .map(|next| {
616 let next_key = unescape_key(&next.name);
617 change_start
618 + changes[change_start..].partition_point(|(key, _)| key < &next_key)
619 })
620 .unwrap_or(changes.len());
621 if change_start == change_end {
622 let cid = entry_cid(entry);
623 let count = match stored_link_subtree_count(entry) {
624 Some(count) => count,
625 None => self.count_links_recursive(cid.clone()).await?,
626 };
627 children.push(BuiltNode {
628 first_key: unescape_key(&entry.name),
629 cid,
630 count,
631 });
632 } else {
633 children.extend(
634 self.update_link_node(entry_cid(entry), &changes[change_start..change_end])
635 .await?,
636 );
637 }
638 change_start = change_end;
639 }
640
641 self.create_link_node_level(children).await
642 })
643 }
644
645 async fn update_link_leaf(
646 &self,
647 entries: Vec<TreeEntry>,
648 changes: &[(String, Option<Cid>)],
649 ) -> Result<Vec<BuiltNode>, BTreeError> {
650 let mut final_entries = entries
651 .into_iter()
652 .map(|entry| (unescape_key(&entry.name), entry_cid(&entry)))
653 .collect::<BTreeMap<_, _>>();
654 for (key, cid) in changes {
655 match cid {
656 Some(cid) => {
657 final_entries.insert(key.clone(), cid.clone());
658 }
659 None => {
660 final_entries.remove(key);
661 }
662 }
663 }
664
665 let final_entries = final_entries.into_iter().collect::<Vec<_>>();
666 let mut nodes = Vec::with_capacity(final_entries.len().div_ceil(self.max_keys));
667 for chunk in final_entries.chunks(self.max_keys) {
668 let cid = self.create_leaf_with_links(chunk).await?;
669 nodes.push(BuiltNode {
670 first_key: chunk[0].0.clone(),
671 cid,
672 count: chunk.len() as u64,
673 });
674 }
675 Ok(nodes)
676 }
677
678 async fn create_link_node_level(
679 &self,
680 children: Vec<BuiltNode>,
681 ) -> Result<Vec<BuiltNode>, BTreeError> {
682 let mut nodes = Vec::with_capacity(children.len().div_ceil(self.max_keys));
683 for chunk in children.chunks(self.max_keys) {
684 let cid = self.create_internal_node(chunk).await?;
685 nodes.push(BuiltNode {
686 first_key: chunk[0].first_key.clone(),
687 cid,
688 count: chunk.iter().map(|child| child.count).sum(),
689 });
690 }
691 Ok(nodes)
692 }
693
694 async fn finish_link_node_updates(
695 &self,
696 mut nodes: Vec<BuiltNode>,
697 ) -> Result<Option<Cid>, BTreeError> {
698 while nodes.len() > 1 {
699 nodes = self.create_link_node_level(nodes).await?;
700 }
701 Ok(nodes.pop().map(|node| node.cid))
702 }
703
704 async fn finish_insert(&self, result: InsertResult) -> Result<Cid, BTreeError> {
705 if let Some(split) = result.split {
706 return self
707 .create_internal_root(
708 &split.left_first_key,
709 &split.left,
710 split.left_count,
711 &split.right_first_key,
712 &split.right,
713 split.right_count,
714 )
715 .await;
716 }
717 Ok(result.cid)
718 }
719
720 fn get_recursive<'a>(&'a self, root: Cid, key: String) -> BTreeFuture<'a, Option<String>> {
721 Box::pin(async move {
722 let entries = self.tree.list_directory(&root).await?;
723 if is_leaf_node(&entries) {
724 let escaped = escape_key(&key);
725 let Some(entry) = entries.iter().find(|entry| entry.name == escaped) else {
726 return Ok(None);
727 };
728 if entry.link_type != LinkType::Blob {
729 return Ok(None);
730 }
731
732 let cid = entry_cid(entry);
733 let Some(data) = self.tree.get(&cid, None).await? else {
734 return Ok(None);
735 };
736 return Ok(Some(String::from_utf8(data)?));
737 }
738
739 let child = find_child(&entries, &key);
740 self.get_recursive(entry_cid(&child), key).await
741 })
742 }
743
744 fn get_link_recursive<'a>(&'a self, root: Cid, key: String) -> BTreeFuture<'a, Option<Cid>> {
745 Box::pin(async move {
746 let entries = self.tree.list_directory(&root).await?;
747 if is_leaf_node(&entries) {
748 let escaped = escape_key(&key);
749 let Some(entry) = entries.iter().find(|entry| entry.name == escaped) else {
750 return Ok(None);
751 };
752 if entry.link_type != LinkType::File {
753 return Ok(None);
754 }
755 return Ok(Some(entry_cid(entry)));
756 }
757
758 let child = find_child(&entries, &key);
759 self.get_link_recursive(entry_cid(&child), key).await
760 })
761 }
762
763 fn get_links_recursive<'a>(
764 &'a self,
765 root: Cid,
766 keys: &'a [String],
767 ) -> BTreeFuture<'a, BTreeMap<String, Cid>> {
768 Box::pin(async move {
769 let entries = sort_entries(self.tree.list_directory(&root).await?);
770 if is_leaf_node(&entries) {
771 let links = entries
772 .into_iter()
773 .map(|entry| (unescape_key(&entry.name), entry_cid(&entry)))
774 .collect::<BTreeMap<_, _>>();
775 return Ok(keys
776 .iter()
777 .filter_map(|key| links.get(key).cloned().map(|cid| (key.clone(), cid)))
778 .collect());
779 }
780
781 let mut found = BTreeMap::new();
782 let mut key_start = 0;
783 for (child_index, entry) in entries.iter().enumerate() {
784 let key_end = entries
785 .get(child_index + 1)
786 .map(|next| {
787 let next_key = unescape_key(&next.name);
788 key_start + keys[key_start..].partition_point(|key| key < &next_key)
789 })
790 .unwrap_or(keys.len());
791 if key_start < key_end {
792 found.extend(
793 self.get_links_recursive(entry_cid(entry), &keys[key_start..key_end])
794 .await?,
795 );
796 }
797 key_start = key_end;
798 }
799 Ok(found)
800 })
801 }
802
803 fn insert_recursive<'a>(
804 &'a self,
805 node: Cid,
806 key: String,
807 value: InsertValue,
808 ) -> BTreeFuture<'a, InsertResult> {
809 Box::pin(async move {
810 let entries = self.tree.list_directory(&node).await?;
811 if is_leaf_node(&entries) {
812 return self.insert_into_leaf(node, entries, key, value).await;
813 }
814 self.insert_into_internal(node, entries, key, value).await
815 })
816 }
817
818 fn insert_into_leaf<'a>(
819 &'a self,
820 node: Cid,
821 _entries: Vec<TreeEntry>,
822 key: String,
823 value: InsertValue,
824 ) -> BTreeFuture<'a, InsertResult> {
825 Box::pin(async move {
826 let escaped_key = escape_key(&key);
827 let (entry_cid, size, link_type) = match value {
828 InsertValue::String(value) => {
829 let (cid, size) = self.tree.put_file(value.as_bytes()).await?;
830 (cid, size, LinkType::Blob)
831 }
832 InsertValue::Link(cid) => (cid, 0, LinkType::File),
833 };
834
835 let new_node = self
836 .tree
837 .set_entry(&node, &[], &escaped_key, &entry_cid, size, link_type)
838 .await?;
839
840 let new_entries = self.tree.list_directory(&new_node).await?;
841 if new_entries.len() > self.max_keys {
842 return Ok(InsertResult {
843 cid: new_node,
844 count: count_link_entries_or_subtrees(self, &new_entries).await?,
845 split: Some(self.split_leaf(new_entries).await?),
846 });
847 }
848
849 Ok(InsertResult {
850 cid: new_node,
851 count: count_link_entries_or_subtrees(self, &new_entries).await?,
852 split: None,
853 })
854 })
855 }
856
857 fn insert_into_internal<'a>(
858 &'a self,
859 node: Cid,
860 entries: Vec<TreeEntry>,
861 key: String,
862 value: InsertValue,
863 ) -> BTreeFuture<'a, InsertResult> {
864 Box::pin(async move {
865 let child = find_child(&entries, &key);
866 let child_name = child.name.clone();
867 let child_cid = entry_cid(&child);
868 let result = self.insert_recursive(child_cid, key, value).await?;
869
870 let mut new_node = self
871 .tree
872 .set_entry(
873 &node,
874 &[],
875 &child_name,
876 &result.cid,
877 result.count,
878 LinkType::Dir,
879 )
880 .await?;
881
882 if let Some(split) = result.split {
883 new_node = self.tree.remove_entry(&new_node, &[], &child_name).await?;
884 new_node = self
885 .tree
886 .set_entry(
887 &new_node,
888 &[],
889 &escape_key(&split.left_first_key),
890 &split.left,
891 split.left_count,
892 LinkType::Dir,
893 )
894 .await?;
895 new_node = self
896 .tree
897 .set_entry(
898 &new_node,
899 &[],
900 &escape_key(&split.right_first_key),
901 &split.right,
902 split.right_count,
903 LinkType::Dir,
904 )
905 .await?;
906 }
907
908 let new_entries = self.tree.list_directory(&new_node).await?;
909 if new_entries.len() > self.max_keys {
910 return Ok(InsertResult {
911 cid: new_node,
912 count: count_link_entries_or_subtrees(self, &new_entries).await?,
913 split: Some(self.split_internal(new_entries).await?),
914 });
915 }
916
917 Ok(InsertResult {
918 cid: new_node,
919 count: count_link_entries_or_subtrees(self, &new_entries).await?,
920 split: None,
921 })
922 })
923 }
924
925 async fn split_leaf(&self, entries: Vec<TreeEntry>) -> Result<SplitResult, BTreeError> {
926 let sorted = sort_entries(entries);
927 let mid = sorted.len() / 2;
928 let left_entries = &sorted[..mid];
929 let right_entries = &sorted[mid..];
930
931 let left = self.create_node_from_entries(left_entries).await?;
932 let right = self.create_node_from_entries(right_entries).await?;
933
934 Ok(SplitResult {
935 left,
936 right,
937 left_first_key: unescape_key(&left_entries[0].name),
938 right_first_key: unescape_key(&right_entries[0].name),
939 left_count: count_link_entries(left_entries),
940 right_count: count_link_entries(right_entries),
941 })
942 }
943
944 async fn split_internal(&self, entries: Vec<TreeEntry>) -> Result<SplitResult, BTreeError> {
945 let sorted = sort_entries(entries);
946 let mid = sorted.len() / 2;
947 let left_entries = &sorted[..mid];
948 let right_entries = &sorted[mid..];
949
950 let left = self.create_node_from_entries(left_entries).await?;
951 let right = self.create_node_from_entries(right_entries).await?;
952
953 Ok(SplitResult {
954 left,
955 right,
956 left_first_key: unescape_key(&left_entries[0].name),
957 right_first_key: unescape_key(&right_entries[0].name),
958 left_count: count_link_entries_or_subtrees(self, left_entries).await?,
959 right_count: count_link_entries_or_subtrees(self, right_entries).await?,
960 })
961 }
962
963 async fn create_leaf(&self, items: &[(String, String)]) -> Result<Cid, BTreeError> {
964 let mut entries = Vec::with_capacity(items.len());
965 for (key, value) in items {
966 let (cid, size) = self.tree.put_file(value.as_bytes()).await?;
967 entries.push(
968 DirEntry::from_cid(escape_key(key), &cid)
969 .with_size(size)
970 .with_link_type(LinkType::Blob),
971 );
972 }
973 Ok(self.tree.put_directory(entries).await?)
974 }
975
976 async fn create_leaf_with_links(&self, items: &[(String, Cid)]) -> Result<Cid, BTreeError> {
977 let entries: Vec<DirEntry> = items
978 .iter()
979 .map(|(key, cid)| {
980 DirEntry::from_cid(escape_key(key), cid).with_link_type(LinkType::File)
981 })
982 .collect();
983 Ok(self.tree.put_directory(entries).await?)
984 }
985
986 async fn create_internal_node(&self, children: &[BuiltNode]) -> Result<Cid, BTreeError> {
987 let entries: Vec<DirEntry> = children
988 .iter()
989 .map(|child| {
990 DirEntry::from_cid(escape_key(&child.first_key), &child.cid)
991 .with_size(child.count)
992 .with_link_type(LinkType::Dir)
993 })
994 .collect();
995 Ok(self.tree.put_directory(entries).await?)
996 }
997
998 async fn create_internal_root(
999 &self,
1000 left_key: &str,
1001 left: &Cid,
1002 left_count: u64,
1003 right_key: &str,
1004 right: &Cid,
1005 right_count: u64,
1006 ) -> Result<Cid, BTreeError> {
1007 let entries = vec![
1008 DirEntry::from_cid(escape_key(left_key), left)
1009 .with_size(left_count)
1010 .with_link_type(LinkType::Dir),
1011 DirEntry::from_cid(escape_key(right_key), right)
1012 .with_size(right_count)
1013 .with_link_type(LinkType::Dir),
1014 ];
1015 Ok(self.tree.put_directory(entries).await?)
1016 }
1017
1018 async fn create_node_from_entries(&self, entries: &[TreeEntry]) -> Result<Cid, BTreeError> {
1019 let dir_entries = entries
1020 .iter()
1021 .cloned()
1022 .map(tree_entry_to_dir_entry)
1023 .collect::<Vec<_>>();
1024 Ok(self.tree.put_directory(dir_entries).await?)
1025 }
1026
1027 fn delete_recursive<'a>(&'a self, root: Cid, key: String) -> BTreeFuture<'a, Option<Cid>> {
1028 Box::pin(async move {
1029 let entries = self.tree.list_directory(&root).await?;
1030 if is_leaf_node(&entries) {
1031 let escaped = escape_key(&key);
1032 if !entries.iter().any(|entry| entry.name == escaped) {
1033 return Ok(Some(root));
1034 }
1035
1036 let new_root = self.tree.remove_entry(&root, &[], &escaped).await?;
1037 let new_entries = self.tree.list_directory(&new_root).await?;
1038 if new_entries.is_empty() {
1039 return Ok(None);
1040 }
1041 return Ok(Some(new_root));
1042 }
1043
1044 let child = find_child(&entries, &key);
1045 let child_name = child.name.clone();
1046 let new_child = self.delete_recursive(entry_cid(&child), key).await?;
1047
1048 let Some(new_child) = new_child else {
1049 let new_root = self.tree.remove_entry(&root, &[], &child_name).await?;
1050 let new_entries = self.tree.list_directory(&new_root).await?;
1051 if new_entries.is_empty() {
1052 return Ok(None);
1053 }
1054 if new_entries.len() == 1 && new_entries[0].link_type == LinkType::Dir {
1055 return Ok(Some(entry_cid(&new_entries[0])));
1056 }
1057 return Ok(Some(new_root));
1058 };
1059
1060 if cid_equals(&new_child, &entry_cid(&child)) {
1061 return Ok(Some(root));
1062 }
1063
1064 let updated = self
1065 .tree
1066 .set_entry(
1067 &root,
1068 &[],
1069 &child_name,
1070 &new_child,
1071 count_link_entries_or_subtrees(
1072 self,
1073 &self.tree.list_directory(&new_child).await?,
1074 )
1075 .await?,
1076 LinkType::Dir,
1077 )
1078 .await?;
1079 Ok(Some(updated))
1080 })
1081 }
1082
1083 fn traverse_in_order<'a>(&'a self, node: Cid) -> BTreeFuture<'a, Vec<(String, String)>> {
1084 Box::pin(async move {
1085 let entries = self.tree.list_directory(&node).await?;
1086 let sorted = sort_entries(entries);
1087 let mut out = Vec::new();
1088
1089 if is_leaf_node(&sorted) {
1090 for entry in sorted {
1091 if entry.link_type != LinkType::Blob {
1092 continue;
1093 }
1094 let cid = entry_cid(&entry);
1095 if let Some(data) = self.tree.get(&cid, None).await? {
1096 out.push((unescape_key(&entry.name), String::from_utf8(data)?));
1097 }
1098 }
1099 return Ok(out);
1100 }
1101
1102 for child in sorted {
1103 out.extend(self.traverse_in_order(entry_cid(&child)).await?);
1104 }
1105 Ok(out)
1106 })
1107 }
1108
1109 fn traverse_links_in_order<'a>(&'a self, node: Cid) -> BTreeFuture<'a, Vec<(String, Cid)>> {
1110 Box::pin(async move {
1111 let entries = self.tree.list_directory(&node).await?;
1112 let sorted = sort_entries(entries);
1113 let mut out = Vec::new();
1114
1115 if is_leaf_node(&sorted) {
1116 for entry in sorted {
1117 if entry.link_type == LinkType::File {
1118 out.push((unescape_key(&entry.name), entry_cid(&entry)));
1119 }
1120 }
1121 return Ok(out);
1122 }
1123
1124 for child in sorted {
1125 out.extend(self.traverse_links_in_order(entry_cid(&child)).await?);
1126 }
1127 Ok(out)
1128 })
1129 }
1130
1131 fn range_traverse<'a>(
1132 &'a self,
1133 node: Cid,
1134 start: Option<String>,
1135 end: Option<String>,
1136 ) -> BTreeFuture<'a, Vec<(String, String)>> {
1137 Box::pin(async move {
1138 let entries = self.tree.list_directory(&node).await?;
1139 let sorted = sort_entries(entries);
1140 let mut out = Vec::new();
1141
1142 if is_leaf_node(&sorted) {
1143 for entry in sorted {
1144 if entry.link_type != LinkType::Blob {
1145 continue;
1146 }
1147 let key = unescape_key(&entry.name);
1148 if start.as_ref().is_some_and(|start| key < *start) {
1149 continue;
1150 }
1151 if end.as_ref().is_some_and(|end| key >= *end) {
1152 return Ok(out);
1153 }
1154
1155 let cid = entry_cid(&entry);
1156 if let Some(data) = self.tree.get(&cid, None).await? {
1157 out.push((key, String::from_utf8(data)?));
1158 }
1159 }
1160 return Ok(out);
1161 }
1162
1163 for (index, child) in sorted.iter().enumerate() {
1164 let child_min = unescape_key(&child.name);
1165 let child_max = sorted.get(index + 1).map(|entry| unescape_key(&entry.name));
1166
1167 if start.as_ref().is_some_and(|start| {
1168 child_max
1169 .as_ref()
1170 .is_some_and(|child_max| child_max <= start)
1171 }) {
1172 continue;
1173 }
1174 if end.as_ref().is_some_and(|end| child_min >= *end) {
1175 return Ok(out);
1176 }
1177
1178 out.extend(
1179 self.range_traverse(entry_cid(child), start.clone(), end.clone())
1180 .await?,
1181 );
1182 }
1183
1184 Ok(out)
1185 })
1186 }
1187
1188 fn range_link_traverse<'a>(
1189 &'a self,
1190 node: Cid,
1191 start: Option<String>,
1192 end: Option<String>,
1193 ) -> BTreeFuture<'a, Vec<(String, Cid)>> {
1194 Box::pin(async move {
1195 let entries = self.tree.list_directory(&node).await?;
1196 let sorted = sort_entries(entries);
1197 let mut out = Vec::new();
1198
1199 if is_leaf_node(&sorted) {
1200 for entry in sorted {
1201 if entry.link_type != LinkType::File {
1202 continue;
1203 }
1204 let key = unescape_key(&entry.name);
1205 if start.as_ref().is_some_and(|start| key < *start) {
1206 continue;
1207 }
1208 if end.as_ref().is_some_and(|end| key >= *end) {
1209 return Ok(out);
1210 }
1211 out.push((key, entry_cid(&entry)));
1212 }
1213 return Ok(out);
1214 }
1215
1216 for (index, child) in sorted.iter().enumerate() {
1217 let child_min = unescape_key(&child.name);
1218 let child_max = sorted.get(index + 1).map(|entry| unescape_key(&entry.name));
1219
1220 if start.as_ref().is_some_and(|start| {
1221 child_max
1222 .as_ref()
1223 .is_some_and(|child_max| child_max <= start)
1224 }) {
1225 continue;
1226 }
1227 if end.as_ref().is_some_and(|end| child_min >= *end) {
1228 return Ok(out);
1229 }
1230
1231 out.extend(
1232 self.range_link_traverse(entry_cid(child), start.clone(), end.clone())
1233 .await?,
1234 );
1235 }
1236
1237 Ok(out)
1238 })
1239 }
1240
1241 fn range_link_traverse_limited<'a>(
1242 &'a self,
1243 node: Cid,
1244 start: Option<String>,
1245 end: Option<String>,
1246 limit: usize,
1247 ) -> BTreeFuture<'a, Vec<(String, Cid)>> {
1248 Box::pin(async move {
1249 let entries = self.tree.list_directory(&node).await?;
1250 let sorted = sort_entries(entries);
1251 let mut out = Vec::new();
1252
1253 if is_leaf_node(&sorted) {
1254 for entry in sorted {
1255 if entry.link_type != LinkType::File {
1256 continue;
1257 }
1258 let key = unescape_key(&entry.name);
1259 if start.as_ref().is_some_and(|start| key < *start) {
1260 continue;
1261 }
1262 if end.as_ref().is_some_and(|end| key >= *end) {
1263 return Ok(out);
1264 }
1265 out.push((key, entry_cid(&entry)));
1266 if out.len() >= limit {
1267 return Ok(out);
1268 }
1269 }
1270 return Ok(out);
1271 }
1272
1273 for (index, child) in sorted.iter().enumerate() {
1274 let child_min = unescape_key(&child.name);
1275 let child_max = sorted.get(index + 1).map(|entry| unescape_key(&entry.name));
1276
1277 if start.as_ref().is_some_and(|start| {
1278 child_max
1279 .as_ref()
1280 .is_some_and(|child_max| child_max <= start)
1281 }) {
1282 continue;
1283 }
1284 if end.as_ref().is_some_and(|end| child_min >= *end) {
1285 return Ok(out);
1286 }
1287
1288 let remaining = limit.saturating_sub(out.len());
1289 if remaining == 0 {
1290 return Ok(out);
1291 }
1292 out.extend(
1293 self.range_link_traverse_limited(
1294 entry_cid(child),
1295 start.clone(),
1296 end.clone(),
1297 remaining,
1298 )
1299 .await?,
1300 );
1301 if out.len() >= limit {
1302 return Ok(out);
1303 }
1304 }
1305
1306 Ok(out)
1307 })
1308 }
1309
1310 fn count_links_recursive<'a>(&'a self, node: Cid) -> BTreeFuture<'a, u64> {
1311 Box::pin(async move {
1312 let entries = self.tree.list_directory(&node).await?;
1313 count_link_entries_or_subtrees(self, &entries).await
1314 })
1315 }
1316
1317 fn count_entries_recursive<'a>(&'a self, node: Cid) -> BTreeFuture<'a, u64> {
1318 Box::pin(async move {
1319 let entries = self.tree.list_directory(&node).await?;
1320 if is_leaf_node(&entries) {
1321 return Ok(entries
1322 .iter()
1323 .filter(|entry| entry.link_type == LinkType::Blob)
1324 .count() as u64);
1325 }
1326
1327 let mut count = 0;
1328 for entry in entries {
1329 count += match stored_link_subtree_count(&entry) {
1330 Some(child_count) => child_count,
1331 None => self.count_entries_recursive(entry_cid(&entry)).await?,
1332 };
1333 }
1334 Ok(count)
1335 })
1336 }
1337}
1338
1339#[derive(Debug, Clone)]
1340struct InsertResult {
1341 cid: Cid,
1342 count: u64,
1343 split: Option<SplitResult>,
1344}
1345
1346pub fn escape_key(key: &str) -> String {
1347 key.replace('%', "%25")
1348 .replace('/', "%2F")
1349 .replace('\0', "%00")
1350}
1351
1352pub fn unescape_key(name: &str) -> String {
1353 name.replace("%2F", "/")
1354 .replace("%2f", "/")
1355 .replace("%00", "\0")
1356 .replace("%25", "%")
1357}
1358
1359fn increment_prefix(value: &str) -> Option<String> {
1360 if value.is_empty() {
1361 return Some(String::new());
1362 }
1363
1364 let mut chars: Vec<char> = value.chars().collect();
1365 let last = chars.pop()?;
1366 let next = char::from_u32(last as u32 + 1)?;
1367 chars.push(next);
1368 Some(chars.into_iter().collect())
1369}
1370
1371fn cid_equals(left: &Cid, right: &Cid) -> bool {
1372 left.hash == right.hash && left.key == right.key
1373}
1374
1375fn is_leaf_node(entries: &[TreeEntry]) -> bool {
1376 entries.is_empty() || entries.iter().any(|entry| entry.link_type != LinkType::Dir)
1377}
1378
1379fn sort_entries(mut entries: Vec<TreeEntry>) -> Vec<TreeEntry> {
1380 entries.sort_by(|left, right| compare_unescaped_names(&left.name, &right.name));
1381 entries
1382}
1383
1384fn compare_unescaped_names(left: &str, right: &str) -> Ordering {
1385 unescape_key(left).cmp(&unescape_key(right))
1386}
1387
1388fn find_child(entries: &[TreeEntry], key: &str) -> TreeEntry {
1389 let sorted = sort_entries(entries.to_vec());
1390 for window in sorted.windows(2) {
1391 let next_name = unescape_key(&window[1].name);
1392 if key < next_name.as_str() {
1393 return window[0].clone();
1394 }
1395 }
1396 sorted
1397 .last()
1398 .cloned()
1399 .expect("internal nodes must have children")
1400}
1401
1402fn entry_cid(entry: &TreeEntry) -> Cid {
1403 Cid {
1404 hash: entry.hash,
1405 key: entry.key,
1406 }
1407}
1408
1409fn tree_entry_to_dir_entry(entry: TreeEntry) -> DirEntry {
1410 let mut out = DirEntry::from_cid(&entry.name, &entry_cid(&entry))
1411 .with_size(entry.size)
1412 .with_link_type(entry.link_type);
1413 if let Some(meta) = entry.meta {
1414 out = out.with_meta(meta);
1415 }
1416 out
1417}
1418
1419fn count_link_entries(entries: &[TreeEntry]) -> u64 {
1420 entries
1421 .iter()
1422 .filter(|entry| entry.link_type == LinkType::File)
1423 .count() as u64
1424}
1425
1426fn stored_link_subtree_count(entry: &TreeEntry) -> Option<u64> {
1427 if entry.link_type != LinkType::Dir || entry.size == 0 {
1428 return None;
1429 }
1430 Some(entry.size)
1431}
1432
1433async fn count_link_entries_or_subtrees<S: Store>(
1434 btree: &BTree<S>,
1435 entries: &[TreeEntry],
1436) -> Result<u64, BTreeError> {
1437 if is_leaf_node(entries) {
1438 return Ok(count_link_entries(entries));
1439 }
1440
1441 let mut count = 0;
1442 for entry in entries {
1443 count += match stored_link_subtree_count(entry) {
1444 Some(child_count) => child_count,
1445 None => btree.count_links_recursive(entry_cid(entry)).await?,
1446 };
1447 }
1448 Ok(count)
1449}