1use std::{
7 cmp,
8 io::{self, Read, Write},
9};
10
11use poule::Reset;
12
13#[derive(Debug, PartialEq, Clone)]
14pub struct Buffer {
15 memory: Vec<u8>,
16 position: usize,
17 end: usize,
18}
19
20impl Buffer {
21 pub fn with_capacity(capacity: usize) -> Buffer {
22 Buffer {
23 memory: vec![0; capacity],
24 position: 0,
25 end: 0,
26 }
27 }
28
29 pub fn grow(&mut self, new_size: usize) -> bool {
41 if self.capacity() >= new_size {
42 return false;
43 }
44
45 unimplemented!()
51 }
52
53 pub fn available_data(&self) -> usize {
54 self.end - self.position
55 }
56
57 pub fn available_space(&self) -> usize {
58 self.capacity() - self.end
59 }
60
61 pub fn capacity(&self) -> usize {
62 self.memory.len()
63 }
64
65 pub fn empty(&self) -> bool {
66 self.position == self.end
67 }
68
69 pub fn consume(&mut self, count: usize) -> usize {
70 let cnt = cmp::min(count, self.available_data());
71 self.position += cnt;
72 if self.position > self.capacity() / 2 {
73 self.shift();
75 }
76 cnt
77 }
78
79 pub fn fill(&mut self, count: usize) -> usize {
80 let cnt = cmp::min(count, self.available_space());
81 self.end += cnt;
82 if self.available_space() < self.available_data() + cnt {
83 self.shift();
85 }
86
87 cnt
88 }
89
90 pub fn reset(&mut self) {
91 self.position = 0;
92 self.end = 0;
93 }
94
95 pub fn data(&self) -> &[u8] {
96 &self.memory[self.position..self.end]
97 }
98
99 pub fn space(&mut self) -> &mut [u8] {
100 &mut self.memory[self.end..]
101 }
102
103 pub fn shift(&mut self) {
104 if self.position > 0 {
105 let length = self.end - self.position;
106 self.memory.copy_within(self.position..self.end, 0);
107 self.position = 0;
108 self.end = length;
109 }
110 }
111
112 pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
113 let end = start.checked_add(length)?;
114 if end >= self.available_data() {
115 return None;
116 }
117
118 let begin = self.position + start;
119 let tail_start = begin + length;
120 self.memory.copy_within(tail_start..self.end, begin);
121 self.end -= length;
122 Some(self.available_data())
123 }
124
125 pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
126 let data_len = data.len();
127 let replaced_end = start.checked_add(length)?;
128 if replaced_end > self.available_data() {
129 return None;
130 }
131
132 let begin = self.position + start;
133 let tail_start = begin + length;
134 let slice_end = begin + data_len;
135
136 match data_len.cmp(&length) {
137 cmp::Ordering::Less => {
138 self.memory[begin..slice_end].copy_from_slice(data);
139 self.memory.copy_within(tail_start..self.end, slice_end);
140 self.end -= length - data_len;
141 }
142 cmp::Ordering::Equal => {
143 self.memory[begin..slice_end].copy_from_slice(data);
144 }
145 cmp::Ordering::Greater => {
146 let new_end = self.end.checked_add(data_len - length)?;
147 if new_end > self.capacity() {
148 return None;
149 }
150 self.memory.copy_within(tail_start..self.end, slice_end);
151 self.memory[begin..slice_end].copy_from_slice(data);
152 self.end = new_end;
153 }
154 }
155 Some(self.available_data())
156 }
157
158 pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
159 self.replace_slice(data, start, 0)
160 }
161}
162
163impl Write for Buffer {
164 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
165 match self.space().write(buf) {
166 Ok(size) => {
167 self.fill(size);
168 Ok(size)
169 }
170 err => err,
171 }
172 }
173
174 fn flush(&mut self) -> io::Result<()> {
175 Ok(())
176 }
177}
178
179impl Read for Buffer {
180 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
181 let len = cmp::min(self.available_data(), buf.len());
182 buf[..len].copy_from_slice(&self.memory[self.position..self.position + len]);
183 self.position += len;
184 Ok(len)
185 }
186}
187
188impl Reset for Buffer {
189 fn reset(&mut self) {
190 self.reset();
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use std::io::Write;
197
198 use super::*;
199
200 #[test]
201 fn fill_and_consume() {
202 let mut b = Buffer::with_capacity(10);
203 assert_eq!(b.available_data(), 0);
204 assert_eq!(b.available_space(), 10);
205 let res = b.write(&b"abcd"[..]);
206 assert_eq!(res.ok(), Some(4));
207 assert_eq!(b.available_data(), 4);
208 assert_eq!(b.available_space(), 6);
209
210 assert_eq!(b.data(), &b"abcd"[..]);
211
212 b.consume(2);
213 assert_eq!(b.available_data(), 2);
214 assert_eq!(b.available_space(), 6);
215 assert_eq!(b.data(), &b"cd"[..]);
216
217 b.shift();
218 assert_eq!(b.available_data(), 2);
219 assert_eq!(b.available_space(), 8);
220 assert_eq!(b.data(), &b"cd"[..]);
221
222 assert_eq!(b.write(&b"efghijklmnop"[..]).ok(), Some(8));
223 assert_eq!(b.available_data(), 10);
224 assert_eq!(b.available_space(), 0);
225 assert_eq!(b.data(), &b"cdefghijkl"[..]);
226 b.shift();
227 assert_eq!(b.available_data(), 10);
228 assert_eq!(b.available_space(), 0);
229 assert_eq!(b.data(), &b"cdefghijkl"[..]);
230 }
231
232 #[test]
233 fn delete() {
234 let mut b = Buffer::with_capacity(10);
235 let _ = b.write(&b"abcdefgh"[..]).expect("should write");
236 assert_eq!(b.available_data(), 8);
237 assert_eq!(b.available_space(), 2);
238
239 assert_eq!(b.delete_slice(2, 3), Some(5));
240 assert_eq!(b.available_data(), 5);
241 assert_eq!(b.available_space(), 5);
242 assert_eq!(b.data(), &b"abfgh"[..]);
243
244 assert_eq!(b.delete_slice(5, 2), None);
245 assert_eq!(b.delete_slice(4, 2), None);
246 }
247
248 #[test]
249 fn replace() {
250 let mut b = Buffer::with_capacity(10);
251 let _ = b.write(&b"abcdefgh"[..]).expect("should write");
252 assert_eq!(b.available_data(), 8);
253 assert_eq!(b.available_space(), 2);
254
255 assert_eq!(b.replace_slice(&b"ABC"[..], 2, 3), Some(8));
256 assert_eq!(b.available_data(), 8);
257 assert_eq!(b.available_space(), 2);
258 assert_eq!(b.data(), &b"abABCfgh"[..]);
259
260 assert_eq!(b.replace_slice(&b"XYZ"[..], 8, 3), None);
261 assert_eq!(b.replace_slice(&b"XYZ"[..], 6, 3), None);
262
263 assert_eq!(b.replace_slice(&b"XYZ"[..], 2, 4), Some(7));
264 assert_eq!(b.available_data(), 7);
265 assert_eq!(b.available_space(), 3);
266 assert_eq!(b.data(), &b"abXYZgh"[..]);
267
268 assert_eq!(b.replace_slice(&b"123"[..], 2, 2), Some(8));
269 assert_eq!(b.available_data(), 8);
270 assert_eq!(b.available_space(), 2);
271 assert_eq!(b.data(), &b"ab123Zgh"[..]);
272 }
273}