ringo_buff/
vec.rs

1use crate::{CircularBuffer, Storage};
2
3impl crate::sealed::StorageBase for Vec<u8> {}
4
5impl Storage for Vec<u8> {
6    fn len(&self) -> usize {
7        self.len()
8    }
9
10    fn as_slice(&self) -> &[u8] {
11        self.as_slice()
12    }
13
14    fn as_mut_slice(&mut self) -> &mut [u8] {
15        self.as_mut_slice()
16    }
17
18    fn split_at(&self, offset: usize) -> (&[u8], &[u8]) {
19        self.as_slice().split_at(offset)
20    }
21
22    fn split_at_mut(&mut self, offset: usize) -> (&mut [u8], &mut [u8]) {
23        self.as_mut_slice().split_at_mut(offset)
24    }
25}
26
27/// A circular buffer backed by a heap-allocated `Vec<u8>`.
28///
29/// Requires the `alloc` feature (enabled by default).
30pub type HeapBuffer = CircularBuffer<Vec<u8>>;
31
32impl HeapBuffer {
33    /// Creates a new buffer with the specified capacity.
34    ///
35    /// This allocates a `Vec` of `capacity` bytes filled with zeros.
36    ///
37    /// # Panics
38    ///
39    /// Panics if `capacity` is 0.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use ringo_buff::HeapBuffer;
45    ///
46    /// let buf = HeapBuffer::new(1024);
47    /// assert_eq!(buf.capacity(), 1024);
48    /// ```
49    pub fn new(capacity: usize) -> Self {
50        assert!(capacity > 0);
51        Self::_new_with_storage(vec![0u8; capacity])
52    }
53
54    /// Attempts to resize the buffer to a `new_capacity`.
55    ///
56    /// # Growing
57    /// If `new_capacity` is larger than the current capacity, the buffer is extended.
58    ///
59    /// # Shrinking
60    /// If `new_capacity` is smaller, the buffer attempts to shrink.
61    /// * This operation forces the buffer to become contiguous (see [`make_contiguous`](CircularBuffer::make_contiguous)).
62    /// * The operation fails if the active data (`remaining()`) is larger than `new_capacity`.
63    ///
64    /// # Errors
65    ///
66    /// Returns `Err(usize)` if the buffer cannot be shrunk because it currently holds too much data.
67    /// The error value is the number of bytes that must be consumed (read) before this resize can succeed.
68    ///
69    /// # Panics
70    ///
71    /// Panics if `new_capacity` is 0.
72    pub fn try_resize(&mut self, new_capacity: usize) -> Result<(), usize> {
73        assert!(new_capacity > 0);
74        if new_capacity >= self.capacity() {
75            // growing
76            self.bytes.resize(new_capacity, 0u8);
77        } else {
78            // shrinking
79            if self.remaining() > new_capacity {
80                // not enough empty space to shrink
81                let extra_bytes_needed = self.remaining() - new_capacity;
82                return Err(extra_bytes_needed);
83            }
84            self.make_contiguous();
85            self.bytes.truncate(new_capacity);
86        }
87        Ok(())
88    }
89}
90
91impl From<Vec<u8>> for HeapBuffer {
92    /// Converts an existing `Vec<u8>` into a `HeapBuffer`, reusing the `Vec` as the storage mechanism for the buffer.
93    fn from(value: Vec<u8>) -> Self {
94        assert!(value.capacity() > 0);
95        Self::_new_with_storage(value)
96    }
97}