use super::{LeafRef, Mutable, NodeRef, Prefix};
use super::{Node, NodeKind, SplitStrategy};
use crate::{Allocator, VerifiedAlloc};
use core::marker::PhantomData as Pd;
use core::mem::{self, MaybeUninit};
use core::ptr::{self, NonNull};
#[repr(C)]
pub struct LeafNode<T, const B: usize> {
prefix: Prefix<T, B>,
length: usize,
children: [MaybeUninit<T>; B],
next: Option<NonNull<Self>>,
}
impl<T, const B: usize> Drop for LeafNode<T, B> {
fn drop(&mut self) {
for child in &mut self.children[..self.length] {
unsafe {
mem::replace(child, MaybeUninit::uninit()).assume_init();
}
}
}
}
impl<T, const B: usize> LeafNode<T, B> {
fn new() -> Self {
Self {
prefix: Prefix::new(NodeKind::Leaf),
length: 0,
children: [(); B].map(|_| MaybeUninit::uninit()),
next: None,
}
}
pub fn clone_from(
&mut self,
other: &Self,
next_leaf: Option<NonNull<Self>>,
) where
T: Clone,
{
for (md, item) in self.children.iter_mut().zip(other.children()) {
md.write(item.clone());
}
self.length = other.length;
self.next = next_leaf;
}
pub fn split(
&mut self,
strategy: SplitStrategy,
alloc: &VerifiedAlloc<impl Allocator>,
) -> NodeRef<Self, Mutable> {
let (left, right) = strategy.sizes(B);
assert!(self.length == B);
let mut new = LeafRef::alloc(alloc);
unsafe {
ptr::copy_nonoverlapping(
(self.children.as_ptr() as *const T).wrapping_add(left),
new.children.as_mut_ptr() as *mut T,
right,
);
}
new.next = self.next;
self.next = Some(new.as_ptr());
self.length = left;
new.length = right;
new
}
pub fn merge(&mut self, other: &mut Self) {
let length = self.length;
assert!(length <= B / 2);
assert!(other.length <= B / 2);
unsafe {
ptr::copy_nonoverlapping(
other.children.as_ptr() as *const T,
(self.children.as_mut_ptr() as *mut T).wrapping_add(length),
other.length,
);
}
assert!(self.next == Some(NonNull::from(&mut *other)));
self.next = other.next;
other.next = None;
self.length += other.length;
other.length = 0;
}
pub fn simple_insert(&mut self, i: usize, item: T) {
let length = self.length;
self.children[i..length + 1].rotate_right(1);
self.children[i] = MaybeUninit::new(item);
self.length += 1;
}
pub fn simple_remove(&mut self, i: usize) -> T {
let length = self.length;
assert!(length > 0);
self.children[i..length].rotate_left(1);
self.length -= 1;
let item = mem::replace(
&mut self.children[length - 1],
MaybeUninit::uninit(),
);
unsafe { item.assume_init() }
}
pub fn children(&self) -> &[T] {
let ptr = &self.children[..self.length] as *const _ as *const [T];
unsafe { &*ptr }
}
pub fn children_mut(&mut self) -> &mut [T] {
let ptr = &mut self.children[..self.length] as *mut _ as *mut [T];
unsafe { &mut *ptr }
}
pub fn set_zero_length(&mut self) {
self.length = 0;
}
pub fn take_raw_child(&mut self, i: usize) -> MaybeUninit<T> {
self.length = self.length.min(i);
mem::replace(&mut self.children[i], MaybeUninit::uninit())
}
pub fn size(&self) -> usize {
self.length
}
}
impl<T, const B: usize> Node for LeafNode<T, B> {
type Prefix = Prefix<T, B>;
type Child = T;
fn new(_: super::node_ref_alloc::Token) -> Self {
Self::new()
}
fn item_size(_item: &Self::Child) -> usize {
1
}
fn prefix(&self) -> &Self::Prefix {
&self.prefix
}
fn size(&self) -> usize {
self.size()
}
fn length(&self) -> usize {
self.length
}
fn index(&self) -> usize {
self.prefix.index
}
fn simple_insert(
this: &mut NodeRef<Self, Mutable>,
i: usize,
item: Self::Child,
) {
Self::simple_insert(this, i, item);
}
fn simple_remove(&mut self, i: usize) -> Self::Child {
self.simple_remove(i)
}
fn split(
&mut self,
strategy: SplitStrategy,
alloc: &VerifiedAlloc<impl Allocator>,
) -> NodeRef<Self, Mutable> {
self.split(strategy, alloc)
}
fn merge(&mut self, other: &mut Self) {
self.merge(other)
}
}
impl<T, const B: usize, R> NodeRef<LeafNode<T, B>, R> {
pub fn into_children<'a>(self) -> &'a [T] {
unsafe { &*(self.children() as *const _) }
}
pub fn into_next(self) -> Result<Self, Self> {
if let Some(node) = self.next {
Ok(Self(node, Pd))
} else {
Err(self)
}
}
}
impl<T, const B: usize> NodeRef<LeafNode<T, B>, Mutable> {
pub fn into_children_mut<'a>(mut self) -> &'a mut [T] {
unsafe { &mut *(self.children_mut() as *mut _) }
}
}