Skip to main content

raw_btree/
storage.rs

1use crate::{
2	balancing::rebalance,
3	node::{Address, Offset},
4	utils::Array,
5	Node, M,
6};
7use core::fmt;
8use std::{cmp::Ordering, ptr::NonNull};
9
10/// BTree node storage.
11///
12/// # Safety
13///
14/// An *active* identifier is a node identifier (`Self::Node`) that has been
15/// created using `allocate_node` (or `insert_node`) but not yet released using
16/// `release_node` or a `Dropper` (created with `start_dropping`).
17///
18/// - Default method implementations must not be overridden by the implementor.
19/// - `allocate_node` must not return an *active* identifier.
20///   Once returned and until released using `release_node`, this identifier
21///   must always map to the same node through `get` and `get_mut`.
22///   We say that the identifier and node are "bound" together by the storage.
23///   The created node must live at least as long as its identifier is active
24///   and the storage is not dropped.
25/// - `release_node` may only drop the node bound to the given identifier.
26/// - `start_dropping` creates a dropper for this storage.
27/// - `get` must return the node bound to the given identifier.
28/// - `get_mut` must return the node bound to the given identifier.
29pub unsafe trait Storage<T>: Default {
30	/// Node.
31	type Node: Copy + PartialEq + core::fmt::Debug;
32
33	/// Nodes dropper.
34	type Dropper: Dropper<T, Self>;
35
36	/// Allocates the given node.
37	fn allocate_node(&mut self, node: Node<T, Self>) -> Self::Node;
38
39	/// # Safety
40	///
41	/// Input node must not have been deallocated.
42	unsafe fn release_node(&mut self, id: Self::Node) -> Node<T, Self>;
43
44	/// Creates a new dropper.
45	///
46	/// Returns `None` if no dropper is required to eventually drop all the
47	/// nodes.
48	fn start_dropping(&self) -> Option<Self::Dropper>;
49
50	/// # Safety
51	///
52	/// Input node must not have been deallocated.
53	unsafe fn get(&self, id: Self::Node) -> &Node<T, Self>;
54
55	/// # Safety
56	///
57	/// - Input node must not have been deallocated.
58	/// - Different `id` must map to non-aliased nodes.
59	/// - Must not be used to create more than one concurrent mutable reference
60	///   to the same node.
61	unsafe fn get_mut(&mut self, id: Self::Node) -> &mut Node<T, Self>;
62
63	/// Inserts the given node into the storage, setting the children parent.
64	///
65	/// # Safety
66	///
67	/// The input node's children must not have been deallocated.
68	unsafe fn insert_node(&mut self, node: Node<T, Self>) -> Self::Node {
69		let children: Array<Self::Node, M> = node.children().collect();
70		let id = self.allocate_node(node);
71		for child_id in children {
72			self.get_mut(child_id).set_parent(Some(id));
73		}
74
75		id
76	}
77
78	/// Normalizes the given address.
79	///
80	/// # Safety
81	///
82	/// Input address's node must not have been deallocated.
83	unsafe fn normalize(&self, mut addr: Address<Self::Node>) -> Option<Address<Self::Node>> {
84		loop {
85			let node = self.get(addr.node);
86			if addr.offset >= node.item_count() {
87				match node.parent() {
88					Some(parent_id) => {
89						addr.offset = self.get(parent_id).child_index(addr.node).unwrap().into();
90						addr.node = parent_id;
91					}
92					None => break None,
93				}
94			} else {
95				break Some(addr);
96			}
97		}
98	}
99
100	/// Converts this arbitrary address into a leaf address.
101	///
102	/// # Safety
103	///
104	/// Input address's node must not have been deallocated.
105	#[inline]
106	unsafe fn leaf_address(&self, mut addr: Address<Self::Node>) -> Address<Self::Node> {
107		loop {
108			let node = self.get(addr.node);
109			match node.child_id_opt(addr.offset.unwrap()) {
110				// TODO unwrap may fail here!
111				Some(child_id) => {
112					addr.node = child_id;
113					addr.offset = self.get(child_id).item_count().into()
114				}
115				None => break,
116			}
117		}
118
119		addr
120	}
121
122	/// Get the address of the item located before this address.
123	///
124	/// # Safety
125	///
126	/// Input address's node must not have been deallocated.
127	#[inline]
128	unsafe fn previous_item_address(
129		&self,
130		mut addr: Address<Self::Node>,
131	) -> Option<Address<Self::Node>> {
132		loop {
133			let node = self.get(addr.node);
134
135			match node.child_id_opt(addr.offset.unwrap()) {
136				// TODO unwrap may fail here.
137				Some(child_id) => {
138					addr.offset = self.get(child_id).item_count().into();
139					addr.node = child_id;
140				}
141				None => loop {
142					if addr.offset > 0 {
143						addr.offset.decr();
144						return Some(addr);
145					}
146
147					match self.get(addr.node).parent() {
148						Some(parent_id) => {
149							addr.offset =
150								self.get(parent_id).child_index(addr.node).unwrap().into();
151							addr.node = parent_id;
152						}
153						None => return None,
154					}
155				},
156			}
157		}
158	}
159
160	/// Returns the front address directly preceding the given address.
161	///
162	/// # Safety
163	///
164	/// Input address's node must not have been deallocated.
165	#[inline]
166	unsafe fn previous_front_address(
167		&self,
168		mut addr: Address<Self::Node>,
169	) -> Option<Address<Self::Node>> {
170		loop {
171			let node = self.get(addr.node);
172			match addr.offset.value() {
173				Some(offset) => {
174					let index = if offset < node.item_count() {
175						offset
176					} else {
177						node.item_count()
178					};
179
180					match node.child_id_opt(index) {
181						Some(child_id) => {
182							addr.offset = (self.get(child_id).item_count()).into();
183							addr.node = child_id;
184						}
185						None => {
186							addr.offset.decr();
187							break;
188						}
189					}
190				}
191				None => match node.parent() {
192					Some(parent_id) => {
193						addr.offset = self.get(parent_id).child_index(addr.node).unwrap().into();
194						addr.offset.decr();
195						addr.node = parent_id;
196						break;
197					}
198					None => return None,
199				},
200			}
201		}
202
203		Some(addr)
204	}
205
206	/// Get the address of the item located after this address if any.
207	///
208	/// # Safety
209	///
210	/// Input address's node must not have been deallocated.
211	#[inline]
212	unsafe fn next_item_address(
213		&self,
214		mut addr: Address<Self::Node>,
215	) -> Option<Address<Self::Node>> {
216		let item_count = self.get(addr.node).item_count();
217		match addr.offset.partial_cmp(&item_count) {
218			Some(std::cmp::Ordering::Less) => {
219				addr.offset.incr();
220			}
221			Some(std::cmp::Ordering::Greater) => {
222				return None;
223			}
224			_ => (),
225		}
226
227		// let original_addr_shifted = addr;
228
229		loop {
230			let node = self.get(addr.node);
231
232			match node.child_id_opt(addr.offset.unwrap()) {
233				// unwrap may fail here.
234				Some(child_id) => {
235					addr.offset = 0.into();
236					addr.node = child_id;
237				}
238				None => {
239					loop {
240						let node = self.get(addr.node);
241
242						if addr.offset < node.item_count() {
243							return Some(addr);
244						}
245
246						match node.parent() {
247							Some(parent_id) => {
248								addr.offset =
249									self.get(parent_id).child_index(addr.node).unwrap().into();
250								addr.node = parent_id;
251							}
252							None => {
253								// return Some(original_addr_shifted)
254								return None;
255							}
256						}
257					}
258				}
259			}
260		}
261	}
262
263	//// Returns the back address directly following the given address.
264	///
265	/// # Safety
266	///
267	/// Input address's node must not have been deallocated.
268	#[inline]
269	unsafe fn next_back_address(
270		&self,
271		mut addr: Address<Self::Node>,
272	) -> Option<Address<Self::Node>> {
273		loop {
274			let node = self.get(addr.node);
275			let index = match addr.offset.value() {
276				Some(offset) => offset + 1,
277				None => 0,
278			};
279
280			if index <= node.item_count() {
281				match node.child_id_opt(index) {
282					Some(child_id) => {
283						addr.offset = Offset::before();
284						addr.node = child_id;
285					}
286					None => {
287						addr.offset = index.into();
288						break;
289					}
290				}
291			} else {
292				match node.parent() {
293					Some(parent_id) => {
294						addr.offset = self.get(parent_id).child_index(addr.node).unwrap().into();
295						addr.node = parent_id;
296						break;
297					}
298					None => return None,
299				}
300			}
301		}
302
303		Some(addr)
304	}
305
306	/// Returns the item address or back address directly following the given
307	/// address.
308	///
309	/// # Safety
310	///
311	/// Input address's node must not have been deallocated.
312	#[inline]
313	unsafe fn next_item_or_back_address(
314		&self,
315		mut addr: Address<Self::Node>,
316	) -> Option<Address<Self::Node>> {
317		let item_count = self.get(addr.node).item_count();
318		match addr.offset.partial_cmp(&item_count) {
319			Some(std::cmp::Ordering::Less) => {
320				addr.offset.incr();
321			}
322			Some(std::cmp::Ordering::Greater) => {
323				return None;
324			}
325			_ => (),
326		}
327
328		let original_addr_shifted = addr;
329
330		loop {
331			let node = self.get(addr.node);
332
333			match node.child_id_opt(addr.offset.unwrap()) {
334				// TODO unwrap may fail here.
335				Some(child_id) => {
336					addr.offset = 0.into();
337					addr.node = child_id;
338				}
339				None => loop {
340					let node = self.get(addr.node);
341
342					if addr.offset < node.item_count() {
343						return Some(addr);
344					}
345
346					match node.parent() {
347						Some(parent_id) => {
348							addr.offset =
349								self.get(parent_id).child_index(addr.node).unwrap().into();
350							addr.node = parent_id;
351						}
352						None => return Some(original_addr_shifted),
353					}
354				},
355			}
356		}
357	}
358
359	/// # Safety
360	///
361	/// Input node must not have been deallocated.
362	unsafe fn address_in<Q: ?Sized>(
363		&self,
364		mut id: Self::Node,
365		cmp: impl Fn(&T, &Q) -> Ordering,
366		key: &Q,
367	) -> Result<Address<Self::Node>, Address<Self::Node>> {
368		loop {
369			match self.get(id).offset_of(&cmp, key) {
370				Ok(offset) => return Ok(Address { node: id, offset }),
371				Err((offset, None)) => return Err(Address::new(id, offset.into())),
372				Err((_, Some(child_id))) => {
373					id = child_id;
374				}
375			}
376		}
377	}
378
379	/// Inserts the item at the given address.
380	///
381	/// # Safety
382	///
383	/// Input nodes must not have been deallocated.
384	unsafe fn insert_at(
385		&mut self,
386		root: Option<Self::Node>,
387		addr: Option<Address<Self::Node>>,
388		item: T,
389	) -> (Option<Self::Node>, Option<Address<Self::Node>>) {
390		self.insert_exactly_at(root, addr.map(|addr| self.leaf_address(addr)), item, None)
391	}
392
393	/// Inserts the given item exactly at the provided **leaf** address.
394	///
395	/// # Safety
396	///
397	/// Input nodes must not have been deallocated.
398	unsafe fn insert_exactly_at(
399		&mut self,
400		root: Option<Self::Node>,
401		addr: Option<Address<Self::Node>>,
402		item: T,
403		opt_right_id: Option<Self::Node>,
404	) -> (Option<Self::Node>, Option<Address<Self::Node>>) {
405		match addr {
406			Some(addr) => {
407				self.get_mut(addr.node)
408					.insert(addr.offset, item, opt_right_id);
409				rebalance(self, root, addr.node, addr)
410			}
411			None => {
412				let new_root = Node::leaf(None, item);
413				let id = self.insert_node(new_root);
414				let addr = Address {
415					node: id,
416					offset: 0.into(),
417				};
418				(Some(id), Some(addr))
419			}
420		}
421	}
422
423	/// Replaces the item located at the given address.
424	///
425	/// # Safety
426	///
427	/// Input address's node must not have been deallocated.
428	unsafe fn replace_at(&mut self, addr: Address<Self::Node>, item: T) -> T {
429		std::mem::replace(self.get_mut(addr.node).item_mut(addr.offset).unwrap(), item)
430	}
431
432	/// # Safety
433	///
434	/// Input nodes must not have been deallocated.
435	#[inline]
436	unsafe fn remove_at(
437		&mut self,
438		root: Option<Self::Node>,
439		addr: Address<Self::Node>,
440	) -> Option<RemovedItem<T, Self>> {
441		match self.get_mut(addr.node).leaf_remove(addr.offset) {
442			Some(Ok(item)) => {
443				// removed from a leaf.
444				let (new_root, new_addr) = rebalance(self, root, addr.node, addr);
445				Some(RemovedItem {
446					new_root,
447					item,
448					new_addr,
449				})
450			}
451			Some(Err(left_child_id)) => {
452				// removed from an internal node.
453				let new_addr = self.next_item_or_back_address(addr).unwrap();
454				let (separator, leaf_id) = self.remove_rightmost_leaf_of(left_child_id);
455				let item = self.get_mut(addr.node).replace(addr.offset, separator);
456				let (new_root, new_addr) = rebalance(self, root, leaf_id, new_addr);
457				Some(RemovedItem {
458					new_root,
459					item,
460					new_addr,
461				})
462			}
463			None => None,
464		}
465	}
466
467	/// Remove the rightmost leaf node under the given node.
468	///
469	/// # Safety
470	///
471	/// Input node must not have been deallocated.
472	#[inline]
473	unsafe fn remove_rightmost_leaf_of(&mut self, mut id: Self::Node) -> (T, Self::Node) {
474		loop {
475			match self.get_mut(id).remove_rightmost_leaf() {
476				Ok(result) => return (result, id),
477				Err(child_id) => {
478					id = child_id;
479				}
480			}
481		}
482	}
483}
484
485pub struct RemovedItem<T, S: Storage<T>> {
486	pub new_root: Option<S::Node>,
487	pub item: T,
488	pub new_addr: Option<Address<S::Node>>,
489}
490
491/// Storage dropper.
492///
493/// Used to drop all the nodes of a node storage.
494///
495/// # Safety
496///
497/// `drop_node` may only drop the node bound to the given identifier.
498pub unsafe trait Dropper<T, S: Storage<T>>: Sized {
499	/// Drops the given node.
500	///
501	/// # Safety
502	///
503	/// - The node must not have been deallocated.
504	/// - No reference to the node or the node's content must exist.
505	/// - The node cannot be dereferenced anymore.
506	unsafe fn drop_node(&mut self, id: S::Node);
507}
508
509#[derive(Default)]
510pub struct BoxStorage;
511
512pub struct BoxPtr<T>(NonNull<Node<T, BoxStorage>>); // TODO use `core::ptr::Unique` when it is stable.
513
514unsafe impl<T: Send> Send for BoxPtr<T> {}
515unsafe impl<T: Sync> Sync for BoxPtr<T> {}
516
517unsafe impl<T> Storage<T> for BoxStorage {
518	type Node = BoxPtr<T>;
519
520	type Dropper = BoxDrop;
521
522	fn allocate_node(&mut self, node: Node<T, Self>) -> Self::Node {
523		let b = Box::new(node);
524		BoxPtr(NonNull::new(Box::into_raw(b)).unwrap())
525	}
526
527	unsafe fn release_node(&mut self, id: Self::Node) -> Node<T, Self> {
528		let b = Box::from_raw(id.0.as_ptr());
529		*b
530	}
531
532	fn start_dropping(&self) -> Option<Self::Dropper> {
533		Some(BoxDrop)
534	}
535
536	unsafe fn get(&self, id: Self::Node) -> &Node<T, Self> {
537		&*id.0.as_ptr()
538	}
539
540	unsafe fn get_mut(&mut self, id: Self::Node) -> &mut Node<T, Self> {
541		&mut *id.0.as_ptr()
542	}
543}
544
545impl<T> fmt::Debug for BoxPtr<T> {
546	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
547		self.0.fmt(f)
548	}
549}
550
551impl<T> Clone for BoxPtr<T> {
552	fn clone(&self) -> Self {
553		*self
554	}
555}
556
557impl<T> Copy for BoxPtr<T> {}
558
559impl<T> PartialEq for BoxPtr<T> {
560	fn eq(&self, other: &Self) -> bool {
561		self.0 == other.0
562	}
563}
564
565impl<T> Eq for BoxPtr<T> {}
566
567impl<T> From<BoxPtr<T>> for usize {
568	fn from(value: BoxPtr<T>) -> Self {
569		value.0.as_ptr() as usize
570	}
571}
572
573pub struct BoxDrop;
574
575unsafe impl<T> Dropper<T, BoxStorage> for BoxDrop {
576	unsafe fn drop_node(&mut self, id: BoxPtr<T>) {
577		let _ = Box::from_raw(id.0.as_ptr());
578	}
579}