use crate::allocator::{Allocator, Global};
use crate::options::{LeafSize, ListOptions};
use cell_ref::CellExt;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::convert::TryFrom;
use core::iter::once;
use core::marker::PhantomData;
use core::mem;
use integral_constant::{Bool, Constant};
#[cfg(skippy_debug)]
pub mod debug;
mod destroy;
mod destroy_safety;
mod insert;
pub mod iter;
mod node;
mod remove;
mod split;
mod traverse;
use crate::PersistentAlloc;
use destroy::{deconstruct, destroy_node_list};
use destroy_safety::SetUnsafeOnDrop;
use insert::insert_after;
use iter::Iter;
pub use node::{AllocItem, LeafNext, LeafRef, This};
use node::{Down, InternalNodeRef, Key, Next, NodeRef, SizeExt};
use remove::remove;
use traverse::{get_last_sibling, get_parent_info};
use traverse::{get_previous, get_previous_info};
fn min_node_length<L: LeafRef>() -> usize {
(max_node_length::<L>() + 1) / 2
}
fn max_node_length<L: LeafRef>() -> usize {
<L::Options as ListOptions>::Fanout::VALUE.max(3)
}
fn roots_match<L: LeafRef>(a: &Down<L>, b: &Down<L>) -> bool {
type Internal<'a, L> = &'a InternalNodeRef<L>;
Internal::try_from(a) == Internal::try_from(b)
}
fn propagate_update_diff<N: NodeRef>(
node: N,
mut key: Option<Key<N::Leaf>>,
old_size: LeafSize<N::Leaf>,
new_size: LeafSize<N::Leaf>,
) {
let has_size_diff = old_size != new_size;
let info = get_parent_info(node);
let mut parent = info.parent;
let mut index = info.index;
while let Some(node) = parent {
key = key.filter(|_| index == 0);
let mut updated = false;
if has_size_diff {
updated = true;
node.size.with_mut(|s| {
*s += new_size.clone();
*s -= old_size.clone();
});
}
if let Some(key) = &key {
updated = true;
node.key.set(Some(key.clone()));
}
if !updated {
break;
}
let info = get_parent_info(node);
parent = info.parent;
index = info.index;
}
}
pub struct SkipList<L, A = Global>
where
L: LeafRef,
A: Allocator,
{
alloc: PersistentAlloc<A>,
root: Option<Down<L>>,
phantom: PhantomData<*mut ()>,
}
impl<L: LeafRef> SkipList<L> {
pub fn new() -> Self {
Self::new_in(Global)
}
pub fn next(item: L) -> Option<L> {
let mut node = match NodeRef::next(&item)? {
Next::Sibling(node) => return Some(node),
Next::Parent(mut node) => loop {
node = match node.next()? {
Next::Sibling(node) => break node,
Next::Parent(node) => node,
}
},
};
loop {
node = match node.down().unwrap() {
Down::Leaf(node) => return Some(node),
Down::Internal(node) => node,
};
}
}
pub fn previous(item: L) -> Option<L> {
let mut node = match get_previous(item)? {
Next::Sibling(node) => return Some(node),
Next::Parent(mut node) => loop {
node = match get_previous(node)? {
Next::Sibling(node) => break node,
Next::Parent(node) => node,
}
},
};
loop {
node = match node.down().unwrap() {
Down::Leaf(node) => return Some(get_last_sibling(node)),
Down::Internal(node) => get_last_sibling(node),
};
}
}
pub fn iter_at(item: L) -> Iter<L> {
Iter(Some(item))
}
fn subtree_first(first_child: Down<L>) -> L {
let mut node = first_child;
loop {
node = match node {
Down::Leaf(node) => return node,
Down::Internal(node) => node.down().unwrap(),
}
}
}
fn subtree_last(first_child: Down<L>) -> L {
let mut node = first_child;
loop {
node = match node {
Down::Leaf(node) => return get_last_sibling(node),
Down::Internal(node) => get_last_sibling(node).down().unwrap(),
}
}
}
}
impl<L, A> SkipList<L, A>
where
L: LeafRef,
A: Allocator,
{
pub fn new_in(alloc: A) -> Self
where
A: 'static,
{
Self {
alloc: PersistentAlloc::new(alloc),
root: None,
phantom: PhantomData,
}
}
pub fn size(&self) -> LeafSize<L> {
self.root.as_ref().map_or_else(Default::default, |r| r.size())
}
pub fn get<S>(&self, index: &S) -> Option<L>
where
S: Ord + ?Sized,
LeafSize<L>: Borrow<S>,
{
self.get_with_cmp(|size| size.borrow().cmp(index))
}
pub fn get_with<S>(&self, index: &S) -> Option<L>
where
S: ?Sized,
LeafSize<L>: PartialOrd<S>,
{
self.get_with_cmp(|size| {
size.partial_cmp(index).unwrap_or_else(
#[cold]
|| panic!("`partial_cmp` returned `None`"),
)
})
}
pub fn get_with_cmp<F>(&self, cmp: F) -> Option<L>
where
F: Fn(&LeafSize<L>) -> Ordering,
{
SkipList::subtree_get(cmp, self.root.clone()?, Default::default())
}
}
impl<L: LeafRef> SkipList<L> {
pub fn index(item: L) -> LeafSize<L> {
fn add_siblings<N: NodeRef>(
mut node: N,
index: &mut LeafSize<N::Leaf>,
) -> Result<InternalNodeRef<N::Leaf>, N> {
loop {
node = match node.next().ok_or(node)? {
Next::Parent(parent) => return Ok(parent),
Next::Sibling(node) => {
*index += node.size();
node
}
}
}
}
let mut index = item.size();
let mut node = match add_siblings(item, &mut index) {
Ok(parent) => parent,
Err(_) => {
return Default::default();
}
};
loop {
node = match add_siblings(node, &mut index) {
Ok(parent) => parent,
Err(node) => {
return node.size().sub(index);
}
};
}
}
fn subtree_get<F>(
cmp: F,
first_child: Down<L>,
offset: LeafSize<L>,
) -> Option<L>
where
F: Fn(&LeafSize<L>) -> Ordering,
{
let mut node = first_child;
let mut size = offset;
loop {
node = match node {
Down::Leaf(mut node) => loop {
let new_size = size.clone().add(node.size());
let ord = cmp(&new_size);
if ord.is_le() {
if let Some(next) = node.next_sibling() {
node = next;
size = new_size;
continue;
}
if !(ord.is_eq() && size == new_size) {
return None;
}
}
return Some(node);
},
Down::Internal(mut node) => loop {
let new_size = size.clone().add(node.size());
let ord = cmp(&new_size);
if ord.is_le() {
if let Some(next) = node.next_sibling() {
node = next;
size = new_size;
continue;
}
if !ord.is_eq() {
return None;
}
}
break node.down().unwrap();
},
}
}
}
pub fn get_after<S>(start: L, offset: &S) -> Option<L>
where
S: Ord + ?Sized,
LeafSize<L>: Borrow<S>,
{
Self::get_after_with_cmp(start, |size| size.borrow().cmp(offset))
}
pub fn get_after_with<S>(start: L, offset: &S) -> Option<L>
where
S: ?Sized,
LeafSize<L>: PartialOrd<S>,
{
Self::get_after_with_cmp(start, |size| {
size.partial_cmp(offset).unwrap_or_else(
#[cold]
|| panic!("`partial_cmp` returned `None`"),
)
})
}
pub fn get_after_with_cmp<F>(start: L, cmp: F) -> Option<L>
where
F: Fn(&LeafSize<L>) -> Ordering,
{
let mut leaf = start;
let mut size = LeafSize::<L>::default();
let mut ord;
let mut internal = loop {
let old_size = size.clone();
size += leaf.size();
ord = cmp(&size);
if ord.is_le() {
match NodeRef::next(&leaf) {
Some(Next::Sibling(next)) => {
leaf = next;
continue;
}
Some(Next::Parent(node)) => break node,
None if ord.is_eq() && old_size == size => {}
None => return None,
}
}
return Some(leaf);
};
let mut leaf_is_last = true;
loop {
match internal.next() {
Some(Next::Sibling(next)) => {
internal = next;
leaf_is_last = false;
}
Some(Next::Parent(node)) => {
internal = node;
continue;
}
None if ord.is_eq() => {
let last = if leaf_is_last {
leaf
} else {
Self::subtree_last(internal.as_down())
};
return if last.size() == Default::default() {
Some(last)
} else {
None
};
}
None => return None,
}
let new_size = size.clone().add(internal.size());
ord = cmp(&new_size);
if ord.is_gt() {
return Self::subtree_get(cmp, internal.down().unwrap(), size);
}
size = new_size;
}
}
}
impl<L, A> SkipList<L, A>
where
L: LeafRef,
A: Allocator,
{
pub fn insert_after(&mut self, pos: L, item: L) {
self.insert_after_from(pos, once(item));
}
pub fn insert_after_from<I>(&mut self, pos: L, items: I)
where
I: IntoIterator<Item = L>,
{
let root = self.root.as_ref().expect("`pos` is not from this list");
let set_unsafe_on_drop = SetUnsafeOnDrop;
let result = insert_after(pos, items.into_iter(), &self.alloc);
assert!(
roots_match(root, &result.old_root),
"`pos` is not from this list",
);
mem::forget(set_unsafe_on_drop);
self.root = Some(result.new_root);
}
pub fn insert_after_opt(&mut self, pos: Option<L>, item: L) {
self.insert_after_opt_from(pos, once(item));
}
pub fn insert_after_opt_from<I>(&mut self, pos: Option<L>, items: I)
where
I: IntoIterator<Item = L>,
{
if let Some(pos) = pos {
self.insert_after_from(pos, items);
} else {
self.push_front_from(items);
}
}
pub fn insert_before(&mut self, pos: L, item: L) {
self.insert_before_from(pos, once(item));
}
pub fn insert_before_from<I>(&mut self, pos: L, items: I)
where
I: IntoIterator<Item = L>,
{
self.insert_after_opt_from(SkipList::previous(pos), items);
}
pub fn insert_before_opt(&mut self, pos: Option<L>, item: L) {
self.insert_before_opt_from(pos, once(item));
}
pub fn insert_before_opt_from<I>(&mut self, pos: Option<L>, items: I)
where
I: IntoIterator<Item = L>,
{
if let Some(pos) = pos {
self.insert_before_from(pos, items);
} else {
self.push_back_from(items);
}
}
pub fn push_front(&mut self, item: L) {
self.push_front_from(once(item));
}
pub fn push_front_from<I>(&mut self, items: I)
where
I: IntoIterator<Item = L>,
{
let mut iter = items.into_iter();
let first = match iter.next() {
Some(item) => item,
None => return,
};
assert!(first.next().is_none(), "item is already in a list");
let size = first.size();
let mut parent = None;
let next = self.root.clone().map(|mut down| {
loop {
match down {
Down::Leaf(node) => return node,
Down::Internal(node) => {
node.size.with_mut(|s| *s += size.clone());
node.key.set(first.key());
down = node.down().unwrap();
parent = Some(node);
}
}
}
});
if let Some(parent) = parent {
parent.set_down(Some(Down::Leaf(first.clone())));
parent.len.with_mut(|len| *len += 1);
NodeRef::set_next(&first, Some(Next::Sibling(next.unwrap())));
self.insert_after_from(first, iter);
} else if let Some(next) = next {
debug_assert!(next.next().is_none());
self.root = Some(Down::Leaf(first.clone()));
self.insert_after_from(first, iter.chain(once(next)));
} else {
debug_assert!(self.root.is_none());
self.root = Some(Down::Leaf(first.clone()));
self.insert_after_from(first, iter);
}
}
pub fn push_back(&mut self, item: L) {
self.push_back_from(once(item));
}
pub fn push_back_from<I>(&mut self, items: I)
where
I: IntoIterator<Item = L>,
{
self.insert_after_opt_from(self.last(), items);
}
pub fn remove(&mut self, item: L) {
let root = self.root.as_ref().expect("`item` is not from this list");
let mut result = remove(item);
assert!(
roots_match(root, &result.old_root),
"`item` is not from this list"
);
unsafe {
destroy_node_list(&mut result.removed, &self.alloc);
}
self.root = result.new_root;
}
pub fn update<F>(&mut self, item: L, update: F)
where
F: FnOnce(),
{
let old_size = item.size();
update();
let new_size = item.size();
propagate_update_diff(item, None, old_size, new_size);
}
pub fn replace(&mut self, old: L, new: L) {
assert!(new.next().is_none(), "new item is already in a list");
let old_size = old.size();
new.set_next(NodeRef::next(&old));
old.set_next(None);
let info = get_previous_info(new.clone());
let (parent, previous) = if let Some(prev) = info.previous {
(prev.parent, prev.node)
} else {
self.root = Some(new.as_down());
return;
};
match previous {
Next::Parent(parent) => parent.set_down(Some(new.as_down())),
Next::Sibling(prev) => {
prev.set_next(Some(Next::Sibling(new.clone())))
}
};
propagate_update_diff(
parent,
if info.index == 0 {
let key = new.key();
parent.key.set(key.clone());
key
} else {
None
},
old_size,
new.size(),
);
}
pub fn first(&self) -> Option<L> {
self.root.clone().map(SkipList::subtree_first)
}
pub fn last(&self) -> Option<L> {
self.root.clone().map(SkipList::subtree_last)
}
pub fn iter(&self) -> Iter<L> {
Iter(self.first())
}
}
impl<L, A> SkipList<L, A>
where
L: LeafRef,
A: Allocator,
L::Options: ListOptions<StoreKeys = Bool<true>>,
{
pub fn insert(&mut self, item: L) -> Result<(), L>
where
L: Ord,
{
self.insert_after_opt(
match self.find(&item) {
Ok(n) => Err(n), Err(n) => Ok(n), }?,
item,
);
Ok(())
}
pub fn find<K>(&self, key: &K) -> Result<L, Option<L>>
where
K: Ord + ?Sized,
L: Borrow<K>,
{
self.find_with_cmp(|item| item.borrow().cmp(key))
}
pub fn find_with<K>(&self, key: &K) -> Result<L, Option<L>>
where
K: ?Sized,
L: PartialOrd<K>,
{
self.find_with_cmp(|item| {
item.partial_cmp(key).unwrap_or_else(
#[cold]
|| panic!("`partial_cmp` returned `None`"),
)
})
}
pub fn find_with_cmp<F>(&self, cmp: F) -> Result<L, Option<L>>
where
F: Fn(&L) -> Ordering,
{
SkipList::subtree_find(cmp, self.root.clone().ok_or(None)?)
}
}
impl<L> SkipList<L>
where
L: LeafRef,
L::Options: ListOptions<StoreKeys = Bool<true>>,
{
fn subtree_find<F>(cmp: F, first_child: Down<L>) -> Result<L, Option<L>>
where
F: Fn(&L) -> Ordering,
{
let mut node = first_child;
#[cfg(debug_assertions)]
let mut first = true;
loop {
let mut prev_leaf: Option<L> = None;
let mut prev_internal: Option<InternalNodeRef<L>> = None;
node = match node {
Down::Leaf(mut node) => loop {
match cmp(&node) {
Ordering::Less => {}
Ordering::Equal => return Ok(node),
Ordering::Greater => {
#[cfg(debug_assertions)]
debug_assert!(first || prev_leaf.is_some());
return Err(prev_leaf);
}
}
if let Some(next) = node.next_sibling() {
prev_leaf = Some(node);
node = next;
} else {
return Err(Some(node));
}
},
Down::Internal(mut node) => loop {
let key = node.key().unwrap();
match cmp(&key) {
Ordering::Less => {}
Ordering::Equal => return Ok(key),
Ordering::Greater => {
#[cfg(debug_assertions)]
debug_assert!(first || prev_internal.is_some());
break prev_internal.ok_or(None)?.down().unwrap();
}
}
if let Some(next) = node.next_sibling() {
prev_internal = Some(node);
node = next;
} else {
break node.down().unwrap();
}
},
};
#[cfg(debug_assertions)]
{
first = false;
}
}
}
pub fn find_after<K>(start: L, key: &K) -> Result<L, Option<L>>
where
K: Ord + ?Sized,
L: Borrow<K>,
{
Self::find_after_with_cmp(start, |item| item.borrow().cmp(key))
}
pub fn find_after_with<K>(start: L, key: &K) -> Result<L, Option<L>>
where
K: ?Sized,
L: PartialOrd<K>,
{
Self::find_after_with_cmp(start, |item| {
item.partial_cmp(key).unwrap_or_else(
#[cold]
|| panic!("`partial_cmp` returned `None`"),
)
})
}
pub fn find_after_with_cmp<F>(start: L, cmp: F) -> Result<L, Option<L>>
where
F: Fn(&L) -> Ordering,
{
let mut leaf = start;
let mut prev = None;
let mut internal = loop {
match cmp(&leaf) {
Ordering::Less => {}
Ordering::Equal => return Ok(leaf),
Ordering::Greater => return Err(prev),
}
match NodeRef::next(&leaf) {
Some(Next::Sibling(next)) => {
prev = Some(leaf);
leaf = next;
}
Some(Next::Parent(node)) => break node,
None => return Err(Some(leaf)),
}
};
let mut leaf_is_last = true;
let down = loop {
match internal.next() {
Some(Next::Sibling(next)) => {
let key = next.key().unwrap();
let ord = cmp(&key);
match ord {
Ordering::Less => {}
Ordering::Equal => return Ok(key),
Ordering::Greater => break internal.down().unwrap(),
}
internal = next;
leaf_is_last = false;
}
Some(Next::Parent(node)) => {
internal = node;
continue;
}
None if leaf_is_last => return Err(Some(leaf)),
None => break internal.down().unwrap(),
}
};
Self::subtree_find(cmp, down)
}
}
impl<L, A> Default for SkipList<L, A>
where
L: LeafRef,
A: Allocator + Default + 'static,
{
fn default() -> Self {
Self::new_in(A::default())
}
}
impl<L, A> Drop for SkipList<L, A>
where
L: LeafRef,
A: Allocator,
{
fn drop(&mut self) {
let mut nodes = deconstruct(match self.root.take() {
Some(root) => root,
None => return,
});
unsafe {
destroy_node_list(&mut nodes, &self.alloc);
}
unsafe {
self.alloc.drop();
}
}
}
impl<L, A> Extend<L> for SkipList<L, A>
where
L: LeafRef,
A: Allocator,
{
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = L>,
{
self.push_back_from(iter);
}
}