From 7939d6df4774fd600b28a5ee2cdff6a370f5824d Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 7 Aug 2025 23:51:40 +0200 Subject: [PATCH] copy from std::tree --- src/lib.rs | 8 +- src/tree.rs | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 src/tree.rs diff --git a/src/lib.rs b/src/lib.rs index d2777ad..e8dd57f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(feature = "nightly", feature(strict_provenance_atomic_ptr))] +#![cfg_attr( + feature = "nightly", + feature(strict_provenance_atomic_ptr, box_vec_non_null) +)] #![cfg_attr(feature = "transposed-option", feature(try_trait_v2))] #[cfg(any(test, feature = "std", feature = "alloc"))] @@ -23,5 +26,8 @@ pub mod smallbox; pub mod sync; pub mod util; +#[cfg(feature = "alloc")] +pub mod tree; + pub use cachepadded::CachePadded; pub use mem::can_transmute; diff --git a/src/tree.rs b/src/tree.rs new file mode 100644 index 0000000..8eed009 --- /dev/null +++ b/src/tree.rs @@ -0,0 +1,400 @@ +use alloc::boxed::Box; +use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; + +mod marker { + use core::marker::PhantomData; + + pub struct LeafOrInternal; + pub struct Leaf; + pub struct Internal; + + pub struct Edge; + pub struct KV; + + pub struct Owned; + pub struct Mut<'a>(PhantomData<&'a mut ()>); + pub struct ValMut<'a>(PhantomData<&'a mut ()>); + pub struct Immutable<'a>(PhantomData<&'a ()>); + pub struct Dying; + pub struct DormantMut; + + pub trait BorrowType { + const TRAVERSAL_PERMIT: bool = true; + } + + impl BorrowType for Owned { + const TRAVERSAL_PERMIT: bool = false; + } + + impl<'a> BorrowType for Mut<'a> {} + impl<'a> BorrowType for ValMut<'a> {} + impl<'a> BorrowType for Immutable<'a> {} + impl BorrowType for Dying {} + impl BorrowType for DormantMut {} +} + +const CAPACITY: usize = 16; + +struct LeafNode { + parent: Option>>, + parent_idx: MaybeUninit, + len: u16, + keys: [MaybeUninit; CAPACITY], + values: [MaybeUninit; CAPACITY], +} + +impl LeafNode { + unsafe fn init(this: *mut Self) { + unsafe { + (&raw mut (*this).parent).write(None); + (&raw mut (*this).len).write(0); + // parent_idx and keys/values may be left uninitialized + } + } + + fn new() -> Box { + unsafe { + let mut this = Box::new_uninit(); + Self::init(this.as_mut_ptr()); + this.assume_init() + } + } +} + +struct InternalNode { + data: LeafNode, + next: Option>>, + edges: [MaybeUninit>; CAPACITY * 2 - 1], +} + +impl InternalNode { + unsafe fn new() -> Box { + unsafe { + let mut this = Box::::new_uninit(); + LeafNode::init(&raw mut (*this.as_mut_ptr()).data); + (&raw mut (*this.as_mut_ptr()).next).write(None); + // edges may be left uninitialized + + this.assume_init() + } + } +} + +type BoxedNode = NonNull>; + +struct NodeRef { + height: usize, + node: NonNull>, + _marker: PhantomData<(BorrowType, Type)>, +} + +impl NodeRef { + fn new_leaf() -> Self { + let node = LeafNode::new(); + NodeRef { + height: 0, + node: Box::into_non_null(node), + _marker: PhantomData, + } + } +} + +impl NodeRef { + fn new_internal(child: Root) -> Self { + let mut node = unsafe { InternalNode::new() }; + node.edges[0].write(child.node); + + // SAFETY: `height` isn't zero + unsafe { NodeRef::from_new_internal(node, child.height + 1) } + } + + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal(internal: Box>, height: usize) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { + height, + node, + _marker: PhantomData, + }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } +} + +impl NodeRef { + /// Mutably borrows the owned root node. Unlike `reborrow_mut`, this is safe + /// because the return value cannot be used to destroy the root, and there + /// cannot be other references to the tree. + pub(super) fn borrow_mut(&mut self) -> NodeRef, Type> { + NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + } + } + + /// Irreversibly transitions to a reference that permits traversal and offers + /// destructive methods and little else. + pub(super) fn into_dying(self) -> NodeRef { + NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + } + } +} + +impl NodeRef { + fn len(&self) -> usize { + unsafe { (*self.node.as_ptr()).len as usize } + } + + fn height(&self) -> usize { + self.height + } + + fn reborrow(&self) -> NodeRef, Type> { + NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + } + } + + fn as_leaf_ptr(this: &Self) -> *mut LeafNode { + this.node.as_ptr() + } +} + +impl NodeRef { + /// Exposes the data of an internal node. + /// + /// Returns a raw ptr to avoid invalidating other references to this node. + fn as_internal_ptr(this: &Self) -> *mut InternalNode { + // SAFETY: the static node type is `Internal`. + this.node.as_ptr() as *mut InternalNode + } +} + +impl<'a, K, V> NodeRef, marker::Internal> { + /// Borrows exclusive access to the data of an internal node. + fn as_internal_mut(&mut self) -> &mut InternalNode { + let ptr = Self::as_internal_ptr(self); + unsafe { &mut *ptr } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, marker::LeafOrInternal> { + fn set_parent_link(&mut self, parent: NonNull>, parent_idx: usize) { + unsafe { + let leaf_ptr = Self::as_leaf_ptr(self); + (*leaf_ptr).parent = Some(parent); + (*leaf_ptr).parent_idx.write(parent_idx as u16); + } + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, Type> { + unsafe fn key_area_mut(&mut self, index: I) -> &mut Output + where + I: core::slice::SliceIndex<[MaybeUninit], Output = Output>, + Output: ?Sized, + { + unsafe { + self.as_leaf_mut() + .keys + .as_mut_slice() + .get_unchecked_mut(index) + } + } + unsafe fn val_area_mut(&mut self, index: I) -> &mut Output + where + I: core::slice::SliceIndex<[MaybeUninit], Output = Output>, + Output: ?Sized, + { + unsafe { + self.as_leaf_mut() + .values + .as_mut_slice() + .get_unchecked_mut(index) + } + } +} + +impl<'a, K: 'a, V: 'a> NodeRef, marker::Internal> { + unsafe fn edge_area_mut(&mut self, index: I) -> &mut Output + where + I: core::slice::SliceIndex<[MaybeUninit>], Output = Output>, + Output: ?Sized, + { + unsafe { + self.as_internal_mut() + .edges + .as_mut_slice() + .get_unchecked_mut(index) + } + } +} + +impl<'a, K: 'a, V: 'a, Type> NodeRef, Type> { + /// Borrows exclusive access to the length of the node. + pub(super) fn len_mut(&mut self) -> &mut u16 { + &mut self.as_leaf_mut().len + } +} + +impl<'a, K, V, Type> NodeRef, Type> { + unsafe fn reborrow_mut(&mut self) -> NodeRef, Type> { + NodeRef { + height: self.height, + node: self.node, + _marker: PhantomData, + } + } + + fn as_leaf_mut(&mut self) -> &mut LeafNode { + unsafe { &mut *Self::as_leaf_ptr(self) } + } + + fn into_leaf_mut(mut self) -> &'a mut LeafNode { + // SAFETY: `self` is a mutable reference to a `NodeRef` with a mutable borrow type. + unsafe { &mut *Self::as_leaf_ptr(&mut self) } + } +} + +impl<'a, K, V> NodeRef, marker::Internal> { + unsafe fn correct_childrens_parent_links(&mut self, range: R) + where + R: Iterator, + { + for i in range { + assert!(i < self.len()); + unsafe { + Handle::new_edge(self.reborrow_mut(), i).correct_parent_link(); + } + } + } + + fn correct_all_childrens_parent_links(&mut self) { + let len = self.len(); + unsafe { + self.correct_childrens_parent_links(0..=len); + } + } +} + +struct Handle { + node: Node, + idx: usize, + _marker: PhantomData, +} + +impl Handle, marker::Edge> { + unsafe fn new_edge(node: NodeRef, idx: usize) -> Self { + assert!(idx < node.len()); + Handle { + node, + idx, + _marker: PhantomData, + } + } +} + +impl<'a, K, V> Handle, marker::Internal>, marker::Edge> { + fn correct_parent_link(self) { + let ptr = unsafe { NonNull::new_unchecked(NodeRef::as_internal_ptr(&self.node)) }; + let idx = self.idx; + let mut child = self.descend(); + child.set_parent_link(ptr, idx); + } +} + +impl<'a, K, V, NodeType, HandleType> Handle, NodeType>, HandleType> { + unsafe fn reborrow_mut( + &mut self, + ) -> Handle, NodeType>, HandleType> { + Handle { + node: unsafe { self.node.reborrow_mut() }, + idx: self.idx, + _marker: PhantomData, + } + } +} + +impl Handle, marker::Edge> { + fn descend(self) -> NodeRef { + let parent_ptr = NodeRef::as_internal_ptr(&self.node); + let node = unsafe { + (*parent_ptr) + .edges + .get_unchecked(self.idx) + .assume_init_read() + }; + NodeRef { + height: self.node.height - 1, + node, + _marker: PhantomData, + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, marker::Internal>, marker::Edge> { + fn insert_fit(&mut self, key: K, val: V, edge: Root) { + debug_assert!(self.node.len() < CAPACITY); + debug_assert!(edge.height == self.node.height - 1); + let new_len = self.node.len() + 1; + + unsafe { + slice_insert(self.node.key_area_mut(..new_len), self.idx, key); + slice_insert(self.node.val_area_mut(..new_len), self.idx, val); + slice_insert( + self.node.edge_area_mut(..new_len + 1), + self.idx + 1, + edge.node, + ); + *self.node.len_mut() = new_len as u16; + + self.node + .correct_childrens_parent_links(self.idx + 1..new_len + 1); + } + } + + fn insert(mut self, key: K, val: V, edge: Root) { + if self.node.len() < CAPACITY { + self.insert_fit(key, val, edge); + } else { + } + } +} + +impl<'a, K: 'a, V: 'a> Handle, marker::Leaf>, marker::Edge> {} + +type Root = NodeRef; + +struct Tree { + root: Option>, + _marker: PhantomData>, +} + +impl Tree { + pub fn new() -> Self { + Self { + root: None, + _marker: PhantomData, + } + } +} + +unsafe fn slice_insert(slice: &mut [MaybeUninit], idx: usize, value: T) { + unsafe { + let len = slice.len(); + debug_assert!(len > idx); + let slice_ptr = slice.as_mut_ptr(); + if len > idx + 1 { + core::ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx - 1); + } + (*slice_ptr.add(idx)).write(value); + } +}