#![doc = include_str!("../README.md")]
#![cfg_attr(feature = "nightly", feature(allocator_api))]
#![cfg_attr(feature = "nightly", feature(box_into_inner))]
use ::allocator_api2::alloc::{Allocator, Global};
use ::allocator_api2::boxed::Box;
use ::std::fmt::Debug;
use ::std::ops::DerefMut;
#[cfg(not(feature = "sync"))]
use ::std::cell::OnceCell;
#[cfg(feature = "sync")]
use ::std::sync::OnceLock as OnceCell;
#[derive(Clone)]
pub struct OnceList<T, A: Allocator = Global> {
head: OnceCell<Box<Cons<T, A>, A>>,
alloc: A,
}
#[derive(Clone)]
struct Cons<T, A: Allocator> {
next: OnceCell<Box<Cons<T, A>, A>>,
val: T,
}
impl<T> OnceList<T, Global> {
pub fn new() -> Self {
Self {
head: OnceCell::new(),
alloc: Global,
}
}
}
impl<T, A: Allocator> OnceList<T, A> {
pub fn new_in(alloc: A) -> Self {
Self {
head: OnceCell::new(),
alloc,
}
}
pub fn len(&self) -> usize {
self.iter().count()
}
pub fn is_empty(&self) -> bool {
self.head.get().is_none()
}
pub fn contains(&self, val: &T) -> bool
where
T: PartialEq,
{
self.iter().any(|v| v == val)
}
pub fn first(&self) -> Option<&T> {
self.head.get().map(|c| &c.val)
}
pub fn first_mut(&mut self) -> Option<&mut T> {
self.head.get_mut().map(|c| &mut c.val)
}
pub fn last(&self) -> Option<&T> {
let mut last_opt = None;
let mut next_cell = &self.head;
while let Some(next_box) = next_cell.get() {
last_opt = Some(&next_box.val);
next_cell = &next_box.next;
}
last_opt
}
pub fn last_mut(&mut self) -> Option<&mut T> {
let mut last_opt = None;
let mut next_cell = &mut self.head;
while let Some(next_box) = next_cell.get_mut() {
let next_cons = Box::deref_mut(next_box);
last_opt = Some(&mut next_cons.val);
next_cell = &mut next_cons.next;
}
last_opt
}
fn last_cell(&self) -> &OnceCell<Box<Cons<T, A>, A>> {
let mut next_cell = &self.head;
while let Some(next_box) = next_cell.get() {
next_cell = &next_box.next;
}
next_cell
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
let mut next_cell = &self.head;
::std::iter::from_fn(move || match next_cell.get() {
Some(c) => {
next_cell = &c.next;
Some(&c.val)
}
None => None,
})
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
struct Iter<'a, T, A: Allocator> {
next_cell: &'a mut OnceCell<Box<Cons<T, A>, A>>,
}
impl<'a, T, A: Allocator> Iterator for Iter<'a, T, A> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let next_box = self.next_cell.get_mut()?;
let next_cons = unsafe { &mut *::std::ptr::from_mut(next_box.as_mut()) };
self.next_cell = &mut next_cons.next;
Some(&mut next_cons.val)
}
}
Iter {
next_cell: &mut self.head,
}
}
pub fn clear(&mut self) {
self.head = OnceCell::new();
}
pub fn allocator(&self) -> &A {
&self.alloc
}
pub fn remove<P>(&mut self, mut pred: P) -> Option<T>
where
P: FnMut(&T) -> bool,
{
let mut next_cell = &mut self.head;
while let Some(next_ref) = next_cell.get() {
if pred(&next_ref.val) {
let next_box = next_cell.take().unwrap();
let mut next_cons = Box::into_inner(next_box);
if let Some(next_next) = next_cons.next.take() {
let _ = next_cell.set(next_next);
}
return Some(next_cons.val);
}
next_cell = &mut next_cell.get_mut().unwrap().next;
}
None
}
}
impl<T: Sized, A: Allocator + Clone> OnceList<T, A> {
pub fn push(&self, val: T) -> &T {
let mut next_cell = &self.head;
let mut boxed_cons = Box::new_in(Cons::new(val), self.alloc.clone());
loop {
match next_cell.set(boxed_cons) {
Ok(()) => {
return &unsafe { next_cell.get().unwrap_unchecked() }.val;
}
Err(new_val_cons) => {
next_cell = &unsafe { next_cell.get().unwrap_unchecked() }.next;
boxed_cons = new_val_cons;
}
}
}
}
pub fn extend<U: IntoIterator<Item = T>>(&self, iter: U) {
let mut last_cell = self.last_cell();
let alloc = self.allocator();
for val in iter {
let _ = last_cell.set(Box::new_in(Cons::new(val), A::clone(alloc)));
last_cell = &unsafe { &last_cell.get().unwrap_unchecked() }.next;
}
}
}
impl<T> Default for OnceList<T, Global> {
fn default() -> Self {
Self::new()
}
}
impl<T: Debug, A: Allocator> Debug for OnceList<T, A> {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T> FromIterator<T> for OnceList<T, Global> {
fn from_iter<U: IntoIterator<Item = T>>(iter: U) -> Self {
let list = Self::new();
let mut last_cell = &list.head;
for val in iter {
let _ = last_cell.set(Box::new(Cons::new(val)));
last_cell = &unsafe { &last_cell.get().unwrap_unchecked() }.next;
}
list
}
}
impl<T, A: Allocator> IntoIterator for OnceList<T, A> {
type Item = T;
type IntoIter = IntoIter<T, A>;
fn into_iter(self) -> Self::IntoIter {
IntoIter(self.head)
}
}
pub struct IntoIter<T, A: Allocator>(OnceCell<Box<Cons<T, A>, A>>);
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let next_cell = self.0.take()?;
let next_cons = Box::into_inner(next_cell);
self.0 = next_cons.next;
Some(next_cons.val)
}
}
impl<T, A: Allocator + Clone> Extend<T> for OnceList<T, A> {
fn extend<U: IntoIterator<Item = T>>(&mut self, iter: U) {
<OnceList<T, A>>::extend(self, iter);
}
}
impl<T, A: Allocator> Cons<T, A> {
fn new(val: T) -> Self {
Self {
next: OnceCell::new(),
val,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let list = OnceList::<i32>::new();
assert!(list.is_empty());
assert_eq!(list.len(), 0);
assert_eq!(list.iter().next(), None);
}
#[test]
fn test_default() {
let list = OnceList::<i32>::default();
assert!(list.is_empty());
assert_eq!(list.len(), 0);
assert_eq!(list.iter().next(), None);
}
#[test]
fn test_push() {
let list = OnceList::new();
let val = list.push(42);
assert_eq!(val, &42);
assert_eq!(list.len(), 1);
assert_eq!(list.clone().into_iter().collect::<Vec<_>>(), vec![42]);
list.push(100);
list.push(3);
assert_eq!(list.len(), 3);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![42, 100, 3]);
}
#[test]
fn test_from_iter() {
let list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
assert_eq!(list.len(), 3);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3]);
}
#[test]
fn test_extend() {
let list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
list.extend([4, 5, 6]);
assert_eq!(list.len(), 6);
assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_clear() {
let mut list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
list.clear();
assert!(list.is_empty());
assert_eq!(list.len(), 0);
assert_eq!(list.iter().next(), None);
}
#[test]
fn test_first_last() {
let empty_list = OnceList::<i32>::new();
assert_eq!(empty_list.first(), None);
assert_eq!(empty_list.last(), None);
let single_list = [42].into_iter().collect::<OnceList<_>>();
assert_eq!(single_list.first(), Some(&42));
assert_eq!(single_list.last(), Some(&42));
let multiple_list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
assert_eq!(multiple_list.first(), Some(&1));
assert_eq!(multiple_list.last(), Some(&3));
}
#[test]
fn test_contains() {
let list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
assert!(list.contains(&1));
assert!(list.contains(&2));
assert!(list.contains(&3));
assert!(!list.contains(&0));
assert!(!list.contains(&4));
let empty_list = OnceList::<i32>::new();
assert!(!empty_list.contains(&1));
}
#[test]
fn test_remove() {
let mut list = [1, 2, 3].into_iter().collect::<OnceList<_>>();
assert_eq!(list.remove(|&v| v == 2), Some(2));
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&1, &3]);
assert_eq!(list.remove(|&v| v == 0), None);
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&1, &3]);
assert_eq!(list.remove(|&v| v == 1), Some(1));
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&3]);
assert_eq!(list.remove(|&v| v == 3), Some(3));
assert!(list.is_empty());
}
}