From 10e762e730aeeed8a659cddc432eeb21d63ce1c1 Mon Sep 17 00:00:00 2001 From: Janis Date: Fri, 8 Aug 2025 00:32:28 +0200 Subject: [PATCH] invested actual thought into this --- src/tree.rs | 109 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 8eed009..49e24c9 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,5 +1,23 @@ +//! A Prefix-Tree (Trie) implementation in Rust. +//! This Trie is structured with key-value pairs at the same level. +// tree: +// root: { kvs: [('f', v0), ('g', v1), ('i', _)], edges: [child0, None, child1] } +// child0: { kvs: [('a', v2), ('b', v3)], edges: [] } +// child1: { kvs: [('a', v4)], edges: [] } +// tree.find() -> () +// tree.find('f') -> v0 +// tree.find('g') -> v1 +// tree.find('fa') -> v2 +// tree.find('fb') -> v3 +// tree.find('ia') -> v4 +// tree.find('i') -> None + use alloc::boxed::Box; -use core::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; +use core::{ + marker::PhantomData, + mem::{ManuallyDrop, MaybeUninit}, + ptr::NonNull, +}; mod marker { use core::marker::PhantomData; @@ -38,9 +56,41 @@ const CAPACITY: usize = 16; struct LeafNode { parent: Option>>, parent_idx: MaybeUninit, + value: ManuallyDrop, + leaf: bool, +} + +struct InternalNode { + data: LeafNode, + next: Option>>, len: u16, keys: [MaybeUninit; CAPACITY], - values: [MaybeUninit; CAPACITY], + edges: [MaybeUninit>; CAPACITY], +} + +type BoxedNode = NonNull>; + +struct NodeRef { + height: usize, + node: NonNull>, + _marker: PhantomData<(BorrowType, Type)>, +} + +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 LeafNode { @@ -53,41 +103,31 @@ impl LeafNode { } fn new() -> Box { + let mut this = Box::new_uninit(); 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 fn init(this: *mut Self) { 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 - + LeafNode::init(&raw mut (*this).data); + (&raw mut (*this).next).write(None); + (&raw mut (*this).edges).write([None; CAPACITY + 1]); + } + } + fn new() -> Box { + let mut this = Box::::new_uninit(); + unsafe { + Self::init(this.as_mut_ptr()); 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(); @@ -101,8 +141,8 @@ impl NodeRef { impl NodeRef { fn new_internal(child: Root) -> Self { - let mut node = unsafe { InternalNode::new() }; - node.edges[0].write(child.node); + let mut node = InternalNode::new(); + node.edges[0] = Some(child.node); // SAFETY: `height` isn't zero unsafe { NodeRef::from_new_internal(node, child.height + 1) } @@ -123,6 +163,8 @@ impl NodeRef { } } +// here follows std::BTree stuff + 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 @@ -285,23 +327,6 @@ impl<'a, K, V> NodeRef, marker::Internal> { } } -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)) };