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
use std::cell::UnsafeCell;
#[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::{Chunks, Node};
pub mod traverse;
pub mod from_offsets;
pub struct Item<T> {
pub offset: u64,
is_root: bool,
pub data: T,
children: Vec<usize>,
}
pub struct Tree<T> {
items: UnsafeCell<Vec<Item<T>>>,
last_added_offset: u64,
one_past_last_seen_root: usize,
pack_entries_end: Option<u64>,
}
#[allow(unsafe_code)]
unsafe impl<T> Sync for Tree<T> {}
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: UnsafeCell::new(Vec::with_capacity(num_objects)),
last_added_offset: 0,
one_past_last_seen_root: 0,
pack_entries_end: None,
})
}
fn assert_is_incrementing(&mut self, offset: u64) -> Result<u64, Error> {
if offset > self.last_added_offset {
self.last_added_offset = offset;
Ok(offset)
} else {
Err(Error::InvariantIncreasingPackOffset {
last_pack_offset: self.last_added_offset,
pack_offset: offset,
})
}
}
pub fn add_root(&mut self, offset: u64, data: T) -> Result<(), Error> {
#[allow(unsafe_code)]
let items = unsafe { &mut *(self.items.get()) };
let offset = self.assert_is_incrementing(offset)?;
items.push(Item {
offset,
data,
is_root: true,
children: Default::default(),
});
self.one_past_last_seen_root = items.len();
Ok(())
}
pub fn add_child(&mut self, base_offset: u64, offset: u64, data: T) -> Result<(), Error> {
#[allow(unsafe_code)]
let items = unsafe { &mut *(self.items.get()) };
let offset = self.assert_is_incrementing(offset)?;
let base_index = items.binary_search_by_key(&base_offset, |e| e.offset).map_err(|_| {
Error::InvariantBasesBeforeDeltasNeedThem {
delta_pack_offset: offset,
base_pack_offset: base_offset,
}
})?;
let child_index = items.len();
items[base_index].children.push(child_index);
items.push(Item {
is_root: false,
offset,
data,
children: Default::default(),
});
Ok(())
}
pub fn into_items(self) -> Vec<Item<T>> {
self.items.into_inner()
}
}