-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlist.rs
113 lines (98 loc) · 2.79 KB
/
list.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use {
core::{pin::Pin, ptr},
pin_project::unsafe_project,
ergo_pin::ergo_pin,
};
use crate::{gen_iter, PinIterator};
#[unsafe_project]
pub struct List<T> {
head: *mut Node<T>,
}
#[unsafe_project]
pub struct Node<T> {
next: *mut Node<T>,
attached: bool,
value: T,
}
impl<T> List<T> {
pub fn new() -> List<T> {
List {
head: ptr::null_mut(),
}
}
pub fn push(self: Pin<&mut Self>, mut node: Pin<&mut Node<T>>) {
let this = self.project();
node.as_mut().on_attached();
*node.as_mut().project().next = *this.head;
*this.head = node.as_ptr();
}
#[ergo_pin]
pub fn remove(mut self: Pin<&mut Self>, mut to_remove: Pin<&mut Node<T>>) -> bool {
let this = self.as_mut().project();
if *this.head == to_remove.as_mut().as_ptr() {
*this.head = *to_remove.as_mut().project().next;
to_remove.on_detached();
return true;
}
for node in pin!(self.iter_nodes()).iter() {
if node.next == to_remove.as_mut().as_ptr() {
*node.project().next = *to_remove.as_mut().project().next;
to_remove.on_detached();
return true;
}
}
return false;
}
fn iter_nodes<'a>(
self: Pin<&'a mut Self>,
) -> impl PinIterator<Item = Pin<&'a mut Node<T>>> + 'a {
gen_iter! {
let mut node = unsafe { Pin::get_unchecked_mut(self).head };
while node != ptr::null_mut() {
yield unsafe { Pin::new_unchecked(&mut *node) };
node = unsafe { (*node).next };
}
}
}
pub fn iter<'a>(self: Pin<&'a mut Self>) -> impl PinIterator<Item = &'a mut T> + 'a {
#[ergo_pin]
gen_iter! {
for node in pin!(self.iter_nodes()).iter() {
yield node.project().value;
}
}
}
}
impl<T> Node<T> {
pub fn new(value: T) -> Node<T> {
Node {
next: ptr::null_mut(),
attached: false,
value,
}
}
fn as_ptr(self: Pin<&mut Self>) -> *mut Self {
unsafe { Pin::get_unchecked_mut(self) as *mut Self }
}
fn on_attached(self: Pin<&mut Self>) {
let this = self.project();
if *this.attached {
panic!("node attached while still attached to another list");
}
*this.attached = true;
}
fn on_detached(self: Pin<&mut Self>) {
let this = self.project();
if !*this.attached {
panic!("node detached while not attached to a list");
}
*this.attached = false;
}
}
impl<T> Drop for Node<T> {
fn drop(&mut self) {
if self.attached {
panic!("node dropped while attached to a list");
}
}
}