1use core::{
2 marker::PhantomData,
3 ptr::NonNull,
4};
5
6use sp_std::{
7 boxed::Box,
8 fmt,
9};
10
11use alloc::string::{
12 String,
13 ToString,
14};
15
16#[derive(Debug)]
19pub struct DLL<T> {
20 pub next: Option<NonNull<DLL<T>>>,
21 pub prev: Option<NonNull<DLL<T>>>,
22 pub elem: T,
23}
24
25pub struct Iter<'a, T> {
29 next: Option<NonNull<DLL<T>>>,
30 this: Option<NonNull<DLL<T>>>,
31 marker: PhantomData<&'a mut DLL<T>>,
32}
33
34impl<'a, T> Iter<'a, T> {
35 #[inline]
37 pub fn is_last(&self) -> bool { self.next.is_none() }
38
39 #[inline]
41 pub fn this(&self) -> Option<NonNull<DLL<T>>> { self.this }
42}
43
44impl<'a, T> Iterator for Iter<'a, T> {
45 type Item = &'a mut T;
46
47 #[inline]
48 fn next(&mut self) -> Option<Self::Item> {
49 self.this = self.next;
50 self.next.map(|node| {
51 let deref = unsafe { &mut *node.as_ptr() };
52 self.next = deref.next;
53 &mut deref.elem
54 })
55 }
56}
57
58impl<T> DLL<T> {
59 #[inline]
61 pub fn singleton(elem: T) -> Self { DLL { next: None, prev: None, elem } }
62
63 #[inline]
65 pub fn is_singleton(dll: Option<NonNull<Self>>) -> bool {
66 dll.map_or(false, |dll| unsafe {
67 let dll = &*dll.as_ptr();
68 dll.prev.is_none() && dll.next.is_none()
69 })
70 }
71
72 pub fn add_after(&mut self, elem: T) {
74 let new_next = NonNull::new(Box::into_raw(Box::new(DLL {
75 next: self.next,
76 prev: NonNull::new(self),
77 elem,
78 })));
79 self.next.map_or((), |ptr| unsafe { (*ptr.as_ptr()).prev = new_next });
80 self.next = new_next;
81 }
82
83 pub fn add_before(&mut self, elem: T) {
85 let new_prev = NonNull::new(Box::into_raw(Box::new(DLL {
86 next: NonNull::new(self),
87 prev: self.prev,
88 elem,
89 })));
90 self.prev.map_or((), |ptr| unsafe { (*ptr.as_ptr()).next = new_prev });
91 self.prev = new_prev;
92 }
93
94 pub fn merge(&mut self, node: NonNull<Self>) {
97 unsafe {
98 (*node.as_ptr()).prev = self.prev;
99 (*node.as_ptr()).next = NonNull::new(self);
100 self.prev.map_or((), |ptr| (*ptr.as_ptr()).next = Some(node));
101 self.prev = Some(node);
102 }
103 }
104
105 pub fn unlink_node(&self) -> Option<NonNull<Self>> {
108 unsafe {
109 let next = self.next;
110 let prev = self.prev;
111 if let Some(next) = next {
112 (*next.as_ptr()).prev = prev;
113 };
114 if let Some(prev) = prev {
115 (*prev.as_ptr()).next = next;
116 }
117 (prev).or(next)
118 }
119 }
120
121 pub fn first(mut node: NonNull<Self>) -> NonNull<Self> {
123 loop {
124 let prev = unsafe { (*node.as_ptr()).prev };
125 match prev {
126 None => break,
127 Some(ptr) => node = ptr,
128 }
129 }
130 node
131 }
132
133 pub fn last(mut node: NonNull<Self>) -> NonNull<Self> {
135 loop {
136 let next = unsafe { (*node.as_ptr()).next };
137 match next {
138 None => break,
139 Some(ptr) => node = ptr,
140 }
141 }
142 node
143 }
144
145 pub fn concat(dll: NonNull<Self>, rest: Option<NonNull<Self>>) {
147 let last = DLL::last(dll);
148 let first = rest.map(DLL::first);
149 unsafe {
150 (*last.as_ptr()).next = first;
151 }
152 first.map_or((), |first| unsafe {
153 (*first.as_ptr()).prev = Some(last);
154 });
155 }
156
157 #[inline]
159 pub fn iter_option<'a>(dll: Option<NonNull<Self>>) -> Iter<'a, T> {
160 Iter { next: dll.map(DLL::first), this: None, marker: PhantomData }
161 }
162
163 #[inline]
165 pub fn iter_mut(&mut self) -> Iter<'_, T> {
166 let link: NonNull<Self> = NonNull::from(self);
167 Iter { next: Some(DLL::first(link)), this: None, marker: PhantomData }
168 }
169
170 #[inline]
172 pub fn iter(&self) -> Iter<'_, T> {
173 let link: NonNull<Self> = NonNull::from(self);
174 Iter { next: Some(DLL::first(link)), this: None, marker: PhantomData }
175 }
176}
177
178impl<T: fmt::Display> fmt::Display for DLL<T> {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 let mut iter = self.iter();
181 let head = &iter.next().map_or(String::from(""), |head| head.to_string());
182 let mut msg = String::from("[ ") + head;
183 for val in iter {
184 msg = msg + " <-> " + &val.to_string();
185 }
186 write!(f, "{}", msg + " ]")
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193 use core::ptr::NonNull;
194
195 #[test]
196 pub fn dll() {
197 unsafe {
198 let dll = NonNull::new_unchecked(Box::leak(Box::new(DLL::singleton(3))));
199 let node = &mut *dll.as_ptr();
201 node.add_after(6);
202 node.add_after(5);
203 node.add_after(4);
204 node.add_before(0);
205 node.add_before(1);
206 node.add_before(2);
207 assert_eq!(node.to_string(), "[ 0 <-> 1 <-> 2 <-> 3 <-> 4 <-> 5 <-> 6 ]");
208 let dll = match DLL::unlink_node(dll.as_ref()) {
210 Some(dll) => dll,
211 None => return (),
212 };
213 assert_eq!(
214 (*dll.as_ptr()).to_string(),
215 "[ 0 <-> 1 <-> 2 <-> 4 <-> 5 <-> 6 ]"
216 );
217 let dll = match DLL::unlink_node(dll.as_ref()) {
218 Some(dll) => dll,
219 None => return (),
220 };
221 assert_eq!((*dll.as_ptr()).to_string(), "[ 0 <-> 1 <-> 4 <-> 5 <-> 6 ]");
222 let dll = match DLL::unlink_node(dll.as_ref()) {
223 Some(dll) => dll,
224 None => return (),
225 };
226 let node = &mut *dll.as_ptr();
227 let mut iter = node.iter();
228 assert_eq!(iter.next(), Some(&mut 0));
229 assert_eq!(iter.next(), Some(&mut 4));
230 if let Some(dll) = iter.this() {
231 let node = &*dll.as_ptr();
232 assert_eq!(node.elem, 4);
233 }
234 }
235 }
236}