rotating_buffer/lib.rs
1#![no_std]
2
3/*!
4# Rotating Buffer
5
6… is a small helper data structure that allows a stack-allocated buffer to be
7reused while keeping data that couldn't be handled immediately.
8
9## Example
10
11```rust
12use rotating_buffer::*;
13let mut buf = RotatingBuffer::<u8, 4>::new();
14
15buf.get_append_only().copy_from_slice(&[1, 2, 3, 4]);
16buf.add_len(4);
17assert_eq!(&[1, 2, 3, 4], buf.as_slice());
18
19buf.rotate_right_and_resize_at(3);
20assert_eq!(&[4], buf.as_slice());
21
22assert_eq!(3, buf.get_append_only().len());
23buf.get_append_only().copy_from_slice(&[5, 6, 7]);
24buf.add_len(3);
25assert_eq!(&[4, 5, 6, 7], buf.as_slice());
26
27buf.rotate_right_and_resize_at(4);
28assert_eq!(buf.as_slice().len(), 0);
29```
30
31For a more in depth example please see `examples/read_to_eof.rs`.
32
33Inspired by a pairing session at [Recurse Center](https://www.recurse.com/) 👩💻🐙
34*/
35
36#[derive(Debug, Clone, Copy)]
37pub struct RotatingBuffer<T: Default + Copy, const S: usize> {
38 inner_length: usize,
39 pub inner: [T; S],
40}
41
42impl<T: Default + Copy, const S: usize> RotatingBuffer<T, S> {
43 pub fn new() -> RotatingBuffer<T, S> {
44 RotatingBuffer {
45 inner: [T::default(); S],
46 inner_length: 0,
47 }
48 }
49
50 /// Extracts slice with the length of the buffer's internally tracked size
51 ///
52 /// # Example
53 ///
54 /// ```rust
55 /// # use rotating_buffer::*;
56 /// let mut buf = RotatingBuffer::<u128, 20>::new();
57 /// assert_eq!(buf.as_slice().len(), 0);
58 ///
59 /// buf.add_len(15);
60 /// assert_eq!(buf.as_slice().len(), 15);
61 /// ```
62 pub fn as_slice(&self) -> &[T] {
63 &self.inner[..self.inner_length]
64 }
65
66 /// Returns a mutable slice with the length of the currently "unused" allocation of the buffer
67 ///
68 /// # Example
69 ///
70 /// ```rust
71 /// # use rotating_buffer::*;
72 /// let mut buf = RotatingBuffer::<u8, 5>::new();
73 /// buf.add_len(3);
74 ///
75 /// assert_eq!(buf.get_append_only().len(), 2);
76 /// buf.get_append_only()[0] = 50;
77 /// assert_eq!(buf.inner, [0, 0, 0, 50, 0]);
78 /// ```
79 pub fn get_append_only(&mut self) -> &mut [T] {
80 &mut self.inner[self.inner_length..]
81 }
82
83 /// Returns `true` if the buffer's internal size is 0
84 pub fn is_empty(&self) -> bool {
85 self.inner_length == 0
86 }
87
88 /// Returns internally tracked length
89 pub fn len(&self) -> usize {
90 self.inner_length
91 }
92
93 /// Returns the capacity of this buffer
94 pub fn capacity(&self) -> usize {
95 S
96 }
97
98 /// Manually set the internal size of the buffer
99 ///
100 /// # Panics
101 ///
102 /// Panics if the new size is bigger than its capacity
103 pub fn resize(&mut self, new_len: usize) {
104 assert!(new_len <= S);
105 self.inner_length = new_len;
106 }
107
108 /// Add to the current internal length of the buffer
109 ///
110 /// # Example
111 ///
112 /// ```rust
113 /// # use rotating_buffer::*;
114 /// let mut buf = RotatingBuffer::<u8, 5>::new();
115 /// assert_eq!(buf.len(), 0);
116 ///
117 /// buf.add_len(3);
118 /// assert_eq!(buf.len(), 3);
119 /// buf.add_len(1);
120 /// assert_eq!(buf.len(), 4);
121 /// ```
122 pub fn add_len(&mut self, new_len: usize) -> usize {
123 self.resize(self.inner_length + new_len);
124 self.inner_length
125 }
126
127 /// Rotates the buffer contents in place (see `core::slice::rotate_right`) and subsequently
128 /// changes the buffer's internal length to however much was rotated
129 ///
130 /// # Example
131 ///
132 /// ```rust
133 /// # use rotating_buffer::*;
134 /// let mut buf = RotatingBuffer::<bool, 5>::new();
135 /// buf.get_append_only()[3] = true;
136 /// buf.add_len(5);
137 ///
138 /// buf.rotate_right_and_resize(2);
139 /// assert_eq!(buf.as_slice()[0], true);
140 /// assert_eq!(buf.len(), 2);
141 /// ```
142 pub fn rotate_right_and_resize(&mut self, k: usize) {
143 self.inner[..self.inner_length].rotate_right(k);
144 self.inner_length = k;
145 }
146
147 /// Rotate and resize buffer by supplying an index rather than a length
148 ///
149 /// # Example
150 ///
151 /// ```rust
152 /// # use rotating_buffer::*;
153 /// let mut buf = RotatingBuffer::<bool, 5>::new();
154 /// buf.get_append_only()[3] = true;
155 /// buf.add_len(5);
156 ///
157 /// buf.rotate_right_and_resize_at(3);
158 /// assert_eq!(buf.as_slice()[0], true);
159 /// assert_eq!(buf.len(), 2);
160 /// ```
161 pub fn rotate_right_and_resize_at(&mut self, index: usize) {
162 self.rotate_right_and_resize(self.inner_length - index);
163 }
164}
165
166/// Maybe just to allow `RotatingBuffer<RotatingBuffer<T, S>, S>` 😄
167///
168/// # Example
169///
170/// ```rust
171/// # use rotating_buffer::*;
172/// let mut buf = RotatingBuffer::<RotatingBuffer<u8, 10>, 5>::new();
173/// buf.add_len(2);
174/// let slice = buf.as_slice();
175/// assert_eq!(slice[0].inner, slice[1].inner);
176/// ```
177///
178/// But why!
179impl<T: Default + Copy, const S: usize> Default for RotatingBuffer<T, S> {
180 fn default() -> Self {
181 Self::new()
182 }
183}