#![allow(clippy::missing_safety_doc)]
use std::fmt::Debug;
use std::marker;
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::ptr::NonNull;
pub use metrics::*;
pub use root::DeleteResult;
pub use rle::{SplitAndJoinSpan, RleRun, ReverseSpan, Single};
mod unsafe_cursor;
mod root;
mod leaf;
mod internal;
mod mutations;
mod metrics;
mod safe_cursor;
pub mod testrange;
mod iter;
mod debug;
#[cfg(debug_assertions)]
pub const DEFAULT_IE: usize = 8; #[cfg(not(debug_assertions))]
pub const DEFAULT_IE: usize = 10;
#[cfg(debug_assertions)]
pub const DEFAULT_LE: usize = 4;
#[cfg(not(debug_assertions))]
pub const DEFAULT_LE: usize = 32;
pub trait ContentTraits: SplitAndJoinSpan + Copy + Debug + Default {}
impl<T: SplitAndJoinSpan + Copy + Debug + Default> ContentTraits for T {}
pub struct ContentTreeRaw<E: ContentTraits, I: TreeMetrics<E>, const INT_ENTRIES: usize = DEFAULT_IE, const LEAF_ENTRIES: usize = DEFAULT_LE> {
count: I::Value,
root: Node<E, I, INT_ENTRIES, LEAF_ENTRIES>,
_pin: marker::PhantomPinned,
}
pub trait Cursors {
type UnsafeCursor;
type Cursor;
type MutCursor;
}
impl<'a, E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> Cursors for &'a ContentTreeRaw<E, I, IE, LE> {
type UnsafeCursor = UnsafeCursor<E, I, IE, LE>;
type Cursor = Cursor<'a, E, I, IE, LE>;
type MutCursor = MutCursor<'a, E, I, IE, LE>;
}
impl<'a, E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> Cursors for &'a Pin<Box<ContentTreeRaw<E, I, IE, LE>>> {
type UnsafeCursor = UnsafeCursor<E, I, IE, LE>;
type Cursor = Cursor<'a, E, I, IE, LE>;
type MutCursor = MutCursor<'a, E, I, IE, LE>;
}
#[deprecated]
pub type ContentTreeWithIndex<E, I> = ContentTreeRaw<E, I, DEFAULT_IE, DEFAULT_LE>;
pub type ContentTree<E> = ContentTreeRaw<E, RawPositionMetricsU32, DEFAULT_IE, DEFAULT_LE>;
#[derive(Debug)]
pub(crate) struct NodeInternal<E: ContentTraits, I: TreeMetrics<E>, const INT_ENTRIES: usize, const LEAF_ENTRIES: usize> {
parent: ParentPtr<E, I, INT_ENTRIES, LEAF_ENTRIES>,
metrics: [I::Value; INT_ENTRIES],
children: [Option<Node<E, I, INT_ENTRIES, LEAF_ENTRIES>>; INT_ENTRIES],
_pin: PhantomPinned, }
#[derive(Debug)]
pub struct NodeLeaf<E: ContentTraits, I: TreeMetrics<E>, const INT_ENTRIES: usize = DEFAULT_IE, const LEAF_ENTRIES: usize = DEFAULT_LE> {
parent: ParentPtr<E, I, INT_ENTRIES, LEAF_ENTRIES>,
num_entries: u8, data: [E; LEAF_ENTRIES],
_pin: PhantomPinned,
next: Option<NonNull<Self>>,
}
#[derive(Debug)]
pub(crate) enum Node<E: ContentTraits, I: TreeMetrics<E>, const IE: usize = DEFAULT_IE, const LE: usize = DEFAULT_LE> {
Internal(Pin<Box<NodeInternal<E, I, IE, LE>>>),
Leaf(Pin<Box<NodeLeaf<E, I, IE, LE>>>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub(crate) enum NodePtr<E: ContentTraits, I: TreeMetrics<E>, const IE: usize = DEFAULT_IE, const LE: usize = DEFAULT_LE> {
Internal(NonNull<NodeInternal<E, I, IE, LE>>),
Leaf(NonNull<NodeLeaf<E, I, IE, LE>>),
}
#[derive(Copy, Clone, Debug, Eq)]
pub(crate) enum ParentPtr<E: ContentTraits, I: TreeMetrics<E>, const IE: usize = DEFAULT_IE, const LE: usize = DEFAULT_LE> {
Root(NonNull<ContentTreeRaw<E, I, IE, LE>>),
Internal(NonNull<NodeInternal<E, I, IE, LE>>)
}
#[derive(Clone, Debug)]
pub struct UnsafeCursor<E: ContentTraits, I: TreeMetrics<E>, const IE: usize = DEFAULT_IE, const LE: usize = DEFAULT_LE> {
node: NonNull<NodeLeaf<E, I, IE, LE>>,
idx: usize,
pub offset: usize, }
#[repr(transparent)]
#[derive(Clone, Debug)]
pub struct SafeCursor<R, E: ContentTraits, I: TreeMetrics<E>, const IE: usize = DEFAULT_IE, const LE: usize = DEFAULT_LE> {
pub inner: UnsafeCursor<E, I, IE, LE>,
marker: marker::PhantomData<R>
}
pub type Cursor<'a, E, I, const IE: usize = DEFAULT_IE, const LE: usize = DEFAULT_LE>
= SafeCursor<&'a ContentTreeRaw<E, I, IE, LE>, E, I, IE, LE>;
pub type MutCursor<'a, E, I, const IE: usize, const LE: usize> = SafeCursor<&'a mut ContentTreeRaw<E, I, IE, LE>, E, I, IE, LE>;
impl<E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> PartialEq for ParentPtr<E, I, IE, LE> {
fn eq(&self, other: &Self) -> bool {
use ParentPtr::*;
match (self, other) {
(Root(a), Root(b)) => a == b,
(Internal(a), Internal(b)) => a == b,
_ => false
}
}
}
unsafe fn ref_to_nonnull<T>(val: &T) -> NonNull<T> {
NonNull::new_unchecked(val as *const _ as *mut _)
}
pub fn null_notify<E, Node>(_e: E, _node: Node) {}
impl<E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> Node<E, I, IE, LE> {
fn set_parent(&mut self, parent: ParentPtr<E, I, IE, LE>) {
unsafe {
match self {
Node::Leaf(l) => l.as_mut().get_unchecked_mut().parent = parent,
Node::Internal(i) => i.as_mut().get_unchecked_mut().parent = parent,
}
}
}
pub fn is_leaf(&self) -> bool {
match self {
Node::Leaf(_) => true,
Node::Internal(_) => false,
}
}
fn unwrap_leaf_mut(&mut self) -> Pin<&mut NodeLeaf<E, I, IE, LE>> {
match self {
Node::Leaf(l) => l.as_mut(),
Node::Internal(_) => panic!("Expected leaf - found internal node"),
}
}
fn unwrap_internal_mut(&mut self) -> Pin<&mut NodeInternal<E, I, IE, LE>> {
match self {
Node::Internal(n) => n.as_mut(),
Node::Leaf(_) => panic!("Expected internal node"),
}
}
unsafe fn as_ptr(&self) -> NodePtr<E, I, IE, LE> {
match self {
Node::Internal(n) => {
NodePtr::Internal(ref_to_nonnull(n.as_ref().get_ref()))
},
Node::Leaf(n) => {
NodePtr::Leaf(ref_to_nonnull(n.as_ref().get_ref()))
},
}
}
fn ptr_eq(&self, ptr: NodePtr<E, I, IE, LE>) -> bool {
match (self, ptr) {
(Node::Internal(n), NodePtr::Internal(ptr)) => {
std::ptr::eq(n.as_ref().get_ref(), ptr.as_ptr())
},
(Node::Leaf(n), NodePtr::Leaf(ptr)) => {
std::ptr::eq(n.as_ref().get_ref(), ptr.as_ptr())
},
_ => panic!("Pointer type does not match")
}
}
}
impl<E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> NodePtr<E, I, IE, LE> {
fn unwrap_leaf(self) -> NonNull<NodeLeaf<E, I, IE, LE>> {
match self {
NodePtr::Leaf(l) => l,
NodePtr::Internal(_) => panic!("Expected leaf - found internal node"),
}
}
unsafe fn get_parent(&self) -> ParentPtr<E, I, IE, LE> {
match self {
NodePtr::Internal(n) => { n.as_ref().parent }
NodePtr::Leaf(n) => { n.as_ref().parent }
}
}
}
impl<E: ContentTraits, I: TreeMetrics<E>, const IE: usize, const LE: usize> ParentPtr<E, I, IE, LE> {
fn unwrap_internal(self) -> NonNull<NodeInternal<E, I, IE, LE>> {
match self {
ParentPtr::Root(_) => { panic!("Expected internal node"); }
ParentPtr::Internal(ptr) => { ptr }
}
}
fn is_root(&self) -> bool {
match self {
ParentPtr::Root(_) => { true }
ParentPtr::Internal(_) => { false }
}
}
}
#[cfg(test)]
mod test {
use std::mem::size_of;
use super::*;
use crate::testrange::TestRange;
#[test]
fn option_node_size_is_transparent() {
let node_size = size_of::<Node<TestRange, RawPositionMetricsU32, DEFAULT_IE, DEFAULT_LE>>();
let opt_node_size = size_of::<Option<Node<TestRange, RawPositionMetricsU32, DEFAULT_IE, DEFAULT_LE>>>();
assert_eq!(node_size, opt_node_size);
}
}