use super::*;
#[derive(Debug)]
#[pin_project::pin_project]
struct OwnedEntry {
#[pin]
links: Links<OwnedEntry>,
val: i32,
}
unsafe impl Linked<Links<Self>> for OwnedEntry {
type Handle = Pin<Box<OwnedEntry>>;
fn into_ptr(handle: Pin<Box<OwnedEntry>>) -> NonNull<Self> {
unsafe { NonNull::from(Box::leak(Pin::into_inner_unchecked(handle))) }
}
unsafe fn from_ptr(ptr: NonNull<Self>) -> Self::Handle {
Pin::new_unchecked(Box::from_raw(ptr.as_ptr()))
}
unsafe fn links(target: NonNull<Self>) -> NonNull<Links<Self>> {
let links = ptr::addr_of_mut!((*target.as_ptr()).links);
NonNull::new_unchecked(links)
}
}
fn owned_entry(val: i32) -> Pin<Box<OwnedEntry>> {
Box::pin(OwnedEntry {
links: Links::new(),
val,
})
}
#[test]
fn pop_front() {
let _trace = trace_init();
let a = owned_entry(5);
let b = owned_entry(7);
let c = owned_entry(9);
let mut list = List::<OwnedEntry>::new();
list.push_front(a);
list.assert_valid();
list.push_front(b);
list.assert_valid();
list.push_front(c);
list.assert_valid();
let d = list.pop_front().unwrap();
assert_eq!(9, d.val);
let e = list.pop_front().unwrap();
assert_eq!(7, e.val);
let f = list.pop_front().unwrap();
assert_eq!(5, f.val);
assert!(list.is_empty());
assert!(list.pop_front().is_none());
list.assert_valid();
}
#[test]
fn iterate_twice() {
let _trace = trace_init();
let a = owned_entry(1);
let b = owned_entry(2);
let c = owned_entry(3);
let mut list = List::<OwnedEntry>::new();
list.push_back(a);
list.push_back(b);
list.push_back(c);
let mut i = 1;
for entry in list.iter() {
assert_eq!(entry.val, i);
i += 1;
}
let mut i = 1;
for entry in list.iter() {
assert_eq!(entry.val, i);
i += 1;
}
}
#[test]
fn cursor_twice() {
let _trace = trace_init();
let a = owned_entry(1);
let b = owned_entry(2);
let c = owned_entry(3);
let mut list = List::<OwnedEntry>::new();
list.push_back(a);
list.push_back(b);
list.push_back(c);
let mut i = 1;
for entry in list.cursor_front_mut() {
assert_eq!(entry.val, i);
i += 1;
}
let mut i = 1;
for entry in list.cursor_front_mut() {
assert_eq!(entry.val, i);
i += 1;
}
}
#[test]
fn double_ended_iter_mut() {
let a = owned_entry(1);
let b = owned_entry(2);
let c = owned_entry(3);
fn incr_entry(entry: Pin<&mut OwnedEntry>) -> i32 {
let entry = entry.project();
*entry.val += 1;
*entry.val
}
let mut list = List::new();
list.push_back(a);
list.push_back(b);
list.push_back(c);
let head_to_tail = list.iter_mut().map(incr_entry).collect::<Vec<_>>();
assert_eq!(&head_to_tail, &[2, 3, 4]);
let tail_to_head = list.iter_mut().rev().map(incr_entry).collect::<Vec<_>>();
assert_eq!(&tail_to_head, &[5, 4, 3]);
}
#[test]
fn double_ended_iter_mut_empties() {
let a = owned_entry(1);
let b = owned_entry(2);
let c = owned_entry(3);
let d = owned_entry(4);
let mut list = List::<OwnedEntry>::new();
list.push_back(a);
list.push_back(b);
list.push_back(c);
list.push_back(d);
let mut iter = list.iter_mut();
assert_eq!(iter.next().map(|entry| entry.val), Some(1));
assert_eq!(iter.next().map(|entry| entry.val), Some(2));
assert_eq!(iter.next_back().map(|entry| entry.val), Some(4));
assert_eq!(iter.next_back().map(|entry| entry.val), Some(3));
assert_eq!(iter.next().map(|entry| entry.val), None);
assert_eq!(iter.next_back().map(|entry| entry.val), None);
}
#[test]
fn drain_filter() {
let mut list = List::new();
list.push_back(owned_entry(1));
list.push_back(owned_entry(2));
list.push_back(owned_entry(3));
list.push_back(owned_entry(4));
{
let mut df = list.drain_filter(|entry: &OwnedEntry| entry.val % 2 == 0);
assert_eq!(df.next().map(|entry| entry.val), Some(2));
assert_eq!(df.next().map(|entry| entry.val), Some(4));
assert_eq!(df.next().map(|entry| entry.val), None);
}
let remaining = list.iter().map(|entry| entry.val).collect::<Vec<_>>();
assert_eq!(remaining, vec![1, 3]);
}