extern crate alloc;
use alloc::{boxed::Box, sync::Arc};
use core::{iter, ptr::NonNull};
use crate::{GetLinks, Links, raw_list, raw_list::RawList};
pub trait Wrapper<T: ?Sized> {
fn into_pointer(self) -> NonNull<T>;
unsafe fn from_pointer(ptr: NonNull<T>) -> Self;
fn as_ref(&self) -> &T;
}
impl<T: ?Sized> Wrapper<T> for Box<T> {
#[inline]
fn into_pointer(self) -> NonNull<T> {
NonNull::new(Box::into_raw(self)).unwrap()
}
#[inline]
unsafe fn from_pointer(ptr: NonNull<T>) -> Self {
unsafe { Box::from_raw(ptr.as_ptr()) }
}
#[inline]
fn as_ref(&self) -> &T {
AsRef::as_ref(self)
}
}
impl<T: ?Sized> Wrapper<T> for Arc<T> {
#[inline]
fn into_pointer(self) -> NonNull<T> {
NonNull::new(Arc::into_raw(self) as _).unwrap()
}
#[inline]
unsafe fn from_pointer(ptr: NonNull<T>) -> Self {
unsafe { Arc::from_raw(ptr.as_ptr() as _) }
}
#[inline]
fn as_ref(&self) -> &T {
AsRef::as_ref(self)
}
}
impl<T: ?Sized> Wrapper<T> for &T {
#[inline]
fn into_pointer(self) -> NonNull<T> {
NonNull::from(self)
}
#[inline]
unsafe fn from_pointer(ptr: NonNull<T>) -> Self {
unsafe { &*ptr.as_ptr() }
}
#[inline]
fn as_ref(&self) -> &T {
self
}
}
pub trait GetLinksWrapped: GetLinks {
type Wrapped: Wrapper<Self::EntryType>;
}
impl<T: ?Sized> GetLinksWrapped for Box<T>
where
Box<T>: GetLinks,
{
type Wrapped = Box<<Box<T> as GetLinks>::EntryType>;
}
impl<T: GetLinks + ?Sized> GetLinks for Box<T> {
type EntryType = T::EntryType;
#[inline]
fn get_links(data: &Self::EntryType) -> &Links<Self::EntryType> {
<T as GetLinks>::get_links(data)
}
}
impl<T: ?Sized> GetLinksWrapped for Arc<T>
where
Arc<T>: GetLinks,
{
type Wrapped = Arc<<Arc<T> as GetLinks>::EntryType>;
}
impl<T: GetLinks + ?Sized> GetLinks for Arc<T> {
type EntryType = T::EntryType;
#[inline]
fn get_links(data: &Self::EntryType) -> &Links<Self::EntryType> {
<T as GetLinks>::get_links(data)
}
}
pub struct List<G: GetLinksWrapped> {
list: RawList<G>,
}
impl<G: GetLinksWrapped> List<G> {
pub const fn new() -> Self {
Self {
list: RawList::new(),
}
}
pub fn iter(&self) -> Iterator<'_, G> {
Iterator::new(self)
}
pub const fn is_empty(&self) -> bool {
self.list.is_empty()
}
pub fn push_back(&mut self, data: G::Wrapped) {
let ptr = data.into_pointer();
if !unsafe { self.list.push_back(ptr) } {
unsafe { G::Wrapped::from_pointer(ptr) };
}
}
pub fn push_front(&mut self, data: G::Wrapped) {
let ptr = data.into_pointer();
if !unsafe { self.list.push_front(ptr) } {
unsafe { G::Wrapped::from_pointer(ptr) };
}
}
pub unsafe fn insert_after(
&mut self,
existing: NonNull<G::EntryType>,
data: G::Wrapped,
) -> bool {
let ptr = data.into_pointer();
let inserted = unsafe { self.list.insert_after(existing, ptr) };
if !inserted {
unsafe { G::Wrapped::from_pointer(ptr) };
}
inserted
}
pub unsafe fn remove(&mut self, data: &G::Wrapped) -> Option<G::Wrapped> {
let entry_ref = Wrapper::as_ref(data);
if unsafe { self.list.remove(entry_ref) } {
Some(unsafe { G::Wrapped::from_pointer(NonNull::from(entry_ref)) })
} else {
None
}
}
pub fn pop_front(&mut self) -> Option<G::Wrapped> {
let front = self.list.pop_front()?;
Some(unsafe { G::Wrapped::from_pointer(front) })
}
pub fn cursor_front(&self) -> Cursor<'_, G> {
Cursor::new(self.list.cursor_front())
}
pub fn cursor_front_mut(&mut self) -> CursorMut<'_, G> {
CursorMut::new(self.list.cursor_front_mut())
}
}
impl<G: GetLinksWrapped> Default for List<G> {
fn default() -> Self {
Self::new()
}
}
impl<G: GetLinksWrapped> Drop for List<G> {
fn drop(&mut self) {
while self.pop_front().is_some() {}
}
}
pub struct Cursor<'a, G: GetLinksWrapped> {
cursor: raw_list::Cursor<'a, G>,
}
impl<'a, G: GetLinksWrapped> Cursor<'a, G> {
const fn new(cursor: raw_list::Cursor<'a, G>) -> Self {
Self { cursor }
}
pub fn current(&self) -> Option<&G::EntryType> {
self.cursor.current()
}
pub fn current_ptr(&self) -> Option<NonNull<G::EntryType>> {
self.cursor.current_ptr()
}
pub fn peek_next(&self) -> Option<&G::EntryType> {
self.cursor.peek_next()
}
pub fn peek_prev(&self) -> Option<&G::EntryType> {
self.cursor.peek_prev()
}
pub fn move_next(&mut self) {
self.cursor.move_next();
}
}
pub struct CursorMut<'a, G: GetLinksWrapped> {
cursor: raw_list::CursorMut<'a, G>,
}
impl<'a, G: GetLinksWrapped> CursorMut<'a, G> {
const fn new(cursor: raw_list::CursorMut<'a, G>) -> Self {
Self { cursor }
}
pub unsafe fn current_mut(&mut self) -> Option<&mut G::EntryType> {
self.cursor.current_mut()
}
pub fn current(&self) -> Option<&G::EntryType> {
self.cursor.current()
}
pub fn current_ptr(&self) -> Option<NonNull<G::EntryType>> {
self.cursor.current_ptr()
}
pub fn insert_after(&mut self, data: G::Wrapped) -> bool {
if let Some(cur) = self.current_ptr() {
let new = data.into_pointer();
return unsafe { self.cursor.list.insert_after(cur, new) };
}
false
}
pub fn remove_current(&mut self) -> Option<G::Wrapped> {
let ptr = self.cursor.remove_current()?;
Some(unsafe { G::Wrapped::from_pointer(ptr) })
}
pub unsafe fn peek_next(&mut self) -> Option<&mut G::EntryType> {
self.cursor.peek_next()
}
pub unsafe fn peek_prev(&mut self) -> Option<&mut G::EntryType> {
self.cursor.peek_prev()
}
pub fn move_next(&mut self) {
self.cursor.move_next();
}
}
pub struct Iterator<'a, G: GetLinksWrapped> {
iter: raw_list::Iterator<'a, G>,
}
impl<'a, G: GetLinksWrapped> Iterator<'a, G> {
fn new(list: &'a List<G>) -> Self {
Self {
iter: list.list.iter(),
}
}
}
impl<'a, G: GetLinksWrapped> iter::Iterator for Iterator<'a, G> {
type Item = &'a G::EntryType;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<G: GetLinksWrapped> iter::DoubleEndedIterator for Iterator<'_, G> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
#[cfg(test)]
mod tests {
use super::{GetLinks, Links, List};
struct Example {
inner: usize,
links: Links<Self>,
}
impl GetLinks for Example {
type EntryType = Self;
fn get_links(obj: &Self) -> &Links<Self> {
&obj.links
}
}
#[track_caller]
fn assert_list_contents(list: &List<Box<Example>>, n: usize) {
let mut count = 0;
for (i, e) in list.iter().enumerate() {
assert_eq!(i + 1, e.inner);
count += 1;
}
assert_eq!(count, n);
let mut count = n;
for e in list.iter().rev() {
assert_eq!(count, e.inner);
count -= 1;
}
assert_eq!(count, 0);
}
#[track_caller]
#[test]
fn test_push_back() {
const MAX: usize = 10;
let mut list = List::<Box<Example>>::new();
for n in 1..=MAX {
list.push_back(Box::new(Example {
inner: n,
links: Links::new(),
}));
}
assert_list_contents(&list, MAX);
}
}