1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use std::collections::VecDeque;
#[derive(thiserror::Error, Debug)]
#[allow(missing_docs)]
pub enum Error {
#[error("Pack offsets must only increment. The previous pack offset was {last_pack_offset}, the current one is {pack_offset}")]
InvariantIncreasingPackOffset {
last_pack_offset: u64,
pack_offset: u64,
},
#[error("Is there ever a need to create empty indices? If so, please post a PR.")]
InvariantNonEmpty,
#[error("The delta at pack offset {delta_pack_offset} could not find its base at {base_pack_offset} - it should have been seen already")]
InvariantBasesBeforeDeltasNeedThem {
delta_pack_offset: u64,
base_pack_offset: u64,
},
}
mod iter;
pub use iter::{Chunk, Node};
pub mod traverse;
pub mod from_offsets;
pub struct Item<T> {
pub offset: u64,
pub next_offset: u64,
pub data: T,
children: Vec<usize>,
}
pub struct Tree<T> {
items: VecDeque<Item<T>>,
roots: usize,
last_index: usize,
}
impl<T> Tree<T> {
pub fn with_capacity(num_objects: usize) -> Result<Self, Error> {
if num_objects == 0 {
return Err(Error::InvariantNonEmpty);
}
Ok(Tree {
items: VecDeque::with_capacity(num_objects),
roots: 0,
last_index: 0,
})
}
fn assert_is_incrementing(&mut self, offset: u64) -> Result<(), Error> {
if self.items.is_empty() {
return Ok(());
}
let last_offset = self.items[self.last_index].offset;
if offset <= last_offset {
return Err(Error::InvariantIncreasingPackOffset {
last_pack_offset: last_offset,
pack_offset: offset,
});
}
self.items[self.last_index].next_offset = offset;
Ok(())
}
fn set_pack_entries_end(&mut self, pack_entries_end: u64) {
if !self.items.is_empty() {
self.items[self.last_index].next_offset = pack_entries_end;
}
}
pub fn add_root(&mut self, offset: u64, data: T) -> Result<(), Error> {
self.assert_is_incrementing(offset)?;
self.last_index = 0;
self.items.push_front(Item {
offset,
next_offset: 0,
data,
children: Vec::new(),
});
self.roots += 1;
Ok(())
}
pub fn add_child(&mut self, base_offset: u64, offset: u64, data: T) -> Result<(), Error> {
self.assert_is_incrementing(offset)?;
let (roots, children) = self.items.as_mut_slices();
assert_eq!(
roots.len(),
self.roots,
"item deque has been resized, maybe we added more nodes than we declared in the constructor?"
);
if let Ok(i) = children.binary_search_by_key(&base_offset, |i| i.offset) {
children[i].children.push(children.len());
} else if let Ok(i) = roots.binary_search_by(|i| base_offset.cmp(&i.offset)) {
roots[i].children.push(children.len());
} else {
return Err(Error::InvariantBasesBeforeDeltasNeedThem {
delta_pack_offset: offset,
base_pack_offset: base_offset,
});
}
self.last_index = self.items.len();
self.items.push_back(Item {
offset,
next_offset: 0,
data,
children: Vec::new(),
});
Ok(())
}
pub fn into_items(self) -> VecDeque<Item<T>> {
self.items
}
}