content_tree/leaf.rs
1use std::mem::take;
2use std::ptr::NonNull;
3
4use rle::Searchable;
5
6use super::*;
7
8impl<E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> NodeLeaf<E, I, IE, LE> {
9 // Note this doesn't return a Pin<Box<Self>> like the others. At the point of creation, there's
10 // no reason for this object to be pinned. (Is that a bad idea? I'm not sure.)
11 pub(crate) unsafe fn new(next: Option<NonNull<Self>>) -> Self {
12 Self::new_with_parent(ParentPtr::Root(NonNull::dangling()), next)
13 }
14
15 pub(crate) fn new_with_parent(parent: ParentPtr<E, I, IE, LE>, next: Option<NonNull<Self>>) -> Self {
16 Self {
17 parent,
18 data: [E::default(); LE],
19 num_entries: 0,
20 _pin: PhantomPinned,
21 next,
22 }
23 }
24
25 // pub fn find2(&self, loc: CRDTLocation) -> (ClientSeq, Option<usize>) {
26 // let mut raw_pos: ClientSeq = 0;
27
28 // for i in 0..NUM_ENTRIES {
29 // let entry = self.data[i];
30 // if entry.is_invalid() { break; }
31
32 // if entry.loc.client == loc.client && entry.get_seq_range().contains(&loc.seq) {
33 // if entry.len > 0 {
34 // raw_pos += loc.seq - entry.loc.seq;
35 // }
36 // return (raw_pos, Some(i));
37 // } else {
38 // raw_pos += entry.get_text_len()
39 // }
40 // }
41 // (raw_pos, None)
42 // }
43
44 /// Find a given text offset within the node.
45 ///
46 /// Returns (index, offset within entry)
47 ///
48 /// TODO: Add a parameter for figuring out the offset at content length, and pass that in
49 /// from the ContentLength trait.
50 pub fn find_offset<F>(&self, mut offset: usize, stick_end: bool, entry_to_num: F) -> Option<(usize, usize)>
51 where F: Fn(E) -> usize {
52 for i in 0..self.len_entries() {
53 // if offset == 0 {
54 // return Some((i, 0));
55 // }
56
57 let entry: E = self.data[i];
58 // if !entry.is_valid() { break; }
59
60 // let text_len = entry.content_len();
61 let entry_len = entry_to_num(entry);
62 if offset < entry_len || (stick_end && entry_len == offset) {
63 // Found it.
64 return Some((i, offset));
65 } else {
66 offset -= entry_len
67 }
68 }
69
70 if offset == 0 { // Special case for the first inserted element - we may never enter the loop.
71 Some((self.len_entries(), 0))
72 } else { None }
73 }
74
75 pub fn next_leaf(&self) -> Option<NonNull<Self>> {
76 self.next
77 }
78
79 pub fn prev_leaf(&self) -> Option<NonNull<Self>> {
80 self.adjacent_leaf_by_traversal(false)
81 }
82
83 pub(crate) fn adjacent_leaf_by_traversal(&self, direction_forward: bool) -> Option<NonNull<Self>> {
84 // TODO: Remove direction_forward here.
85
86 // println!("** traverse called {:?} {}", self, traverse_next);
87 // idx is 0. Go up as far as we can until we get to an index that has room, or we hit the
88 // root.
89 let mut parent = self.parent;
90 let mut node_ptr = NodePtr::Leaf(unsafe { NonNull::new_unchecked(self as *const _ as *mut _) });
91
92 loop {
93 match parent {
94 ParentPtr::Root(_) => { return None; },
95 ParentPtr::Internal(n) => {
96 let node_ref = unsafe { n.as_ref() };
97 // Time to find ourself up this tree.
98 let idx = node_ref.find_child(node_ptr).unwrap();
99 // println!("found myself at {}", idx);
100
101 let next_idx: Option<usize> = if direction_forward {
102 let next_idx = idx + 1;
103 // This would be much cleaner if I put a len field in NodeInternal instead.
104 // TODO: Consider using node_ref.count_children() instead of this mess.
105 if (next_idx < IE) && node_ref.children[next_idx].is_some() {
106 Some(next_idx)
107 } else { None }
108 } else if idx > 0 {
109 Some(idx - 1)
110 } else { None };
111 // println!("index {:?}", next_idx);
112
113 if let Some(next_idx) = next_idx {
114 // Whew - now we can descend down from here.
115 // println!("traversing laterally to {}", next_idx);
116 node_ptr = unsafe { node_ref.children[next_idx].as_ref().unwrap().as_ptr() };
117 break;
118 } else {
119 // idx is 0. Keep climbing that ladder!
120 node_ptr = NodePtr::Internal(unsafe { NonNull::new_unchecked(node_ref as *const _ as *mut _) });
121 parent = node_ref.parent;
122 }
123 }
124 }
125 }
126
127 // Now back down. We don't need idx here because we just take the first / last item in each
128 // node going down the tree.
129 loop {
130 // println!("nodeptr {:?}", node_ptr);
131 match node_ptr {
132 NodePtr::Internal(n) => {
133 let node_ref = unsafe { n.as_ref() };
134 let next_idx = if direction_forward {
135 0
136 } else {
137 let num_children = node_ref.count_children();
138 assert!(num_children > 0);
139 num_children - 1
140 };
141 node_ptr = unsafe { node_ref.children[next_idx].as_ref().unwrap().as_ptr() };
142 },
143 NodePtr::Leaf(n) => {
144 // Finally.
145 return Some(n);
146 }
147 }
148 }
149 }
150
151 // pub(super) fn actually_count_entries(&self) -> usize {
152 // self.data.iter()
153 // .position(|e| e.loc.client == CLIENT_INVALID)
154 // .unwrap_or(NUM_ENTRIES)
155 // }
156 pub fn len_entries(&self) -> usize {
157 self.num_entries as usize
158 }
159
160 pub fn as_slice(&self) -> &[E] {
161 &self.data[0..self.num_entries as usize]
162 }
163
164 // Recursively (well, iteratively) ascend and update all the counts along
165 // the way up. TODO: Move this - This method shouldn't be in NodeLeaf.
166 pub fn update_parent_count(&mut self, amt: I::Update) {
167 if amt == I::Update::default() { return; }
168
169 let mut child = NodePtr::Leaf(unsafe { NonNull::new_unchecked(self) });
170 let mut parent = self.parent;
171
172 loop {
173 match parent {
174 ParentPtr::Root(mut r) => {
175 unsafe {
176 I::update_offset_by_marker(&mut r.as_mut().count, &amt);
177 // r.as_mut().count = r.as_ref().count.wrapping_add(amt as usize); }
178 }
179 break;
180 },
181 ParentPtr::Internal(mut n) => {
182 let idx = unsafe { n.as_mut() }.find_child(child).unwrap();
183 let c = &mut unsafe { n.as_mut() }.metrics[idx];
184 // :(
185 I::update_offset_by_marker(c, &amt);
186 // *c = c.wrapping_add(amt as u32);
187
188 // And recurse.
189 child = NodePtr::Internal(n);
190 parent = unsafe { n.as_mut() }.parent;
191 },
192 };
193 }
194 }
195
196 pub fn flush_metric_update(&mut self, marker: &mut I::Update) {
197 // println!("flush {:?}", marker);
198 let amt = take(marker);
199 self.update_parent_count(amt);
200 }
201
202 pub fn has_root_as_parent(&self) -> bool {
203 self.parent.is_root()
204 }
205
206 pub fn count_items(&self) -> I::Value {
207 if I::CAN_COUNT_ITEMS {
208 // Optimization using the index. TODO: check if this is actually faster.
209 match self.parent {
210 ParentPtr::Root(root) => {
211 unsafe { root.as_ref() }.count
212 }
213 ParentPtr::Internal(node) => {
214 let child = NodePtr::Leaf(unsafe { NonNull::new_unchecked(self as *const _ as *mut _) });
215 let idx = unsafe { node.as_ref() }.find_child(child).unwrap();
216 unsafe { node.as_ref() }.metrics[idx]
217 }
218 }
219 } else {
220 // Count items the boring way. Hopefully this will optimize tightly.
221 let mut val = I::Value::default();
222 for elem in self.data[..self.num_entries as usize].iter() {
223 I::increment_offset(&mut val, elem);
224 }
225 val
226 }
227 }
228
229 /// Remove a single item from the node
230 pub fn splice_out(&mut self, idx: usize) {
231 debug_assert!(idx < self.num_entries as usize);
232 self.data.copy_within(idx + 1..self.num_entries as usize, idx);
233 self.num_entries -= 1;
234 }
235
236 pub fn clear_all(&mut self) {
237 // self.data[0..self.num_entries as usize].fill(E::default());
238 self.num_entries = 0;
239 }
240
241 pub fn unsafe_cursor_at_start(&self) -> UnsafeCursor<E, I, IE, LE> {
242 UnsafeCursor::new(
243 unsafe { NonNull::new_unchecked(self as *const _ as *mut _) },
244 0,
245 0
246 )
247 }
248
249 // pub fn cursor_at_start<'a, 'b: 'a>(&'a self, tree: &'b ContentTreeRaw<E, I, IE, LE>) -> Cursor<E, I, IE, LE> {
250 // // This is safe because you can only reference a leaf while you immutably borrow a
251 // // content-tree. The lifetime of the returned cursor should match self.
252 // unsafe { Cursor::unchecked_from_raw(tree, self.unsafe_cursor_at_start()) }
253 // }
254}
255
256impl<E: ContentTraits + Searchable, I: TreeMetrics<E>, const IE: usize, const LE: usize> NodeLeaf<E, I, IE, LE> {
257 pub fn find(&self, loc: E::Item) -> Option<UnsafeCursor<E, I, IE, LE>> {
258 for i in 0..self.len_entries() {
259 let entry: E = self.data[i];
260
261 if let Some(offset) = entry.get_offset(loc) {
262 debug_assert!(offset < entry.len());
263 // let offset = if entry.is_insert() { entry_offset } else { 0 };
264
265 return Some(UnsafeCursor::new(
266 unsafe { NonNull::new_unchecked(self as *const _ as *mut _) },
267 i,
268 offset
269 ))
270 }
271 }
272 None
273 }
274}