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