1use alloc::boxed::Box;
124use core::marker::PhantomData;
125use core::ptr::NonNull;
126
127pub trait SListItemOwned<Tag>: Sized {
139 fn get_node(&mut self) -> &mut Option<NonNull<Self>>;
141
142 fn append(&mut self, mut l: SLinkedListOwned<Self, Tag>) {
146 let node = self.get_node();
147 assert!(node.is_none(), "can only append to a tail node");
148
149 *node = l.head.take();
150
151 l.length = 0;
154 l.tail = None;
155 }
156
157 fn pop(&mut self) -> Option<Box<Self>> {
161 let node = self.get_node();
162 if let Some(next_ptr) = node {
163 let mut popped_box: Box<Self> = unsafe { Box::from_raw(next_ptr.as_ptr()) };
164 *node = popped_box.get_node().take(); Some(popped_box)
166 } else {
167 None
168 }
169 }
170
171 fn consume_all(&mut self) {
173 let mut current = self.get_node().take();
174 while let Some(node_ptr) = current {
175 let mut node_box: Box<Self> = unsafe { Box::from_raw(node_ptr.as_ptr()) };
176 current = node_box.get_node().take();
177 }
179 }
180}
181
182#[repr(C)]
187pub struct SLinkedListOwned<T, Tag>
188where
189 T: SListItemOwned<Tag>,
190{
191 length: usize,
192 head: Option<NonNull<T>>,
193 tail: Option<NonNull<T>>,
194 _phan: PhantomData<fn(&Tag)>,
195}
196
197unsafe impl<T, Tag> Send for SLinkedListOwned<T, Tag> where T: SListItemOwned<Tag> {}
198
199impl<T, Tag> SLinkedListOwned<T, Tag>
200where
201 T: SListItemOwned<Tag>,
202{
203 #[inline(always)]
205 pub const fn new() -> Self {
206 SLinkedListOwned { length: 0, head: None, tail: None, _phan: PhantomData }
207 }
208
209 pub fn clear(&mut self) {
211 while self.pop_front().is_some() {}
212 }
213
214 #[inline(always)]
216 pub fn len(&self) -> usize {
217 self.length
218 }
219
220 #[inline(always)]
222 pub fn is_empty(&self) -> bool {
223 self.length == 0
224 }
225
226 #[inline]
228 pub fn push_front(&mut self, mut item: Box<T>) {
229 debug_assert!(item.get_node().is_none(), "Node is already in a list");
230 *item.get_node() = self.head;
232 let ptr = NonNull::from(Box::leak(item));
233 self.head = Some(ptr); if self.tail.is_none() {
235 self.tail = Some(ptr);
237 }
238 self.length += 1;
239 }
240
241 #[inline]
243 pub fn push_back(&mut self, mut item: Box<T>) {
244 debug_assert!(item.get_node().is_none(), "Node is already in a list");
247 let ptr = NonNull::from(Box::leak(item));
248 let old_tail = self.tail.replace(ptr);
251 match old_tail {
252 Some(mut old_tail_ptr) => {
253 unsafe {
255 *old_tail_ptr.as_mut().get_node() = Some(ptr);
256 }
257 }
258 None => {
259 debug_assert!(self.head.is_none());
260 self.head = Some(ptr);
262 }
263 }
264 self.length += 1;
265 }
266
267 pub fn pop_front(&mut self) -> Option<Box<T>> {
269 if let Some(head_ptr) = self.head {
270 let mut head_box: Box<T> = unsafe { Box::from_raw(head_ptr.as_ptr()) };
271 self.head = *head_box.get_node();
272
273 if self.head.is_none() {
274 self.tail = None;
275 }
276
277 self.length -= 1;
278
279 *head_box.get_node() = None;
280
281 Some(head_box)
282 } else {
283 None
284 }
285 }
286
287 #[inline]
289 pub fn get_front(&self) -> Option<&T> {
290 self.head.map(|ptr| unsafe { ptr.as_ref() })
291 }
292
293 #[inline]
295 pub fn get_front_mut(&mut self) -> Option<&mut T> {
296 self.head.map(|mut ptr| unsafe { ptr.as_mut() })
297 }
298
299 #[inline]
301 pub fn get_back(&self) -> Option<&T> {
302 self.tail.map(|ptr| unsafe { ptr.as_ref() })
303 }
304
305 #[inline]
307 pub fn get_back_mut(&mut self) -> Option<&mut T> {
308 self.tail.map(|mut ptr| unsafe { ptr.as_mut() })
309 }
310
311 #[inline(always)]
313 pub fn is_front(&self, node: &T) -> bool {
314 self.head.is_some_and(|head| core::ptr::eq(head.as_ptr(), node))
315 }
316
317 #[inline(always)]
319 pub fn drain(&mut self) -> SLinkedListOwnedDrainer<'_, T, Tag> {
320 SLinkedListOwnedDrainer { list: self }
321 }
322
323 #[inline(always)]
325 pub fn iter_mut(&mut self) -> SLinkedListOwnedIterMut<'_, T, Tag> {
326 SLinkedListOwnedIterMut { cur: self.head, _phan: PhantomData }
327 }
328}
329
330impl<T, Tag> Default for SLinkedListOwned<T, Tag>
331where
332 T: SListItemOwned<Tag>,
333{
334 fn default() -> Self {
335 Self::new()
336 }
337}
338
339impl<T, Tag> Drop for SLinkedListOwned<T, Tag>
340where
341 T: SListItemOwned<Tag>,
342{
343 fn drop(&mut self) {
344 self.drain().for_each(drop);
346 }
347}
348
349pub struct SLinkedListOwnedDrainer<'a, T, Tag>
351where
352 T: SListItemOwned<Tag>,
353{
354 list: &'a mut SLinkedListOwned<T, Tag>,
355}
356
357impl<'a, T, Tag> Iterator for SLinkedListOwnedDrainer<'a, T, Tag>
358where
359 T: SListItemOwned<Tag>,
360{
361 type Item = Box<T>;
362
363 #[inline]
364 fn next(&mut self) -> Option<Box<T>> {
365 self.list.pop_front()
366 }
367}
368
369pub struct SLinkedListOwnedIterMut<'a, T, Tag>
371where
372 T: SListItemOwned<Tag>,
373{
374 cur: Option<NonNull<T>>,
375 _phan: PhantomData<(&'a mut T, fn(&Tag))>,
376}
377
378impl<'a, T, Tag> Iterator for SLinkedListOwnedIterMut<'a, T, Tag>
379where
380 T: SListItemOwned<Tag> + 'a,
381{
382 type Item = &'a mut T;
383
384 fn next(&mut self) -> Option<Self::Item> {
385 if let Some(mut cur_ptr) = self.cur {
386 let cur_mut = unsafe { cur_ptr.as_mut() };
387 self.cur = *cur_mut.get_node();
388 Some(cur_mut)
389 } else {
390 None
391 }
392 }
393}
394
395#[cfg(test)]
396mod tests {
397 use super::*;
398 use core::sync::atomic::{AtomicUsize, Ordering};
399
400 pub struct TestTag;
401
402 #[derive(Debug)]
403 pub struct TestNode {
404 pub value: i64,
405 pub next: Option<NonNull<TestNode>>,
406 }
407
408 static ACTIVE_NODE_COUNT: AtomicUsize = AtomicUsize::new(0);
409
410 impl Drop for TestNode {
411 fn drop(&mut self) {
412 ACTIVE_NODE_COUNT.fetch_sub(1, Ordering::SeqCst);
413 }
414 }
415
416 impl SListItemOwned<TestTag> for TestNode {
417 fn get_node(&mut self) -> &mut Option<NonNull<Self>> {
418 &mut self.next
419 }
420 }
421
422 fn new_node(v: i64) -> TestNode {
423 ACTIVE_NODE_COUNT.fetch_add(1, Ordering::SeqCst);
424 TestNode { value: v, next: None }
425 }
426
427 #[test]
428 fn test_push_back_pop_front() {
429 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
430 let mut l = SLinkedListOwned::<TestNode, TestTag>::new();
431
432 l.push_back(Box::new(new_node(1)));
433 l.push_back(Box::new(new_node(2)));
434 l.push_back(Box::new(new_node(3)));
435
436 assert_eq!(3, l.len());
437 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
438 assert!(!l.is_empty());
439
440 assert_eq!(l.get_front().unwrap().value, 1);
441 assert_eq!(l.get_back().unwrap().value, 3);
442
443 let n1 = l.pop_front();
444 assert!(n1.is_some());
445 assert_eq!(n1.unwrap().value, 1);
446 assert_eq!(l.len(), 2);
447
448 let n2 = l.pop_front();
449 assert!(n2.is_some());
450 assert_eq!(n2.unwrap().value, 2);
451 assert_eq!(l.len(), 1);
452
453 let n3 = l.pop_front();
454 assert!(n3.is_some());
455 assert_eq!(n3.unwrap().value, 3);
456 assert_eq!(l.len(), 0);
457
458 assert!(l.pop_front().is_none());
459 assert!(l.is_empty());
460 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
461 }
462
463 #[test]
464 fn test_push_front() {
465 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
466 let mut l = SLinkedListOwned::<TestNode, TestTag>::new();
467
468 l.push_front(Box::new(new_node(1))); assert_eq!(l.len(), 1);
470 assert_eq!(l.get_front().unwrap().value, 1);
471 assert_eq!(l.get_back().unwrap().value, 1);
472
473 l.push_front(Box::new(new_node(2))); assert_eq!(l.len(), 2);
475 assert_eq!(l.get_front().unwrap().value, 2);
476 assert_eq!(l.get_back().unwrap().value, 1);
477
478 l.push_front(Box::new(new_node(3))); assert_eq!(l.len(), 3);
480 assert_eq!(l.get_front().unwrap().value, 3);
481 assert_eq!(l.get_back().unwrap().value, 1);
482
483 assert_eq!(l.pop_front().unwrap().value, 3);
485 assert_eq!(l.pop_front().unwrap().value, 2);
486 assert_eq!(l.pop_front().unwrap().value, 1);
487 assert!(l.is_empty());
488 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
489 }
490
491 #[test]
492 fn test_drain() {
493 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
494 let mut l = SLinkedListOwned::<TestNode, TestTag>::new();
495
496 l.push_back(Box::new(new_node(10)));
497 l.push_back(Box::new(new_node(20)));
498 l.push_back(Box::new(new_node(30)));
499
500 assert_eq!(l.len(), 3);
501 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 3);
502
503 {
504 let mut drain = l.drain();
505 assert_eq!(drain.next().unwrap().value, 10);
506 assert_eq!(drain.next().unwrap().value, 20);
507 assert_eq!(drain.next().unwrap().value, 30);
508 assert!(drain.next().is_none());
509 }
510
511 assert_eq!(l.len(), 0);
512 assert!(l.is_empty());
513 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
514 }
515
516 #[test]
517 fn test_iter_mut() {
518 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
519 let mut l = SLinkedListOwned::<TestNode, TestTag>::new();
520
521 l.push_back(Box::new(new_node(100)));
522 l.push_back(Box::new(new_node(200)));
523 l.push_back(Box::new(new_node(300)));
524
525 let mut iter = l.iter_mut();
526 let n1 = iter.next().unwrap();
527 assert_eq!(n1.value, 100);
528 n1.value = 101;
529
530 let n2 = iter.next().unwrap();
531 assert_eq!(n2.value, 200);
532 n2.value = 201;
533
534 let n3 = iter.next().unwrap();
535 assert_eq!(n3.value, 300);
536 n3.value = 301;
537
538 assert!(iter.next().is_none());
539
540 assert_eq!(l.pop_front().unwrap().value, 101);
541 assert_eq!(l.pop_front().unwrap().value, 201);
542 assert_eq!(l.pop_front().unwrap().value, 301);
543
544 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
545 }
546
547 #[test]
548 fn test_clear() {
549 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
550 let mut l = SLinkedListOwned::<TestNode, TestTag>::new();
551
552 l.push_back(Box::new(new_node(1)));
553 l.push_back(Box::new(new_node(2)));
554
555 assert_eq!(l.len(), 2);
556 l.clear();
557 assert!(l.is_empty());
558 assert_eq!(l.len(), 0);
559 assert!(l.get_front().is_none());
560 assert!(l.get_back().is_none());
561 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
562 }
563
564 #[test]
565 fn test_drop() {
566 ACTIVE_NODE_COUNT.store(0, Ordering::SeqCst);
567 {
568 let mut l = SLinkedListOwned::<TestNode, TestTag>::new();
569 l.push_back(Box::new(new_node(1)));
570 l.push_back(Box::new(new_node(2)));
571 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 2);
572 }
573 assert_eq!(ACTIVE_NODE_COUNT.load(Ordering::SeqCst), 0);
574 }
575}