1use std::num::NonZeroUsize;
2
3pub struct RingBuf {
5 inner_block: Vec<u8>,
7 read_offset: usize,
9 write_offset: usize,
11}
12
13impl RingBuf {
14 pub fn with_capacity(value: NonZeroUsize) -> Self {
18 Self {
19 inner_block: vec![0; value.get()],
20 read_offset: 0,
21 write_offset: 0,
22 }
23 }
24
25 pub fn remaining(&self) -> usize {
27 self.write_offset - self.read_offset
28 }
29
30 pub fn remaining_mut(&self) -> usize {
33 self.read_offset + self.inner_block.len() - self.write_offset
34 }
35
36 pub fn chunk_mut(&mut self) -> &mut [u8] {
39 let write_offset = self.write_offset % self.inner_block.len();
40
41 let mut write_len = self.remaining_mut();
42
43 if write_len > self.inner_block.len() - write_offset {
44 write_len = self.inner_block.len() - write_offset;
45 }
46
47 &mut self.inner_block[write_offset..write_offset + write_len]
48 }
49
50 pub fn chunk(&self) -> &[u8] {
53 let read_offset = self.read_offset % self.inner_block.len();
54
55 let mut read_len = self.remaining();
56
57 if read_len > self.inner_block.len() - read_offset {
58 read_len = self.inner_block.len() - read_offset;
59 }
60
61 &self.inner_block[read_offset..read_offset + read_len]
62 }
63
64 pub fn advance_mut(&mut self, offset: usize) {
68 if offset > self.remaining_mut() {
69 panic!(
70 "advance out of bounds: the remaining mut len is {} but advancing by {}",
71 self.remaining_mut(),
72 offset
73 );
74 }
75
76 self.write_offset += offset;
77 }
78
79 pub fn advance(&mut self, offset: usize) {
83 if offset > self.remaining() {
84 panic!(
85 "advance out of bounds: the remaining len is {} but advancing by {}",
86 self.remaining(),
87 offset
88 );
89 }
90
91 self.read_offset += offset;
92 }
93
94 pub fn write(&mut self, mut buf: &[u8]) -> usize {
100 let mut write_len = 0;
101
102 while buf.len() > 0 && self.remaining_mut() > 0 {
103 let chunk_mut = self.chunk_mut();
104
105 if chunk_mut.len() >= buf.len() {
106 chunk_mut[..buf.len()].copy_from_slice(buf);
107 self.advance_mut(buf.len());
108 write_len += buf.len();
109
110 return write_len;
111 }
112
113 let advance = chunk_mut.len();
114
115 chunk_mut.copy_from_slice(&buf[..advance]);
116
117 write_len += advance;
118
119 self.advance_mut(advance);
121
122 buf = &buf[advance..];
124 }
125
126 return write_len;
127 }
128
129 pub fn read(&mut self, mut buf: &mut [u8]) -> usize {
133 let mut read_len = 0;
134
135 while buf.len() > 0 && self.remaining() > 0 {
136 let chunk = self.chunk();
137
138 if chunk.len() >= buf.len() {
139 buf.copy_from_slice(&chunk[..buf.len()]);
140
141 self.advance(buf.len());
142 read_len += buf.len();
143
144 return read_len;
145 }
146
147 let advance = chunk.len();
148
149 buf[..advance].copy_from_slice(chunk);
150
151 read_len += advance;
152
153 self.advance(advance);
154
155 buf = &mut buf[advance..];
156 }
157
158 return read_len;
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn test_ring_buf() {
168 let capacity = 1024;
169
170 let mut ring_buf = RingBuf::with_capacity(NonZeroUsize::new(1024).unwrap());
171
172 assert_eq!(ring_buf.remaining(), 0);
173 assert_eq!(ring_buf.remaining_mut(), capacity);
174
175 assert_eq!(ring_buf.write(&vec![1; capacity * 2]), ring_buf.remaining());
178
179 assert_eq!(ring_buf.remaining(), capacity);
180 assert_eq!(ring_buf.remaining_mut(), 0);
181
182 let mut buf = vec![0; capacity / 2];
183
184 assert_eq!(ring_buf.read(&mut buf), capacity / 2);
185
186 assert_eq!(buf, vec![1; capacity / 2]);
187
188 assert_eq!(ring_buf.write(&vec![2; capacity / 4]), capacity / 4);
189
190 let mut buf = vec![0; capacity / 2];
191
192 assert_eq!(ring_buf.read(&mut buf), capacity / 2);
193
194 assert_eq!(buf, vec![1; capacity / 2]);
195
196 let mut buf = vec![0; capacity / 8];
197
198 assert_eq!(ring_buf.read(&mut buf), capacity / 8);
199
200 assert_eq!(buf, vec![2; capacity / 8]);
201
202 assert_eq!(ring_buf.remaining_mut(), 7 * capacity / 8);
203
204 assert_eq!(ring_buf.write(&vec![3; capacity * 10]), 7 * capacity / 8);
205
206 assert_eq!(ring_buf.remaining_mut(), 0);
207
208 assert_eq!(ring_buf.remaining(), capacity);
209
210 let mut buf = vec![0; capacity / 8];
211
212 assert_eq!(ring_buf.read(&mut buf), capacity / 8);
213
214 assert_eq!(buf, vec![2; capacity / 8]);
215
216 assert_eq!(ring_buf.remaining_mut(), capacity / 8);
217
218 assert_eq!(ring_buf.remaining(), 7 * capacity / 8);
219
220 let mut buf = vec![0; capacity * 10];
221
222 assert_eq!(ring_buf.read(&mut buf), 7 * capacity / 8);
223
224 assert_eq!(buf[..7 * capacity / 8], vec![3; 7 * capacity / 8]);
225 }
226}