swap_buffer_queue/
buffer.rs

1//! [`Buffer`] definition and simple implementations.
2
3use core::{
4    fmt,
5    iter::FusedIterator,
6    marker::PhantomData,
7    mem::ManuallyDrop,
8    ops::{Deref, DerefMut, Range},
9    ptr,
10};
11
12use crate::queue::Queue;
13
14mod array;
15#[cfg(feature = "alloc")]
16mod vec;
17
18pub use array::ArrayBuffer;
19#[cfg(feature = "alloc")]
20pub use vec::VecBuffer;
21
22/// [`Queue`] buffer. It is used together with [`InsertIntoBuffer`].
23///
24/// # Safety
25/// [`Buffer::clear`] *clears* the inserted range from the buffer
26/// (see [`InsertIntoBuffer::insert_into`]), meaning new values can be inserted.
27pub unsafe trait Buffer: Default {
28    /// The slice type returned by [`slice`](Buffer::slice) method.
29    type Slice<'a>
30    where
31        Self: 'a;
32    /// Returns the buffer's capacity.
33    fn capacity(&self) -> usize;
34    /// Returns a slice of the buffer.
35    ///
36    /// # Safety
37    /// Range **must** have been inserted (see [`InsertIntoBuffer::insert_into`]) before calling
38    /// this method.
39    unsafe fn slice(&mut self, range: Range<usize>) -> Self::Slice<'_>;
40    /// Clears the buffer.
41    ///
42    /// # Safety
43    /// Range **must** have been inserted (see [`InsertIntoBuffer::insert_into`]) before calling
44    /// this method.
45    ///
46    /// Calling this method *clears* the inserted value, meaning new values can be inserted.
47    unsafe fn clear(&mut self, range: Range<usize>);
48}
49
50/// [`Buffer`] value.
51///
52/// # Safety
53/// Range `index..index+value.size()` is considered inserted into the buffer after calling
54/// [`InsertIntoBuffer::insert_into`] (see [`Buffer::slice`]/[`Buffer::clear`])
55pub unsafe trait InsertIntoBuffer<B: Buffer> {
56    /// Returns the size taken by a value in the buffer.
57    fn size(&self) -> usize;
58    /// Inserts the value into the buffer at the given index.
59    ///
60    /// # Safety
61    /// For every call to this method, the inserted range `index..index+self.size()` **must not**
62    /// overlap with a previously inserted one.
63    unsafe fn insert_into(self, buffer: &B, index: usize);
64}
65
66/// [`Buffer`] kind where value are inserted one by one.
67///
68/// # Safety
69/// `index` is considered inserted into the buffer after calling [`CellBuffer::insert`] (see [`Buffer::slice`]/[`Buffer::clear`])
70pub(crate) unsafe trait CellBuffer<T>: Buffer {
71    /// Inserts a value into the buffer at the given index.
72    ///
73    /// # Safety
74    /// For every call to this method, `index` **must not** have previously been inserted.
75    unsafe fn insert(&self, index: usize, value: T);
76}
77
78/// Wrapper to implement [`InsertIntoBuffer`] on iterators.
79pub struct ValueIter<I>(pub I);
80
81/// Extension trait to instantiate [`ValueIter`].
82pub trait IntoValueIter: Sized {
83    /// Iterator type to be wrapped in [`ValueIter`].
84    type Iter;
85    /// Wrap iterator into [`ValueIter`].
86    fn into_value_iter(self) -> ValueIter<Self::Iter>;
87}
88
89impl<I> IntoValueIter for I
90where
91    I: IntoIterator,
92    I::IntoIter: ExactSizeIterator,
93{
94    type Iter = I::IntoIter;
95    fn into_value_iter(self) -> ValueIter<Self::Iter> {
96        ValueIter(self.into_iter())
97    }
98}
99
100// SAFETY: `insert_into` does initialize the slice in the buffer
101unsafe impl<B, I, T> InsertIntoBuffer<B> for ValueIter<I>
102where
103    B: CellBuffer<T>,
104    I: Iterator<Item = T> + ExactSizeIterator,
105{
106    #[inline]
107    fn size(&self) -> usize {
108        self.0.len()
109    }
110
111    #[inline]
112    unsafe fn insert_into(mut self, buffer: &B, index: usize) {
113        // don't loop on iterator, because `ExactSizeIterator` is not a sufficient guarantee
114        // for unsafe code
115        for i in index..(index + self.0.len()) {
116            const ERROR: &str = "iterator exhausted before reaching its exact size";
117            // SAFETY: function contract encompass `CellBuffer::insert` one
118            unsafe { buffer.insert(i, self.0.next().expect(ERROR)) };
119        }
120    }
121}
122
123// SAFETY: `insert_into` does initialize the slice in the buffer
124unsafe impl<B, T, const N: usize> InsertIntoBuffer<B> for [T; N]
125where
126    B: CellBuffer<T>,
127{
128    #[inline]
129    fn size(&self) -> usize {
130        N
131    }
132
133    #[inline]
134    unsafe fn insert_into(self, buffer: &B, index: usize) {
135        for (i, elt) in self.into_iter().enumerate() {
136            // SAFETY: function contract encompass `CellBuffer::insert` one
137            unsafe { buffer.insert(index + i, elt) };
138        }
139    }
140}
141
142/// Resizable [`Buffer`].
143pub trait Resize: Buffer {
144    /// Resizes the buffer.
145    fn resize(&mut self, capacity: usize);
146}
147
148/// [`Buffer`] whose values can be drained from.
149///
150/// # Safety
151/// Calling [`Drain::remove`] remove the value inserted at index `index
152/// (see [`InsertIntoBuffer::insert_into`])
153pub unsafe trait Drain: Buffer {
154    /// Value to be removed from the buffer
155    type Value;
156    /// Removes a value from the buffer at a given index and return it.
157    ///
158    /// # Safety
159    /// A value **must** have been inserted at this index (see [`InsertIntoBuffer::insert_into`])
160    /// before calling this method.
161    unsafe fn remove(&mut self, index: usize) -> Self::Value;
162}
163
164/// [`Buffer`] slice returned by [`Queue::try_dequeue`] (see [`Buffer::Slice`]).
165///
166/// Buffer is released when the slice is dropped, so the other buffer will be dequeued next,
167/// unless [`BufferSlice::requeue`]/[`BufferSlice::into_iter`] is called.
168///
169/// # Examples
170/// ```
171/// # use std::ops::Deref;
172/// # use swap_buffer_queue::Queue;
173/// # use swap_buffer_queue::buffer::VecBuffer;
174/// let queue: Queue<VecBuffer<usize>> = Queue::with_capacity(42);
175/// queue.try_enqueue([0]).unwrap();
176/// queue.try_enqueue([1]).unwrap();
177///
178/// let slice = queue.try_dequeue().unwrap();
179/// assert_eq!(slice.deref(), &[0, 1]);
180/// assert_eq!(slice.into_iter().collect::<Vec<_>>(), vec![0, 1]);
181/// ```
182pub struct BufferSlice<'a, B, N>
183where
184    B: Buffer,
185{
186    queue: &'a Queue<B, N>,
187    buffer_index: usize,
188    range: Range<usize>,
189    slice: B::Slice<'a>,
190}
191
192impl<'a, B, N> BufferSlice<'a, B, N>
193where
194    B: Buffer,
195{
196    #[inline]
197    pub(crate) fn new(
198        queue: &'a Queue<B, N>,
199        buffer_index: usize,
200        range: Range<usize>,
201        slice: B::Slice<'a>,
202    ) -> Self {
203        Self {
204            queue,
205            buffer_index,
206            range,
207            slice,
208        }
209    }
210
211    /// Reinsert the buffer at the beginning queue.
212    ///
213    /// It will thus de dequeued again next.
214    ///
215    /// # Examples
216    /// ```
217    /// # use std::ops::Deref;
218    /// # use swap_buffer_queue::Queue;
219    /// # use swap_buffer_queue::buffer::VecBuffer;
220    /// let queue: Queue<VecBuffer<usize>> = Queue::with_capacity(42);
221    /// queue.try_enqueue([0]).unwrap();
222    /// queue.try_enqueue([1]).unwrap();
223    ///
224    /// let slice = queue.try_dequeue().unwrap();
225    /// assert_eq!(slice.deref(), &[0, 1]);
226    /// slice.requeue();
227    /// let slice = queue.try_dequeue().unwrap();
228    /// assert_eq!(slice.deref(), &[0, 1]);
229    /// ```
230    #[inline]
231    pub fn requeue(self) {
232        let slice = ManuallyDrop::new(self);
233        slice.queue.requeue(slice.buffer_index, slice.range.clone());
234    }
235}
236
237impl<'a, B, N> fmt::Debug for BufferSlice<'a, B, N>
238where
239    B: Buffer,
240    B::Slice<'a>: fmt::Debug,
241{
242    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243        f.debug_tuple("BufferSlice").field(&self.slice).finish()
244    }
245}
246
247impl<'a, B, N> Deref for BufferSlice<'a, B, N>
248where
249    B: Buffer,
250{
251    type Target = B::Slice<'a>;
252
253    #[inline]
254    fn deref(&self) -> &Self::Target {
255        &self.slice
256    }
257}
258
259impl<'a, B, N> DerefMut for BufferSlice<'a, B, N>
260where
261    B: Buffer,
262{
263    #[inline]
264    fn deref_mut(&mut self) -> &mut Self::Target {
265        &mut self.slice
266    }
267}
268
269impl<'a, B, N> Drop for BufferSlice<'a, B, N>
270where
271    B: Buffer,
272{
273    #[inline]
274    fn drop(&mut self) {
275        self.queue.release(self.buffer_index, self.range.clone());
276    }
277}
278
279impl<'a, B, N> IntoIterator for BufferSlice<'a, B, N>
280where
281    B: Buffer + Drain,
282{
283    type Item = B::Value;
284    type IntoIter = BufferIter<'a, B, N>;
285
286    #[inline]
287    fn into_iter(self) -> Self::IntoIter {
288        let slice = ManuallyDrop::new(self);
289        BufferIter {
290            queue: slice.queue,
291            buffer_index: slice.buffer_index,
292            range: slice.range.clone(),
293            _phantom: PhantomData,
294        }
295    }
296}
297
298/// [`Buffer`] iterator returned by [`BufferSlice::into_iter`] (see [`Drain`]).
299///
300/// Buffer is lazily drained, and requeued (see [`BufferSlice::requeue`]) if the iterator is dropped while non exhausted.
301///
302/// # Examples
303/// ```
304/// # use std::ops::Deref;
305/// # use swap_buffer_queue::Queue;
306/// # use swap_buffer_queue::buffer::VecBuffer;
307/// let queue: Queue<VecBuffer<usize>> = Queue::with_capacity(42);
308/// queue.try_enqueue([0]).unwrap();
309/// queue.try_enqueue([1]).unwrap();
310///
311/// let mut iter = queue.try_dequeue().unwrap().into_iter();
312/// assert_eq!(iter.next(), Some(0));
313/// drop(iter);
314/// let mut iter = queue.try_dequeue().unwrap().into_iter();
315/// assert_eq!(iter.next(), Some(1));
316/// assert_eq!(iter.next(), None);
317/// ```
318pub struct OwnedBufferIter<Q, B, N>
319where
320    Q: AsRef<Queue<B, N>>,
321    B: Buffer,
322{
323    queue: Q,
324    buffer_index: usize,
325    range: Range<usize>,
326    _phantom: PhantomData<Queue<B, N>>,
327}
328
329/// Alias of [`OwnedBufferIter`] with a queue reference.
330pub type BufferIter<'a, B, N> = OwnedBufferIter<&'a Queue<B, N>, B, N>;
331
332impl<'a, B, N> BufferIter<'a, B, N>
333where
334    B: Buffer,
335{
336    /// Convert back a buffer iterator into a buffer slice.
337    ///
338    /// # Examples
339    /// ```
340    /// # use std::ops::Deref;
341    /// # use std::sync::Arc;
342    /// # use swap_buffer_queue::Queue;
343    /// # use swap_buffer_queue::buffer::VecBuffer;
344    /// let queue: Arc<Queue<VecBuffer<usize>>> = Arc::new(Queue::with_capacity(42));
345    /// queue.try_enqueue([0]).unwrap();
346    /// queue.try_enqueue([1]).unwrap();
347    ///
348    /// let iter = queue.try_dequeue().unwrap().into_iter();
349    /// let slice = iter.into_slice();
350    /// assert_eq!(slice.deref(), &[0, 1]);
351    /// ```
352    #[inline]
353    pub fn into_slice(self) -> BufferSlice<'a, B, N> {
354        let iter = ManuallyDrop::new(self);
355        BufferSlice {
356            queue: iter.queue,
357            buffer_index: iter.buffer_index,
358            range: iter.range.clone(),
359            slice: iter.queue.get_slice(iter.buffer_index, iter.range.clone()),
360        }
361    }
362}
363
364impl<Q, B, N> OwnedBufferIter<Q, B, N>
365where
366    Q: AsRef<Queue<B, N>>,
367    B: Buffer,
368{
369    /// Returns a "owned" version of the buffer iterator using a "owned" version of the queue.
370    ///
371    /// # Examples
372    /// ```
373    /// # use std::ops::Deref;
374    /// # use std::sync::Arc;
375    /// # use swap_buffer_queue::Queue;
376    /// # use swap_buffer_queue::buffer::VecBuffer;
377    /// let queue: Arc<Queue<VecBuffer<usize>>> = Arc::new(Queue::with_capacity(42));
378    /// queue.try_enqueue([0]).unwrap();
379    /// queue.try_enqueue([1]).unwrap();
380    ///
381    /// let mut iter = queue
382    ///     .try_dequeue()
383    ///     .unwrap()
384    ///     .into_iter()
385    ///     .with_owned(queue.clone());
386    /// drop(queue); // iter is "owned", queue can be dropped
387    /// assert_eq!(iter.next(), Some(0));
388    /// assert_eq!(iter.next(), Some(1));
389    /// assert_eq!(iter.next(), None);
390    /// ```
391    #[inline]
392    pub fn with_owned<O>(self, queue: O) -> OwnedBufferIter<O, B, N>
393    where
394        O: AsRef<Queue<B, N>>,
395    {
396        let iter = ManuallyDrop::new(self);
397        assert!(
398            ptr::eq(iter.queue.as_ref(), queue.as_ref()),
399            "new owner must reference the queue referenced by the iterator"
400        );
401        OwnedBufferIter {
402            queue,
403            buffer_index: iter.buffer_index,
404            range: iter.range.clone(),
405            _phantom: PhantomData,
406        }
407    }
408}
409
410impl<Q, B, N> fmt::Debug for OwnedBufferIter<Q, B, N>
411where
412    Q: AsRef<Queue<B, N>>,
413    B: Buffer,
414{
415    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
416        f.debug_tuple("BufferIter").field(&self.range).finish()
417    }
418}
419
420impl<Q, B, N> Drop for OwnedBufferIter<Q, B, N>
421where
422    Q: AsRef<Queue<B, N>>,
423    B: Buffer,
424{
425    #[inline]
426    fn drop(&mut self) {
427        self.queue
428            .as_ref()
429            .requeue(self.buffer_index, self.range.clone());
430    }
431}
432
433impl<Q, B, N> Iterator for OwnedBufferIter<Q, B, N>
434where
435    Q: AsRef<Queue<B, N>>,
436    B: Buffer + Drain,
437{
438    type Item = B::Value;
439
440    #[inline]
441    fn next(&mut self) -> Option<Self::Item> {
442        if self.range.is_empty() {
443            return None;
444        }
445        let value = self
446            .queue
447            .as_ref()
448            .remove(self.buffer_index, self.range.start);
449        self.range.start += 1;
450        Some(value)
451    }
452
453    #[inline]
454    fn size_hint(&self) -> (usize, Option<usize>) {
455        self.range.size_hint()
456    }
457}
458
459impl<Q, B, N> ExactSizeIterator for OwnedBufferIter<Q, B, N>
460where
461    Q: AsRef<Queue<B, N>>,
462    B: Buffer + Drain,
463{
464}
465
466impl<Q, B, N> FusedIterator for OwnedBufferIter<Q, B, N>
467where
468    Q: AsRef<Queue<B, N>>,
469    B: Buffer + Drain,
470{
471}