use std::fmt::Debug;
use std::marker::PhantomData;
use std::cmp::Ordering;
use std::mem;
use std::ptr::NonNull;
use std::ops::Not;
pub struct IterList<T> {
current: NonNull<Node<T>>,
index: usize,
len: usize,
_boo: PhantomData<T>,
}
struct Node<T> {
next: Option<NonNull<Node<T>>>,
prev: Option<NonNull<Node<T>>>,
elem: T,
}
impl<T> Node<T> {
fn new_nonnull(elem: T) -> NonNull<Self> {
unsafe {
NonNull::new_unchecked(Box::into_raw(Box::new(Self {
next: None,
prev: None,
elem,
})))
}
}
}
unsafe impl<T: Send> Send for IterList<T> {}
unsafe impl<T: Sync> Sync for IterList<T> {}
impl<T> IterList<T> {
#[inline]
pub const fn new() -> Self {
Self {
current: NonNull::dangling(),
len: 0,
index: 0,
_boo: PhantomData
}
}
pub unsafe fn new_zeroed(count: usize) -> Self {
(0..count).fold(Self::new(), |mut list, _| {
list.insert_next(std::mem::MaybeUninit::zeroed().assume_init()); list
})
}
pub fn insert_next(&mut self, elem: T) {
let mut new = Node::new_nonnull(elem);
match self.len {
0 => self.current = new,
_ => {
unsafe {
if let Some(mut next) = self.current.as_mut().next {
next.as_mut().prev = Some(new);
new.as_mut().next = Some(next);
}
self.current.as_mut().next = Some(new);
new.as_mut().prev = Some(self.current);
}
},
}
self.len += 1;
}
pub fn insert_prev(&mut self, elem: T) {
let mut new = Node::new_nonnull(elem);
match self.len {
0 => self.current = new,
_ => {
unsafe {
if let Some(mut prev) = self.current.as_mut().prev {
prev.as_mut().next = Some(new);
new.as_mut().prev = Some(prev);
}
self.current.as_mut().prev = Some(new);
new.as_mut().next = Some(self.current);
}
self.index += 1;
},
}
self.len += 1;
}
pub fn push_next(&mut self, elem: T) {
if self.len == 0 {
self.insert_next(elem);
return;
}
self.insert_next(elem);
let _ = self.advance();
}
pub fn push_prev(&mut self, elem: T) {
if self.len == 0 {
self.insert_prev(elem);
return;
}
self.insert_prev(elem);
let _ = self.retreat();
}
pub fn move_to_front(&mut self) -> usize {
if self.len == 0 { return 0; }
self.index = 0;
for i in 0_usize.. {
match unsafe { self.current.as_ref().prev } {
Some(prev) => self.current = prev,
None => return i,
}
}
unsafe { std::hint::unreachable_unchecked() }
}
pub fn move_to_back(&mut self) -> usize {
if self.len == 0 { return 0; }
self.index = self.len - 1;
for i in 0_usize.. {
match unsafe { self.current.as_ref().next } {
Some(next) => self.current = next,
None => return i,
}
}
unsafe { std::hint::unreachable_unchecked() }
}
#[inline]
#[must_use]
pub fn move_to(&mut self, index: usize) -> bool {
match self.index.cmp(&index) {
Ordering::Greater => !(0..self.index - index).any(|_| !self.retreat()),
Ordering::Less => !(0..index - self.index).any(|_| !self.advance()),
Ordering::Equal => true,
}
}
#[inline]
#[must_use]
pub fn advance(&mut self) -> bool {
if self.len == 0 { return false; }
unsafe { self.current.as_ref() }.next.map(|next| {
self.current = next;
self.index += 1; })
.is_some()
}
#[inline]
pub unsafe fn advance_unchecked(&mut self) {
self.current = self.current.as_ref().next.unwrap_unchecked();
self.index += 1;
}
#[inline]
#[must_use]
pub fn retreat(&mut self) -> bool {
if self.len == 0 { return false; }
unsafe { self.current.as_ref() }.prev.map(|prev| {
self.current = prev;
self.index -= 1; })
.is_some()
}
#[inline]
pub unsafe fn retreat_unchecked(&mut self) {
self.current = self.current.as_ref().prev.unwrap_unchecked();
self.index -= 1;
}
#[inline]
#[must_use]
pub fn move_by(&mut self, offset: isize) -> bool {
match offset.cmp(&0) {
Ordering::Greater => (0..offset ).fold(true, |_, _| self.advance()),
Ordering::Less => (0..-offset).fold(true, |_, _| self.retreat()),
Ordering::Equal => true,
}
}
fn get_raw(&self, offset: isize) -> Option<NonNull<Node<T>>> {
if self.index as isize + offset < 0 || self.index as isize + offset >= self.len as isize {
return None;
}
match offset.cmp(&0) {
Ordering::Greater => (0.. offset).try_fold(self.current, |mut ptr, _| unsafe { ptr.as_ref() }.next.map(|c| { ptr = c; ptr })),
Ordering::Less => (0..-offset).try_fold(self.current, |mut ptr, _| unsafe { ptr.as_ref() }.prev.map(|c| { ptr = c; ptr })),
Ordering::Equal => Some(self.current)
}
}
#[inline]
pub fn get(&self, offset: isize) -> Option<&T> {
self.get_raw(offset).map(|ptr| unsafe { &ptr.as_ref().elem })
}
#[inline]
pub fn get_mut(&mut self, offset: isize) -> Option<&mut T> {
self.get_raw(offset).map(|mut ptr| unsafe { &mut ptr.as_mut().elem })
}
pub fn consume_forward(&mut self) -> Option<(T, bool)> {
if self.len == 0 { return None; }
let node = unsafe { Box::from_raw(self.current.as_ptr()) };
self.len -= 1;
node.prev.map(|mut prev| unsafe { prev.as_mut().next = node.next });
match node.next {
Some(mut next) => {
unsafe { next.as_mut().prev = node.prev; }
self.current = next;
Some((node.elem, true))
},
None => {
self.current = node.prev.unwrap_or(NonNull::dangling()); Some((node.elem, false))
}
}
}
pub fn consume_backward(&mut self) -> Option<(T, bool)> {
if self.len == 0 { return None; }
let node = unsafe { Box::from_raw(self.current.as_ptr()) };
self.len -= 1;
self.index -= 1;
node.next.map(|mut next| unsafe { next.as_mut().prev = node.prev });
match node.prev {
Some(mut prev) => {
unsafe { prev.as_mut().next = node.next; }
self.current = prev;
Some((node.elem, true))
},
None => {
self.current = node.next.unwrap_or(NonNull::dangling());
Some((node.elem, false))
}
}
}
#[inline]
pub fn replace_cursor(&mut self, elem: T) -> Option<T> {
match self.len {
0 => { self.push_next(elem); None },
_ => Some(std::mem::replace(unsafe { &mut self.current.as_mut().elem }, elem)),
}
}
#[inline]
pub unsafe fn apply_cursor_unchecked(&mut self, cursor: &Cursor<T>) {
self.current = cursor.current.unwrap_unchecked();
self.index = cursor.index;
}
#[inline]
pub fn apply_cursor(&mut self, cursor: &Cursor<T>) -> bool {
if self.index + cursor.index >= self.len { return false; }
match self.index.cmp(&cursor.index) {
Ordering::Greater => (0..self.index - cursor.index)
.try_fold(self.current, |ptr, _| unsafe { ptr.as_ref() }.prev.map(|c| { self.current = c; ptr }))
.map(|p| { self.current = p; self.index = cursor.index }).is_some(),
Ordering::Less => (0..cursor.index - self.index)
.try_fold(self.current, |ptr, _| unsafe { ptr.as_ref() }.next.map(|c| { self.current = c; ptr }))
.map(|p| { self.current = p; self.index = cursor.index }).is_some(),
Ordering::Equal => true,
}
}
pub fn split_after(&mut self) -> Option<Self> {
if self.len == 0 { return None; }
unsafe { self.current.as_ref() }.next.map(|next| {
let mut new = Self::new();
new.current = next;
new.len = self.len - self.index - 1;
self.len -= new.len;
unsafe { self.current.as_mut().next = None; }
unsafe { new .current.as_mut().prev = None; }
new
})
}
pub fn split_before(&mut self) -> Option<Self> {
if self.len == 0 { return None; }
unsafe { self.current.as_ref() }.prev.map(|prev| {
let mut new = Self::new();
new.current = prev;
new.len = self.index;
self.len -= new.len;
self.index = 0;
new.index = new.len - 1;
unsafe { self.current.as_mut().prev = None; }
unsafe { new .current.as_mut().next = None; }
new
})
}
#[inline]
pub fn current(&self) -> Option<&T> {
self.is_empty().not().then_some(unsafe { &self.current.as_ref().elem })
}
#[inline]
pub fn get_current_mut(&mut self) -> Option<&mut T> {
self.is_empty().not().then_some(unsafe { &mut self.current.as_mut().elem })
}
#[inline]
pub const fn len(&self) -> usize {
self.len
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub const fn index(&self) -> usize {
self.index
}
#[inline]
pub fn as_cursor(&self) -> Cursor<T> {
Cursor {
_list: PhantomData,
index: self.index,
current: self.is_empty().not().then_some(self.current),
}
}
}
impl<T> std::ops::Index<isize> for IterList<T> {
type Output = T;
#[inline]
fn index(&self, index: isize) -> &Self::Output {
self.get(index).expect("Index out of bounds")
}
}
impl<T> Default for IterList<T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<T> std::ops::IndexMut<isize> for IterList<T> {
#[inline]
fn index_mut(&mut self, index: isize) -> &mut Self::Output {
self.get_mut(index).expect("Index out of bounds")
}
}
impl<T: Clone> Clone for IterList<T> {
fn clone(&self) -> Self {
let mut cursor = self.as_cursor();
cursor.move_to_front();
let mut list = cursor.cloned()
.fold(Self::new(), |mut list, elem| { list.push_next(elem); list });
let _ = list.move_to(self.index());
list
}
}
impl<T: Debug> Debug for IterList<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "[")?;
let base = -(self.index() as isize);
for i in 0..self.len as isize {
let element = self.get(base + i);
if let Some(element) = element {
write!(f, "{:?}", element)?;
}
if i + 1 < (self.len as isize) {
write!(f, ", ")?;
}
}
write!(f, "]")
}
}
impl<T> Drop for IterList<T> {
#[inline]
fn drop(&mut self) {
if self.is_empty() { return; }
self.move_to_front();
loop {
let next = unsafe { self.current.as_ref().next };
mem::drop(unsafe { Box::from_raw(self.current.as_ptr()) });
match next {
Some(next) => self.current = next,
None => break,
}
}
}
}
impl<T> Iterator for IterList<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.consume_forward().map(|(elem, b)| {
if !b { while self.consume_backward().is_some() {} }
elem
})
}
}
impl<T> DoubleEndedIterator for IterList<T> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.consume_backward().map(|(elem, b)| {
if !b { while self.consume_forward().is_some() {} }
elem
})
}
}
impl<T> From<Vec<T>> for IterList<T> {
fn from(vec: Vec<T>) -> Self {
let mut list = vec.into_iter().fold(Self::new(),
|mut list, elem| { list.push_next(elem); list });
list.move_to_front();
list
}
}
impl<T: Clone> From<&[T]> for IterList<T> {
fn from(slice: &[T]) -> Self {
let mut list = slice.iter().cloned().fold(Self::new(),
|mut list, elem| { list.push_next(elem); list });
list.move_to_front();
list
}
}
impl<T> FromIterator<T> for IterList<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut list = iter.into_iter().fold(Self::new(),
|mut list, elem| { list.push_next(elem); list });
list.move_to_front();
list
}
}
#[derive(Clone, Copy)]
pub struct Cursor<'i, T> {
current: Option<NonNull<Node<T>>>,
index: usize,
_list: PhantomData<&'i T>,
}
unsafe impl<'i, T: Send> Send for Cursor<'i, T> {}
unsafe impl<'i, T: Sync> Sync for Cursor<'i, T> {}
impl<'i, T> Iterator for Cursor<'i, T> {
type Item = &'i T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.current.map(|c| {
self.current = unsafe { c.as_ref().next };
self.index += 1;
unsafe { &c.as_ref().elem }
})
}
}
impl<'t, T> Cursor<'t, T> {
#[inline]
pub const unsafe fn from_raw(ptr: *mut u8) -> Self {
Self {
current: Some(NonNull::new_unchecked(ptr as *mut Node<T>)),
index: 0,
_list: PhantomData,
}
}
#[inline]
pub const unsafe fn new_dangling() -> Self {
Self {
current: Some(NonNull::dangling()),
index: 0,
_list: PhantomData,
}
}
#[inline]
pub const fn new() -> Self {
Self {
current: None,
index: 0,
_list: PhantomData,
}
}
#[inline]
pub fn from(list: &'t IterList<T>) -> Self {
assert!(!list.is_empty(), "Cannot create a cursor from an empty list");
Self {
current: Some(list.current),
index: list.index,
_list: PhantomData,
}
}
#[inline]
pub fn reacquire(&mut self, list: &'t IterList<T>) {
self.current = (list.len != 0).then_some(list.current);
self.index = list.index;
}
#[inline]
pub fn current(&self) -> Option<&T> {
self.current.map(|c| unsafe { &c.as_ref().elem })
}
#[inline]
pub const fn index(&self) -> usize {
self.index
}
pub fn move_to_front(&mut self) -> usize {
self.index = 0;
for i in 0_usize.. {
match self.current.and_then(|c| unsafe { c.as_ref().prev }) {
Some(prev) => self.current = Some(prev),
None => return i,
}
}
unsafe { std::hint::unreachable_unchecked() }
}
pub fn move_to_back(&mut self) -> usize {
for i in 0_usize.. {
match self.current.and_then(|c| unsafe { c.as_ref().next }) {
Some(next) => self.current = Some(next),
None => {
self.index = i;
return i;
},
}
}
unsafe { std::hint::unreachable_unchecked() }
}
#[inline]
#[must_use]
pub fn move_to(&mut self, index: usize) -> bool {
match self.index.cmp(&index) {
Ordering::Greater => !(0..self.index - index).any(|_| !self.retreat()),
Ordering::Less => !(0..index - self.index).any(|_| !self.advance()),
Ordering::Equal => true,
}
}
#[inline]
#[must_use]
pub fn advance(&mut self) -> bool {
self.current.and_then(|c| unsafe { c.as_ref().next }).map(|next| {
self.current = Some(next);
self.index += 1; })
.is_some()
}
#[inline]
#[must_use]
pub fn retreat(&mut self) -> bool {
self.current.and_then(|c| unsafe { c.as_ref().prev }).map(|prev| {
self.current = Some(prev);
self.index -= 1; })
.is_some()
}
#[inline]
pub fn move_by(&mut self, offset: isize) -> bool {
match offset.cmp(&0) {
Ordering::Greater => (0..offset ).fold(true, |_, _| self.advance()),
Ordering::Less => (0..-offset).fold(true, |_, _| self.retreat()),
Ordering::Equal => true,
}
}
pub fn get(&self, offset: isize) -> Option<&T> {
match offset.cmp(&0) {
Ordering::Greater => (0.. offset).try_fold(self.current, |mut ptr, _| ptr.and_then(|c| unsafe { c.as_ref().next }).map(|c| { ptr = Some(c); ptr }))?,
Ordering::Less => (0..-offset).try_fold(self.current, |mut ptr, _| ptr.and_then(|c| unsafe { c.as_ref().prev }).map(|c| { ptr = Some(c); ptr }))?,
Ordering::Equal => self.current
}.map(|c| unsafe { &c.as_ref().elem })
}
}
impl<'i, T> std::ops::Deref for Cursor<'i, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.current().unwrap()
}
}
impl<'i, T> std::ops::Index<isize> for Cursor<'i, T> {
type Output = T;
#[inline]
fn index(&self, index: isize) -> &Self::Output {
self.get(index).unwrap_or_else(|| panic!("Index out of bounds"))
}
}
impl<T: Debug> Debug for Cursor<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}: {:?}", self.index, self.current())
}
}