ringbuffer/with_alloc/
alloc_ringbuffer.rs

1use core::ops::{Index, IndexMut};
2
3use crate::ringbuffer_trait::{
4    RingBuffer, RingBufferIntoIterator, RingBufferIterator, RingBufferMutIterator,
5};
6
7extern crate alloc;
8
9// We need boxes, so depend on alloc
10use crate::{impl_ring_buffer_set_len, mask_and, GrowableAllocRingBuffer, SetLen};
11use core::ptr;
12
13/// The `AllocRingBuffer` is a `RingBuffer` which is based on a Vec. This means it allocates at runtime
14/// on the heap, and therefore needs the [`alloc`] crate. This struct and therefore the dependency on
15/// alloc can be disabled by disabling the `alloc` (default) feature.
16///
17/// # Example
18/// ```
19/// use ringbuffer::{AllocRingBuffer, RingBuffer};
20///
21/// let mut buffer = AllocRingBuffer::new(2);
22///
23/// // First entry of the buffer is now 5.
24/// buffer.enqueue(5);
25///
26/// // The last item we enqueued is 5
27/// assert_eq!(buffer.back(), Some(&5));
28///
29/// // Second entry is now 42.
30/// buffer.enqueue(42);
31///
32/// assert_eq!(buffer.peek(), Some(&5));
33/// assert!(buffer.is_full());
34///
35/// // Because capacity is reached the next enqueue will be the first item of the buffer.
36/// buffer.enqueue(1);
37/// assert_eq!(buffer.to_vec(), vec![42, 1]);
38/// ```
39#[derive(Debug)]
40pub struct AllocRingBuffer<T> {
41    pub(crate) buf: *mut T,
42
43    // the size of the allocation. Next power of 2 up from the capacity
44    size: usize,
45    // maximum number of elements actually allowed in the ringbuffer.
46    // Always less than or equal than the size
47    capacity: usize,
48
49    readptr: usize,
50    writeptr: usize,
51}
52
53// SAFETY: all methods that require mutable access take &mut,
54// being send and sync was the old behavior but broke when we switched to *mut T.
55unsafe impl<T: Sync> Sync for AllocRingBuffer<T> {}
56unsafe impl<T: Send> Send for AllocRingBuffer<T> {}
57
58impl<T, const N: usize> From<[T; N]> for AllocRingBuffer<T> {
59    fn from(value: [T; N]) -> Self {
60        let mut rb = Self::new(value.len());
61        rb.extend(value);
62        rb
63    }
64}
65
66impl<T: Clone, const N: usize> From<&[T; N]> for AllocRingBuffer<T> {
67    // the cast here is actually not trivial
68    #[allow(trivial_casts)]
69    fn from(value: &[T; N]) -> Self {
70        Self::from(value as &[T])
71    }
72}
73
74impl<T: Clone> From<&[T]> for AllocRingBuffer<T> {
75    fn from(value: &[T]) -> Self {
76        let mut rb = Self::new(value.len());
77        rb.extend(value.iter().cloned());
78        rb
79    }
80}
81
82impl<T> From<GrowableAllocRingBuffer<T>> for AllocRingBuffer<T> {
83    fn from(mut v: GrowableAllocRingBuffer<T>) -> AllocRingBuffer<T> {
84        let mut rb = AllocRingBuffer::new(v.len());
85        rb.extend(v.drain());
86        rb
87    }
88}
89
90impl<T: Clone> From<&mut [T]> for AllocRingBuffer<T> {
91    fn from(value: &mut [T]) -> Self {
92        Self::from(&*value)
93    }
94}
95
96impl<T: Clone, const CAP: usize> From<&mut [T; CAP]> for AllocRingBuffer<T> {
97    fn from(value: &mut [T; CAP]) -> Self {
98        Self::from(value.clone())
99    }
100}
101
102impl<T> From<alloc::vec::Vec<T>> for AllocRingBuffer<T> {
103    fn from(value: alloc::vec::Vec<T>) -> Self {
104        let mut res = AllocRingBuffer::new(value.len());
105        res.extend(value);
106        res
107    }
108}
109
110impl<T> From<alloc::collections::VecDeque<T>> for AllocRingBuffer<T> {
111    fn from(value: alloc::collections::VecDeque<T>) -> Self {
112        let mut res = AllocRingBuffer::new(value.len());
113        res.extend(value);
114        res
115    }
116}
117
118impl<T> From<alloc::collections::LinkedList<T>> for AllocRingBuffer<T> {
119    fn from(value: alloc::collections::LinkedList<T>) -> Self {
120        let mut res = AllocRingBuffer::new(value.len());
121        res.extend(value);
122        res
123    }
124}
125
126impl From<alloc::string::String> for AllocRingBuffer<char> {
127    fn from(value: alloc::string::String) -> Self {
128        let mut res = AllocRingBuffer::new(value.len());
129        res.extend(value.chars());
130        res
131    }
132}
133
134impl From<&str> for AllocRingBuffer<char> {
135    fn from(value: &str) -> Self {
136        let mut res = AllocRingBuffer::new(value.len());
137        res.extend(value.chars());
138        res
139    }
140}
141
142impl<T, const CAP: usize> From<crate::ConstGenericRingBuffer<T, CAP>> for AllocRingBuffer<T> {
143    fn from(mut value: crate::ConstGenericRingBuffer<T, CAP>) -> Self {
144        let mut res = AllocRingBuffer::new(value.len());
145        res.extend(value.drain());
146        res
147    }
148}
149
150impl<T> Drop for AllocRingBuffer<T> {
151    fn drop(&mut self) {
152        self.drain().for_each(drop);
153
154        let layout = alloc::alloc::Layout::array::<T>(self.size).unwrap();
155        unsafe {
156            alloc::alloc::dealloc(self.buf.cast(), layout);
157        }
158    }
159}
160
161impl<T: Clone> Clone for AllocRingBuffer<T> {
162    fn clone(&self) -> Self {
163        debug_assert_ne!(self.capacity, 0);
164
165        let mut new = Self::new(self.capacity);
166        new.extend(self.iter().cloned());
167        new
168    }
169}
170
171impl<T: PartialEq> PartialEq for AllocRingBuffer<T> {
172    fn eq(&self, other: &Self) -> bool {
173        self.capacity == other.capacity
174            && self.len() == other.len()
175            && self.iter().zip(other.iter()).all(|(a, b)| a == b)
176    }
177}
178
179impl<T: Eq + PartialEq> Eq for AllocRingBuffer<T> {}
180
181impl<T> IntoIterator for AllocRingBuffer<T> {
182    type Item = T;
183    type IntoIter = RingBufferIntoIterator<T, Self>;
184
185    fn into_iter(self) -> Self::IntoIter {
186        RingBufferIntoIterator::new(self)
187    }
188}
189
190#[allow(clippy::into_iter_without_iter)]
191// iter() is implemented on the trait
192impl<'a, T> IntoIterator for &'a AllocRingBuffer<T> {
193    type Item = &'a T;
194    type IntoIter = RingBufferIterator<'a, T, AllocRingBuffer<T>>;
195
196    fn into_iter(self) -> Self::IntoIter {
197        self.iter()
198    }
199}
200
201#[allow(clippy::into_iter_without_iter)]
202// iter_mut() is implemented on the trait
203impl<'a, T> IntoIterator for &'a mut AllocRingBuffer<T> {
204    type Item = &'a mut T;
205    type IntoIter = RingBufferMutIterator<'a, T, AllocRingBuffer<T>>;
206
207    fn into_iter(self) -> Self::IntoIter {
208        self.iter_mut()
209    }
210}
211
212impl<T> Extend<T> for AllocRingBuffer<T> {
213    fn extend<A: IntoIterator<Item = T>>(&mut self, iter: A) {
214        let iter = iter.into_iter();
215
216        for i in iter {
217            let _ = self.enqueue(i);
218        }
219    }
220}
221
222unsafe impl<T> RingBuffer<T> for AllocRingBuffer<T> {
223    #[inline]
224    unsafe fn ptr_capacity(rb: *const Self) -> usize {
225        (*rb).capacity
226    }
227
228    #[inline]
229    unsafe fn ptr_buffer_size(rb: *const Self) -> usize {
230        (*rb).size
231    }
232
233    impl_ringbuffer!(readptr, writeptr);
234
235    #[inline]
236    fn enqueue(&mut self, value: T) -> Option<T> {
237        let mut ret = None;
238
239        if self.is_full() {
240            // mask with and is allowed here because size is always a power of two
241            let previous_value =
242                unsafe { ptr::read(get_unchecked_mut(self, mask_and(self.size, self.readptr))) };
243
244            ret = Some(previous_value);
245            self.readptr += 1;
246        }
247
248        // mask with and is allowed here because size is always a power of two
249        let index = mask_and(self.size, self.writeptr);
250
251        unsafe {
252            ptr::write(get_unchecked_mut(self, index), value);
253        }
254
255        self.writeptr += 1;
256
257        ret
258    }
259
260    fn dequeue(&mut self) -> Option<T> {
261        if self.is_empty() {
262            None
263        } else {
264            // mask with and is allowed here because size is always a power of two
265            let index = mask_and(self.size, self.readptr);
266            let res = unsafe { get_unchecked_mut(self, index) };
267            self.readptr += 1;
268
269            // Safety: the fact that we got this maybeuninit from the buffer (with mask) means that
270            // it's initialized. If it wasn't the is_empty call would have caught it. Values
271            // are always initialized when inserted so this is safe.
272            unsafe { Some(ptr::read(res)) }
273        }
274    }
275
276    impl_ringbuffer_ext!(
277        get_base_ptr,
278        get_base_mut_ptr,
279        get_unchecked,
280        get_unchecked_mut,
281        readptr,
282        writeptr,
283        mask_and
284    );
285
286    #[inline]
287    fn fill_with<F: FnMut() -> T>(&mut self, mut f: F) {
288        self.clear();
289
290        self.readptr = 0;
291        self.writeptr = self.capacity;
292
293        for i in 0..self.capacity {
294            unsafe { ptr::write(get_unchecked_mut(self, i), f()) };
295        }
296    }
297}
298
299impl<T> AllocRingBuffer<T> {
300    /// Creates a `AllocRingBuffer` with a certain capacity. The actual capacity is the input to the
301    /// function raised to the power of two (effectively the input is the log2 of the actual capacity)
302    #[inline]
303    #[must_use]
304    pub fn with_capacity_power_of_2(cap_power_of_two: usize) -> Self {
305        Self::new(1 << cap_power_of_two)
306    }
307
308    #[inline]
309    /// Alias of [`with_capacity`](AllocRingBuffer::new).
310    #[must_use]
311    #[deprecated = "alias of new"]
312    pub fn with_capacity(cap: usize) -> Self {
313        Self::new(cap)
314    }
315
316    /// Creates a `AllocRingBuffer` with a certain capacity. The capacity must not be zero.
317    ///
318    /// # Panics
319    /// Panics when capacity is zero
320    #[inline]
321    #[must_use]
322    pub fn new(capacity: usize) -> Self {
323        assert_ne!(capacity, 0, "Capacity must be greater than 0");
324        let size = capacity.next_power_of_two();
325        let layout = alloc::alloc::Layout::array::<T>(size).unwrap();
326        let buf = unsafe { alloc::alloc::alloc(layout).cast() };
327        Self {
328            buf,
329            size,
330            capacity,
331            readptr: 0,
332            writeptr: 0,
333        }
334    }
335}
336
337/// Get a const pointer to the buffer
338unsafe fn get_base_ptr<T>(rb: *const AllocRingBuffer<T>) -> *const T {
339    (*rb).buf.cast()
340}
341
342/// Get a mut pointer to the buffer
343unsafe fn get_base_mut_ptr<T>(rb: *mut AllocRingBuffer<T>) -> *mut T {
344    (*rb).buf
345}
346
347/// Get a reference from the buffer without checking it is initialized.
348///
349/// Caller must be sure the index is in bounds, or this will panic.
350#[inline]
351unsafe fn get_unchecked<'a, T>(rb: *const AllocRingBuffer<T>, index: usize) -> &'a T {
352    let p = (*rb).buf.add(index);
353    // Safety: caller makes sure the index is in bounds for the ringbuffer.
354    // All in bounds values in the ringbuffer are initialized
355    &*p
356}
357
358/// Get a mut reference from the buffer without checking it is initialized.
359///
360/// Caller must be sure the index is in bounds, or this will panic.
361#[inline]
362unsafe fn get_unchecked_mut<T>(rb: *mut AllocRingBuffer<T>, index: usize) -> *mut T {
363    let p = (*rb).buf.add(index);
364
365    // Safety: caller makes sure the index is in bounds for the ringbuffer.
366    // All in bounds values in the ringbuffer are initialized
367    p.cast()
368}
369
370impl<T> Index<usize> for AllocRingBuffer<T> {
371    type Output = T;
372
373    fn index(&self, index: usize) -> &Self::Output {
374        self.get(index).expect("index out of bounds")
375    }
376}
377
378impl<T> IndexMut<usize> for AllocRingBuffer<T> {
379    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
380        self.get_mut(index).expect("index out of bounds")
381    }
382}
383
384impl<T> SetLen for AllocRingBuffer<T> {
385    impl_ring_buffer_set_len!(readptr, writeptr);
386}
387
388#[cfg(test)]
389mod tests {
390    use crate::{AllocRingBuffer, RingBuffer};
391
392    // just test that this compiles
393    #[test]
394    fn test_generic_clone() {
395        fn helper(a: &AllocRingBuffer<i32>) -> AllocRingBuffer<i32> {
396            a.clone()
397        }
398
399        _ = helper(&AllocRingBuffer::new(2));
400        _ = helper(&AllocRingBuffer::new(5));
401    }
402
403    #[test]
404    fn test_not_power_of_two() {
405        let mut rb = AllocRingBuffer::new(10);
406        const NUM_VALS: usize = 1000;
407
408        // recycle the ringbuffer a bunch of time to see if noneof the logic
409        // messes up
410        for _ in 0..100 {
411            for i in 0..NUM_VALS {
412                let _ = rb.enqueue(i);
413            }
414            assert!(rb.is_full());
415
416            for i in 0..10 {
417                assert_eq!(Some(i + NUM_VALS - rb.capacity()), rb.dequeue());
418            }
419
420            assert!(rb.is_empty());
421        }
422    }
423
424    #[test]
425    fn test_with_capacity_power_of_two() {
426        let b = AllocRingBuffer::<i32>::with_capacity_power_of_2(2);
427        assert_eq!(b.capacity, 4);
428    }
429
430    #[test]
431    #[should_panic]
432    fn test_index_zero_length() {
433        let b = AllocRingBuffer::<i32>::new(2);
434        let _ = b[2];
435    }
436
437    #[test]
438    fn test_extend() {
439        let mut buf = AllocRingBuffer::<u8>::new(4);
440        (0..4).for_each(|_| {
441            let _ = buf.enqueue(0);
442        });
443
444        let new_data = [0, 1, 2];
445        buf.extend(new_data);
446
447        let expected = [0, 0, 1, 2];
448
449        for i in 0..4 {
450            let actual = buf[i];
451            let expected = expected[i];
452            assert_eq!(actual, expected);
453        }
454    }
455
456    #[test]
457    fn test_extend_with_overflow() {
458        let mut buf = AllocRingBuffer::<u8>::new(8);
459        (0..8).for_each(|_| {
460            let _ = buf.enqueue(0);
461        });
462
463        let new_data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
464        buf.extend(new_data);
465
466        let expected = [2, 3, 4, 5, 6, 7, 8, 9];
467
468        for i in 0..8 {
469            let actual = buf[i];
470            let expected = expected[i];
471            assert_eq!(actual, expected);
472        }
473    }
474
475    #[test]
476    fn test_conversions() {
477        // from &[T]
478        let data: &[i32] = &[1, 2, 3, 4];
479        let buf = AllocRingBuffer::from(data);
480        assert_eq!(buf.capacity, 4);
481        assert_eq!(buf.to_vec(), alloc::vec![1, 2, 3, 4]);
482
483        // from &[T; N]
484        let buf = AllocRingBuffer::from(&[1, 2, 3, 4]);
485        assert_eq!(buf.capacity, 4);
486        assert_eq!(buf.to_vec(), alloc::vec![1, 2, 3, 4]);
487
488        // from [T; N]
489        let buf = AllocRingBuffer::from([1, 2, 3, 4]);
490        assert_eq!(buf.capacity, 4);
491        assert_eq!(buf.to_vec(), alloc::vec![1, 2, 3, 4]);
492    }
493}