indicator/gat/tumbling_operator/queue/
mod.rs

1use core::ops::{Deref, DerefMut, Index, IndexMut};
2
3/// Circular Queue.
4pub mod circular;
5
6/// Collection.
7pub trait Collection {
8    /// Create a new queue with the given capacity.
9    fn with_capacity(cap: usize) -> Self;
10}
11
12/// Queue.
13pub trait Queue {
14    /// Item.
15    type Item;
16
17    /// Enque.
18    fn enque(&mut self, item: Self::Item);
19
20    /// Deque.
21    fn deque(&mut self) -> Option<Self::Item>;
22
23    /// Length.
24    fn len(&self) -> usize;
25
26    /// Capacity.
27    fn cap(&self) -> usize;
28
29    /// Get a reference of the item in the given position (tail position is `0`).
30    fn get(&self, idx: usize) -> Option<&Self::Item>;
31
32    /// Get a mutable reference of the item in the given position (tail position is `0`).
33    fn get_mut(&mut self, idx: usize) -> Option<&mut Self::Item>;
34
35    /// Is empty.
36    #[inline]
37    fn is_empty(&self) -> bool {
38        self.len() == 0
39    }
40
41    /// Is full.
42    #[inline]
43    fn is_full(&self) -> bool {
44        self.len() == self.cap()
45    }
46
47    /// Returns whether elements are on stack.
48    fn is_inline(&self) -> bool;
49
50    /// Enque an item and deque the oldest item if overflow.
51    #[inline]
52    fn enque_and_deque_overflow(&mut self, item: Self::Item) -> Option<Self::Item> {
53        if self.is_full() {
54            let oldest = self.deque();
55            self.enque(item);
56            oldest
57        } else {
58            self.enque(item);
59            None
60        }
61    }
62}
63
64/// A change to the queue.
65#[derive(Debug, Clone, Copy)]
66pub enum Change<T> {
67    /// Enqued.
68    Push(Option<T>),
69    /// The latest value has been updated.
70    Swap(Option<T>),
71}
72
73impl<T> Change<T> {
74    /// As ref.
75    pub fn as_ref(&self) -> Change<&T> {
76        match self {
77            Self::Push(v) => Change::Push(v.as_ref()),
78            Self::Swap(v) => Change::Swap(v.as_ref()),
79        }
80    }
81
82    /// Convert into outdated.
83    pub fn outdated(self) -> Option<T> {
84        match self {
85            Self::Push(v) => v,
86            Self::Swap(v) => v,
87        }
88    }
89
90    /// Check if it is a new peirod change (push).
91    pub fn is_new_period(&self) -> bool {
92        matches!(self, Self::Push(_))
93    }
94
95    fn as_push(&self) -> Option<&T> {
96        if let Self::Push(v) = self {
97            v.as_ref()
98        } else {
99            None
100        }
101    }
102
103    fn as_swap(&self) -> Option<&T> {
104        if let Self::Swap(v) = self {
105            v.as_ref()
106        } else {
107            None
108        }
109    }
110}
111
112/// The core tumbling queue.
113#[derive(Debug, Clone)]
114pub struct Tumbling<Q: Queue>(Q, Change<Q::Item>);
115
116impl<Q> Tumbling<Q>
117where
118    Q: Queue,
119{
120    pub(crate) fn new(queue: Q) -> Self {
121        Self(queue, Change::Push(None))
122    }
123
124    /// Convert to a view of the queue.
125    pub fn as_view<'a>(&'a self) -> View<'a, dyn Queue<Item = Q::Item> + 'a> {
126        View {
127            queue: &self.0,
128            change: &self.1,
129        }
130    }
131
132    /// Convert to a [`QueueRef`].
133    pub fn as_queue_ref(&self) -> QueueRef<'_, Q::Item> {
134        QueueRef(self.as_view())
135    }
136
137    /// Convert to a mutable view of the queue.
138    pub fn as_view_mut<'a>(&'a mut self) -> ViewMut<'a, dyn Queue<Item = Q::Item> + 'a> {
139        ViewMut {
140            queue: &mut self.0,
141            change: &mut self.1,
142        }
143    }
144
145    /// Convert to a [`QueueMut`].
146    pub fn as_queue_mut(&mut self) -> QueueMut<'_, Q::Item> {
147        QueueMut(self.as_view_mut())
148    }
149}
150
151impl<Q> Deref for Tumbling<Q>
152where
153    Q: Queue,
154{
155    type Target = Q;
156
157    fn deref(&self) -> &Self::Target {
158        &self.0
159    }
160}
161
162/// A view of the tumbling queue.
163pub struct View<'a, Q: Queue + ?Sized> {
164    queue: &'a Q,
165    change: &'a Change<Q::Item>,
166}
167
168impl<'a, Q: Queue + ?Sized> Clone for View<'a, Q> {
169    fn clone(&self) -> Self {
170        *self
171    }
172}
173
174impl<'a, Q: Queue + ?Sized> Copy for View<'a, Q> {}
175
176impl<'a, Q: Queue + ?Sized> View<'a, Q> {
177    /// Change.
178    #[inline]
179    pub fn change(&self) -> Change<&Q::Item> {
180        self.change.as_ref()
181    }
182}
183
184impl<'a, Q> Deref for View<'a, Q>
185where
186    Q: Queue + ?Sized,
187{
188    type Target = Q;
189
190    fn deref(&self) -> &Self::Target {
191        self.queue
192    }
193}
194
195impl<'a, Q> Index<usize> for View<'a, Q>
196where
197    Q: Queue + ?Sized,
198{
199    type Output = Q::Item;
200
201    #[inline]
202    fn index(&self, index: usize) -> &Self::Output {
203        self.queue.get(index).expect("index out of range")
204    }
205}
206
207/// A reference of the tumbling queue.
208pub struct QueueRef<'a, T>(View<'a, dyn Queue<Item = T> + 'a>);
209
210impl<'a, T> Clone for QueueRef<'a, T> {
211    fn clone(&self) -> Self {
212        *self
213    }
214}
215
216impl<'a, T> Copy for QueueRef<'a, T> {}
217
218impl<'a, T> Deref for QueueRef<'a, T> {
219    type Target = View<'a, dyn Queue<Item = T> + 'a>;
220
221    fn deref(&self) -> &Self::Target {
222        &self.0
223    }
224}
225
226/// A mutable view of the tumbling queue.
227pub struct ViewMut<'a, Q: Queue + ?Sized> {
228    queue: &'a mut Q,
229    change: &'a mut Change<Q::Item>,
230}
231
232impl<'a, Q: Queue + ?Sized> ViewMut<'a, Q> {
233    /// Push.
234    #[inline]
235    pub fn push(&mut self, item: Q::Item) -> Option<&Q::Item> {
236        *self.change = Change::Push(self.queue.enque_and_deque_overflow(item));
237        self.change.as_push()
238    }
239
240    /// Swap.
241    #[inline]
242    pub fn swap(&mut self, mut item: Q::Item) -> Option<&Q::Item> {
243        if let Some(head) = self.queue.get_mut(0) {
244            core::mem::swap(head, &mut item);
245        }
246        *self.change = Change::Swap(Some(item));
247        self.change.as_swap()
248    }
249
250    /// Change.
251    #[inline]
252    pub fn change(&self) -> Change<&Q::Item> {
253        self.change.as_ref()
254    }
255}
256
257impl<'a, Q> Deref for ViewMut<'a, Q>
258where
259    Q: Queue + ?Sized,
260{
261    type Target = Q;
262
263    fn deref(&self) -> &Self::Target {
264        self.queue
265    }
266}
267
268impl<'a, Q> DerefMut for ViewMut<'a, Q>
269where
270    Q: Queue + ?Sized,
271{
272    fn deref_mut(&mut self) -> &mut Self::Target {
273        self.queue
274    }
275}
276
277impl<'a, Q> Index<usize> for ViewMut<'a, Q>
278where
279    Q: Queue + ?Sized,
280{
281    type Output = Q::Item;
282
283    #[inline]
284    fn index(&self, index: usize) -> &Self::Output {
285        self.queue.get(index).expect("index out of range")
286    }
287}
288
289impl<'a, Q> IndexMut<usize> for ViewMut<'a, Q>
290where
291    Q: Queue,
292{
293    #[inline]
294    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
295        self.queue.get_mut(index).expect("index out of range")
296    }
297}
298
299/// A mutable reference of the tumbling queue.
300pub struct QueueMut<'a, T>(ViewMut<'a, dyn Queue<Item = T> + 'a>);
301
302impl<'a, T> QueueMut<'a, T> {
303    /// As a [`QueueRef`]
304    pub fn as_queue_ref(&self) -> QueueRef<T> {
305        QueueRef(View {
306            queue: self.queue,
307            change: self.change,
308        })
309    }
310
311    /// Convert into a [`QueueRef`]
312    pub fn into_queue_ref(self) -> QueueRef<'a, T> {
313        QueueRef(View {
314            queue: self.0.queue,
315            change: self.0.change,
316        })
317    }
318}
319
320impl<'a, T> Deref for QueueMut<'a, T> {
321    type Target = ViewMut<'a, dyn Queue<Item = T> + 'a>;
322
323    fn deref(&self) -> &Self::Target {
324        &self.0
325    }
326}
327
328impl<'a, T> DerefMut for QueueMut<'a, T> {
329    fn deref_mut(&mut self) -> &mut Self::Target {
330        &mut self.0
331    }
332}