1#![allow(rustdoc::redundant_explicit_links)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![cfg_attr(docsrs, allow(unused_attributes))]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6extern crate alloc;
95#[cfg(any(feature = "std", test))]
96extern crate std;
97
98use core::fmt;
99use core::marker::PhantomData;
100use core::mem;
101use core::ptr::{self, null};
102use pointers::Pointer;
103
104pub unsafe trait SListItem<Tag>: Sized {
114 fn get_node(&self) -> &mut SListNode<Self, Tag>;
115}
116
117#[repr(C)]
120pub struct SListNode<T: Sized, Tag> {
121 next: *const T,
122 _phan: PhantomData<fn(&Tag)>,
123}
124
125unsafe impl<T, Tag> Send for SListNode<T, Tag> {}
126
127impl<T: SListItem<Tag>, Tag> SListNode<T, Tag> {}
128
129impl<T, Tag> Default for SListNode<T, Tag> {
130 #[inline(always)]
131 fn default() -> Self {
132 Self { next: null(), _phan: Default::default() }
133 }
134}
135
136impl<T: SListItem<Tag> + fmt::Debug, Tag> fmt::Debug for SListNode<T, Tag> {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 write!(f, "(")?;
139 if !self.next.is_null() {
140 write!(f, "next: {:p} ", self.next)?;
141 } else {
142 write!(f, "next: none ")?;
143 }
144 write!(f, ")")
145 }
146}
147
148#[repr(C)]
152pub struct SLinkedList<P, Tag>
153where
154 P: Pointer,
155 P::Target: SListItem<Tag>,
156{
157 length: usize,
158 head: *const P::Target,
159 tail: *const P::Target,
160 _phan: PhantomData<fn(&Tag)>,
161}
162
163unsafe impl<P, Tag> Send for SLinkedList<P, Tag>
164where
165 P: Pointer,
166 P::Target: SListItem<Tag>,
167{
168}
169
170impl<P: fmt::Debug, Tag> fmt::Debug for SLinkedList<P, Tag>
171where
172 P: Pointer,
173 P::Target: SListItem<Tag>,
174{
175 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
176 write!(f, "{{ length: {} ", self.length)?;
177 if !self.head.is_null() {
178 write!(f, "head: {:?} ", self.head)?;
179 } else {
180 write!(f, "head: none ")?;
181 }
182 if !self.tail.is_null() {
183 write!(f, "tail: {:?} ", self.tail)?;
184 } else {
185 write!(f, "tail: none ")?;
186 }
187 write!(f, "}}")
188 }
189}
190
191impl<P, Tag> SLinkedList<P, Tag>
192where
193 P: Pointer,
194 P::Target: SListItem<Tag>,
195{
196 #[inline(always)]
198 pub fn new() -> Self {
199 SLinkedList { length: 0, head: null(), tail: null(), _phan: Default::default() }
200 }
201
202 #[inline]
204 pub fn clear(&mut self) {
205 while self.pop_front().is_some() {}
209 }
210
211 #[inline(always)]
213 pub fn len(&self) -> usize {
214 self.length
215 }
216
217 #[inline(always)]
219 pub fn is_empty(&self) -> bool {
220 self.length == 0
221 }
222
223 #[inline]
225 pub fn push_back(&mut self, item: P) {
226 let node = item.as_ref().get_node();
227 node.next = null();
228 let ptr = item.into_raw();
229 if !self.tail.is_null() {
230 unsafe {
232 (*self.tail).get_node().next = ptr;
233 }
234 } else {
235 self.head = ptr;
237 }
238 self.tail = ptr;
239 self.length += 1;
240 }
241
242 #[inline]
244 pub fn push_front(&mut self, item: P) {
245 let ptr = item.into_raw();
246 let node = unsafe { (*ptr).get_node() };
247 node.next = self.head;
248 if self.head.is_null() {
249 self.tail = ptr;
251 }
252 self.head = ptr;
253 self.length += 1;
254 }
255
256 pub fn pop_front(&mut self) -> Option<P> {
258 if !self.head.is_null() {
259 let head_ptr = self.head;
260 let node = unsafe { (*head_ptr).get_node() };
261 let next_ptr = node.next;
262
263 self.head = next_ptr;
265
266 if self.head.is_null() {
268 self.tail = null();
269 }
270
271 node.next = null();
273 self.length -= 1;
274
275 Some(unsafe { P::from_raw(head_ptr) })
276 } else {
277 None
278 }
279 }
280
281 #[inline]
283 pub fn get_front(&self) -> Option<&P::Target> {
284 if !self.head.is_null() { unsafe { Some(&(*self.head)) } } else { None }
285 }
286
287 #[inline]
289 pub fn get_back(&self) -> Option<&P::Target> {
290 if !self.tail.is_null() { unsafe { Some(&(*self.tail)) } } else { None }
291 }
292
293 #[inline(always)]
295 pub fn is_front(&self, node: &P::Target) -> bool {
296 if self.head.is_null() { false } else { ptr::eq(self.head, node) }
297 }
298
299 #[inline(always)]
311 pub fn iter<'a>(&'a self) -> SLinkedListIterator<'a, P, Tag> {
312 SLinkedListIterator { list: self, cur: null() }
313 }
314
315 #[inline(always)]
317 pub fn drain<'a>(&'a mut self) -> SLinkedListDrainer<'a, P, Tag> {
318 SLinkedListDrainer { list: self }
319 }
320}
321
322impl<P, Tag> Drop for SLinkedList<P, Tag>
323where
324 P: Pointer,
325 P::Target: SListItem<Tag>,
326{
327 fn drop(&mut self) {
328 if mem::needs_drop::<P>() {
329 self.drain().for_each(drop);
330 }
331 }
332}
333
334pub struct SLinkedListIterator<'a, P, Tag>
335where
336 P: Pointer,
337 P::Target: SListItem<Tag>,
338{
339 list: &'a SLinkedList<P, Tag>,
340 cur: *const P::Target,
341}
342
343unsafe impl<'a, P, Tag> Send for SLinkedListIterator<'a, P, Tag>
344where
345 P: Pointer,
346 P::Target: SListItem<Tag>,
347{
348}
349
350impl<'a, P, Tag> Iterator for SLinkedListIterator<'a, P, Tag>
351where
352 P: Pointer,
353 P::Target: SListItem<Tag>,
354{
355 type Item = &'a P::Target;
356
357 #[inline]
358 fn next(&mut self) -> Option<Self::Item> {
359 if !self.cur.is_null() {
360 let next = unsafe { (*self.cur).get_node().next };
361 if !next.is_null() {
362 self.cur = next;
363 } else {
364 return None;
365 }
366 } else {
367 if !self.list.head.is_null() {
368 self.cur = self.list.head;
369 } else {
370 return None;
371 }
372 }
373 unsafe { Some(&(*self.cur)) }
374 }
375}
376
377pub struct SLinkedListDrainer<'a, P, Tag>
378where
379 P: Pointer,
380 P::Target: SListItem<Tag>,
381{
382 list: &'a mut SLinkedList<P, Tag>,
383}
384
385unsafe impl<'a, P, Tag> Send for SLinkedListDrainer<'a, P, Tag>
386where
387 P: Pointer,
388 P::Target: SListItem<Tag>,
389{
390}
391
392impl<'a, P, Tag> Iterator for SLinkedListDrainer<'a, P, Tag>
393where
394 P: Pointer,
395 P::Target: SListItem<Tag>,
396{
397 type Item = P;
398
399 #[inline]
400 fn next(&mut self) -> Option<P> {
401 self.list.pop_front()
402 }
403}
404
405#[cfg(test)]
406mod tests {
407 use super::*;
408 use alloc::boxed::Box;
409 use std::cell::UnsafeCell;
410 use std::sync::atomic::{AtomicUsize, Ordering};
411
412 pub struct TestTag;
413
414 #[derive(Debug)]
415 pub struct TestNode {
416 pub value: i64,
417 pub node: UnsafeCell<SListNode<Self, TestTag>>,
418 }
419
420 static ACTIVE_NODE_COUNT: AtomicUsize = AtomicUsize::new(0);
421
422 impl Drop for TestNode {
423 fn drop(&mut self) {
424 ACTIVE_NODE_COUNT.fetch_sub(1, Ordering::SeqCst);
425 }
426 }
427
428 unsafe impl Send for TestNode {}
429
430 unsafe impl SListItem<TestTag> for TestNode {
431 fn get_node(&self) -> &mut SListNode<Self, TestTag> {
432 unsafe { &mut *self.node.get() }
433 }
434 }
435
436 fn new_node(v: i64) -> TestNode {
437 ACTIVE_NODE_COUNT.fetch_add(1, Ordering::SeqCst);
438 TestNode { value: v, node: UnsafeCell::new(SListNode::default()) }
439 }
440
441 #[test]
442 fn test_push_back_pop_front_box() {
443 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
444 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
445
446 let node1 = Box::new(new_node(1));
447 l.push_back(node1);
448
449 let node2 = Box::new(new_node(2));
450 l.push_back(node2);
451
452 let node3 = Box::new(new_node(3));
453 l.push_back(node3);
454
455 assert_eq!(3, l.len());
456 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
457
458 let mut iter = l.iter();
460 assert_eq!(iter.next().unwrap().value, 1);
461 assert_eq!(iter.next().unwrap().value, 2);
462 assert_eq!(iter.next().unwrap().value, 3);
463 assert!(iter.next().is_none());
464
465 let n1 = l.pop_front();
467 assert!(n1.is_some());
468 assert_eq!(n1.unwrap().value, 1);
469 assert_eq!(l.len(), 2);
470
471 let n2 = l.pop_front();
472 assert!(n2.is_some());
473 assert_eq!(n2.unwrap().value, 2);
474 assert_eq!(l.len(), 1);
475
476 let n3 = l.pop_front();
477 assert!(n3.is_some());
478 assert_eq!(n3.unwrap().value, 3);
479 assert_eq!(l.len(), 0);
480
481 assert!(l.pop_front().is_none());
482 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
483 }
484
485 #[test]
486 fn test_push_front_box() {
487 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
488 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
489
490 let node1 = Box::new(new_node(1));
491 l.push_front(node1); let node2 = Box::new(new_node(2));
494 l.push_front(node2); let node3 = Box::new(new_node(3));
497 l.push_front(node3); assert_eq!(3, l.len());
500 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
501
502 let mut iter = l.iter();
504 assert_eq!(iter.next().unwrap().value, 3);
505 assert_eq!(iter.next().unwrap().value, 2);
506 assert_eq!(iter.next().unwrap().value, 1);
507 assert!(iter.next().is_none());
508
509 let n1 = l.pop_front();
511 assert!(n1.is_some());
512 assert_eq!(n1.unwrap().value, 3);
513 assert_eq!(l.len(), 2);
514
515 let n2 = l.pop_front();
516 assert!(n2.is_some());
517 assert_eq!(n2.unwrap().value, 2);
518 assert_eq!(l.len(), 1);
519
520 let n3 = l.pop_front();
521 assert!(n3.is_some());
522 assert_eq!(n3.unwrap().value, 1);
523 assert_eq!(l.len(), 0);
524
525 assert!(l.pop_front().is_none());
526 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
527 }
528
529 #[test]
530 fn test_drain() {
531 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
532 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
533
534 l.push_back(Box::new(new_node(10)));
535 l.push_back(Box::new(new_node(20)));
536 l.push_back(Box::new(new_node(30)));
537
538 assert_eq!(l.len(), 3);
539 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
540
541 {
542 let mut drain = l.drain();
543 assert_eq!(drain.next().unwrap().value, 10);
544 assert_eq!(drain.next().unwrap().value, 20);
545 assert_eq!(drain.next().unwrap().value, 30);
546 assert!(drain.next().is_none());
547 }
548
549 assert_eq!(l.len(), 0);
550 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
551 }
552
553 #[test]
554 fn test_clear() {
555 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
556 let mut l = SLinkedList::<Box<TestNode>, TestTag>::new();
557
558 l.push_back(Box::new(new_node(1)));
559 l.push_back(Box::new(new_node(2)));
560 assert_eq!(l.len(), 2);
561 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 2);
562
563 l.clear();
564
565 assert!(l.is_empty());
566 assert_eq!(l.len(), 0);
567 assert!(l.get_front().is_none());
568 assert!(l.get_back().is_none());
569 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
570
571 l.push_back(Box::new(new_node(3)));
573 assert_eq!(l.len(), 1);
574 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 1);
575 }
576}