1use std::{cell::UnsafeCell, time::Duration};
8
9pub enum DeltaList<T> {
19 Cons(Box<UnsafeCell<(Duration, T, DeltaList<T>)>>),
20 Nil,
21}
22
23impl<T> DeltaList<T> {
24 pub fn insert(&mut self, delta: Duration, data: T) {
30 insert_delta(self, delta, data);
31 }
32
33 pub fn front(&self) -> Option<(&Duration, &T)> {
34 if let DeltaList::Cons(e) = self {
35 let elm = unsafe { &(*e.get()) };
36 Some((&elm.0, &elm.1))
37 } else {
38 None
39 }
40 }
41
42 pub fn front_mut(&mut self) -> Option<(&mut Duration, &mut T)> {
43 if let DeltaList::Cons(e) = self {
44 let elm = e.get_mut();
45 Some((&mut elm.0, &mut elm.1))
46 } else {
47 None
48 }
49 }
50
51 pub fn pop(&mut self) -> Option<Self> {
52 if let DeltaList::Cons(e) = self {
53 let next = std::mem::replace(&mut e.get_mut().2, DeltaList::Nil);
54 let head = std::mem::replace(self, next);
55 Some(head)
56 } else {
57 None
58 }
59 }
60
61 pub fn is_empty(&self) -> bool {
62 matches!(self, DeltaList::Nil)
63 }
64
65 pub fn filter<U>(&mut self, f: U)
66 where
67 U: Fn(&T) -> bool,
68 {
69 filter_delta(self, f);
70 }
71}
72
73fn insert_delta<T>(mut list: &mut DeltaList<T>, mut delta: Duration, data: T) {
74 loop {
75 match list {
76 DeltaList::Nil => {
77 *list = DeltaList::Cons(Box::new(UnsafeCell::new((delta, data, DeltaList::Nil))));
78 return;
79 }
80 DeltaList::Cons(e) => {
81 let front = e.get();
82 let d_mut = unsafe { &mut (*front).0 };
83 if delta < *d_mut {
84 *d_mut -= delta;
85 let next = std::mem::replace(list, DeltaList::Nil);
86 *list = DeltaList::Cons(Box::new(UnsafeCell::new((delta, data, next))));
87 return;
88 } else {
89 delta -= *d_mut;
90 list = unsafe { &mut (*front).2 };
91 }
92 }
93 }
94 }
95}
96
97fn filter_delta<T, U>(mut list: &mut DeltaList<T>, f: U)
98where
99 U: Fn(&T) -> bool,
100{
101 loop {
102 match list {
103 DeltaList::Nil => {
104 return;
105 }
106 DeltaList::Cons(e) => {
107 let front = e.get();
108 let d_mut = unsafe { &mut (*front).1 };
109 if f(d_mut) {
110 list = unsafe { &mut (*front).2 };
111 } else {
112 let next = unsafe { &mut (*front).2 };
113 let next = std::mem::replace(next, DeltaList::Nil);
114 *list = next;
115 }
116 }
117 }
118 }
119}