use super::{Link, Links, List};
use crate::{util::FmtOption, Linked};
use core::{
fmt, mem,
ops::{Deref, DerefMut},
pin::Pin,
ptr::NonNull,
};
pub struct CursorMut<'list, T: Linked<Links<T>> + ?Sized> {
core: CursorCore<T, &'list mut List<T>>,
}
pub struct Cursor<'list, T: Linked<Links<T>> + ?Sized> {
core: CursorCore<T, &'list List<T>>,
}
struct CursorCore<T: ?Sized, L> {
list: L,
curr: Link<T>,
index: usize,
}
impl<'list, T: Linked<Links<T>> + ?Sized> Iterator for CursorMut<'list, T> {
type Item = Pin<&'list mut T>;
fn next(&mut self) -> Option<Self::Item> {
let node = self.core.curr?;
self.move_next();
unsafe { Some(self.core.pin_node_mut(node)) }
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
impl<'list, T: Linked<Links<T>> + ?Sized> CursorMut<'list, T> {
pub(super) fn new(list: &'list mut List<T>, curr: Link<T>, index: usize) -> Self {
Self {
core: CursorCore { list, index, curr },
}
}
pub fn index(&self) -> Option<usize> {
self.core.index()
}
pub fn move_next(&mut self) {
self.core.move_next()
}
pub fn move_prev(&mut self) {
self.core.move_prev()
}
pub fn remove_current(&mut self) -> Option<T::Handle> {
let node = self.core.curr?;
unsafe {
self.core.curr = T::links(node).as_ref().next();
self.core.list.remove(node)
}
}
pub fn remove_first(&mut self, mut predicate: impl FnMut(&T) -> bool) -> Option<T::Handle> {
while !predicate(unsafe { self.core.curr?.as_ref() }) {
self.move_next();
}
self.remove_current()
}
pub fn current(&self) -> Option<Pin<&T>> {
self.core.current()
}
pub fn current_mut(&mut self) -> Option<Pin<&mut T>> {
self.core
.curr
.map(|node| unsafe { self.core.pin_node_mut(node) })
}
pub fn peek_next(&self) -> Option<Pin<&T>> {
self.core.peek_next()
}
pub fn peek_prev(&self) -> Option<Pin<&T>> {
self.core.peek_prev()
}
pub fn peek_next_mut(&mut self) -> Option<Pin<&mut T>> {
self.core
.next_link()
.map(|next| unsafe { self.core.pin_node_mut(next) })
}
pub fn peek_prev_mut(&mut self) -> Option<Pin<&mut T>> {
self.core
.prev_link()
.map(|prev| unsafe { self.core.pin_node_mut(prev) })
}
pub fn insert_after(&mut self, element: T::Handle) {
let node = T::into_ptr(element);
assert_ne!(
self.core.curr,
Some(node),
"cannot insert a node after itself"
);
let next = self.core.next_link();
unsafe {
self.core
.list
.insert_nodes_between(self.core.curr, next, node, node, 1);
}
if self.core.curr.is_none() {
self.core.index = self.core.list.len;
}
}
pub fn insert_before(&mut self, element: T::Handle) {
let node = T::into_ptr(element);
assert_ne!(
self.core.curr,
Some(node),
"cannot insert a node before itself"
);
let prev = self.core.prev_link();
unsafe {
self.core
.list
.insert_nodes_between(prev, self.core.curr, node, node, 1);
}
self.core.index += 1;
}
pub fn len(&self) -> usize {
self.core.list.len()
}
pub fn is_empty(&self) -> bool {
self.core.list.is_empty()
}
pub fn split_after(&mut self) -> List<T> {
let split_at = if self.core.index == self.core.list.len {
self.core.index = 0;
0
} else {
self.core.index + 1
};
unsafe {
self.core.list.split_after_node(self.core.curr, split_at)
}
}
pub fn split_before(&mut self) -> List<T> {
let split_at = self.core.index;
self.core.index = 0;
let split_node = match self.core.curr {
Some(node) => node,
None => return mem::replace(self.core.list, List::new()),
};
let tail = unsafe { T::links(split_node).as_mut().set_prev(None) };
let head = if let Some(tail) = tail {
let _next = unsafe { T::links(tail).as_mut().set_next(None) };
debug_assert_eq!(_next, Some(split_node));
self.core.list.head.replace(split_node)
} else {
None
};
let split = List {
head,
tail,
len: split_at,
};
self.core.list.len -= split_at;
split
}
pub fn splice_after(&mut self, mut spliced: List<T>) {
let (splice_head, splice_tail, splice_len) = match spliced.take_all() {
Some(splice) => splice,
None => return,
};
let next = self.core.next_link();
unsafe {
self.core.list.insert_nodes_between(
self.core.curr,
next,
splice_head,
splice_tail,
splice_len,
);
}
if self.core.curr.is_none() {
self.core.index = self.core.list.len();
}
}
pub fn splice_before(&mut self, mut spliced: List<T>) {
let (splice_head, splice_tail, splice_len) = match spliced.take_all() {
Some(splice) => splice,
None => return,
};
let prev = self.core.prev_link();
unsafe {
self.core.list.insert_nodes_between(
prev,
self.core.curr,
splice_head,
splice_tail,
splice_len,
);
}
self.core.index += splice_len;
}
#[must_use]
pub fn as_cursor(&self) -> Cursor<'_, T> {
Cursor {
core: CursorCore {
list: self.core.list,
curr: self.core.curr,
index: self.core.index,
},
}
}
}
impl<T: Linked<Links<T>> + ?Sized> fmt::Debug for CursorMut<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self {
core: CursorCore { list, curr, index },
} = self;
f.debug_struct("CursorMut")
.field("curr", &FmtOption::new(curr))
.field("list", list)
.field("index", index)
.finish()
}
}
impl<'list, T: Linked<Links<T>> + ?Sized> Iterator for Cursor<'list, T> {
type Item = Pin<&'list T>;
fn next(&mut self) -> Option<Self::Item> {
let node = self.core.curr?;
self.move_next();
unsafe { Some(self.core.pin_node(node)) }
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
impl<'list, T: Linked<Links<T>> + ?Sized> Cursor<'list, T> {
pub(super) fn new(list: &'list List<T>, curr: Link<T>, index: usize) -> Self {
Self {
core: CursorCore { list, index, curr },
}
}
pub fn index(&self) -> Option<usize> {
self.core.index()
}
pub fn move_next(&mut self) {
self.core.move_next();
}
pub fn move_prev(&mut self) {
self.core.move_prev();
}
pub fn current(&self) -> Option<Pin<&T>> {
self.core.current()
}
pub fn peek_next(&self) -> Option<Pin<&T>> {
self.core.peek_next()
}
pub fn peek_prev(&self) -> Option<Pin<&T>> {
self.core.peek_prev()
}
pub fn len(&self) -> usize {
self.core.list.len()
}
pub fn is_empty(&self) -> bool {
self.core.list.is_empty()
}
}
impl<T: Linked<Links<T>> + ?Sized> fmt::Debug for Cursor<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self {
core: CursorCore { list, curr, index },
} = self;
f.debug_struct("Cursor")
.field("curr", &FmtOption::new(curr))
.field("list", list)
.field("index", index)
.finish()
}
}
impl<'list, T, L> CursorCore<T, L>
where
T: Linked<Links<T>> + ?Sized,
L: Deref<Target = List<T>> + 'list,
{
fn index(&self) -> Option<usize> {
self.curr?;
Some(self.index)
}
fn move_next(&mut self) {
match self.curr.take() {
Some(curr) => unsafe {
self.curr = T::links(curr).as_ref().next();
self.index += 1;
},
None => {
self.curr = self.list.head;
self.index = 0;
}
}
}
fn move_prev(&mut self) {
match self.curr.take() {
Some(curr) => unsafe {
self.curr = T::links(curr).as_ref().prev();
self.index = self.index.saturating_sub(1);
},
None => {
self.curr = self.list.tail;
self.index = self.index.checked_sub(1).unwrap_or(self.list.len());
}
}
}
fn current(&self) -> Option<Pin<&T>> {
self.curr.map(|node| unsafe { self.pin_node(node) })
}
fn peek_next(&self) -> Option<Pin<&T>> {
self.next_link().map(|next| unsafe { self.pin_node(next) })
}
fn peek_prev(&self) -> Option<Pin<&T>> {
self.prev_link().map(|prev| unsafe { self.pin_node(prev) })
}
#[inline(always)]
fn next_link(&self) -> Link<T> {
match self.curr {
Some(curr) => unsafe { T::links(curr).as_ref().next() },
None => self.list.head,
}
}
#[inline(always)]
fn prev_link(&self) -> Link<T> {
match self.curr {
Some(curr) => unsafe { T::links(curr).as_ref().prev() },
None => self.list.tail,
}
}
unsafe fn pin_node(&self, node: NonNull<T>) -> Pin<&'list T> {
Pin::new_unchecked(node.as_ref())
}
}
impl<'list, T, L> CursorCore<T, L>
where
T: Linked<Links<T>> + ?Sized,
L: Deref<Target = List<T>> + DerefMut + 'list,
{
unsafe fn pin_node_mut(&self, mut node: NonNull<T>) -> Pin<&'list mut T> {
Pin::new_unchecked(node.as_mut())
}
}