1use std::{
10 cmp,
11 io::{self, Read, Write},
12 ptr,
13};
14
15use pool::Reset;
16
17#[derive(Debug, PartialEq, Eq, Clone)]
18pub struct Buffer {
19 memory: Vec<u8>,
20 capacity: usize,
21 position: usize,
22 end: usize,
23}
24
25impl Buffer {
26 pub fn with_capacity(capacity: usize) -> Buffer {
27 Buffer {
28 memory: vec![0; capacity],
29 capacity,
30 position: 0,
31 end: 0,
32 }
33 }
34
35 pub fn from_slice(sl: &[u8]) -> Buffer {
36 Buffer {
37 memory: Vec::from(sl),
38 capacity: sl.len(),
39 position: 0,
40 end: sl.len(),
41 }
42 }
43
44 pub fn grow(&mut self, new_size: usize) -> bool {
45 if self.capacity >= new_size {
46 return false;
47 }
48
49 self.memory.resize(new_size, 0);
50 self.capacity = new_size;
51 true
52 }
53
54 pub fn shrink(&mut self, target_size: usize) -> bool {
57 if target_size >= self.capacity {
58 return false;
59 }
60 self.shift();
61 if self.end > target_size {
62 return false;
63 }
64 self.memory.truncate(target_size);
65 self.memory.shrink_to_fit();
66 self.capacity = target_size;
67 true
68 }
69
70 pub fn available_data(&self) -> usize {
71 self.end - self.position
72 }
73
74 pub fn available_space(&self) -> usize {
75 self.capacity - self.end
76 }
77
78 pub fn capacity(&self) -> usize {
79 self.capacity
80 }
81
82 pub fn empty(&self) -> bool {
83 self.position == self.end
84 }
85
86 pub fn consume(&mut self, count: usize) -> usize {
87 let cnt = cmp::min(count, self.available_data());
88 self.position += cnt;
89 if self.position > self.capacity / 2 {
90 self.shift();
92 }
93 cnt
94 }
95
96 pub fn fill(&mut self, count: usize) -> usize {
98 let cnt = cmp::min(count, self.available_space());
99 self.end += cnt;
100 if self.available_space() < self.available_data() + cnt {
101 self.shift();
103 }
104
105 cnt
106 }
107
108 pub fn reset(&mut self) {
109 self.position = 0;
110 self.end = 0;
111 }
112
113 pub fn data(&self) -> &[u8] {
114 &self.memory[self.position..self.end]
115 }
116
117 pub fn space(&mut self) -> &mut [u8] {
118 &mut self.memory[self.end..self.capacity]
119 }
120
121 pub fn shift(&mut self) {
122 if self.position > 0 {
123 unsafe {
128 let length = self.end - self.position;
129 ptr::copy(
130 self.memory[self.position..self.end].as_ptr(),
131 self.memory[..length].as_mut_ptr(),
132 length,
133 );
134 self.position = 0;
135 self.end = length;
136 }
137 }
138 }
139
140 pub fn delete_slice(&mut self, start: usize, length: usize) -> Option<usize> {
141 if start + length >= self.available_data() {
142 return None;
143 }
144
145 unsafe {
151 let begin = self.position + start;
152 let next_end = self.end - length;
153 ptr::copy(
154 self.memory[begin + length..self.end].as_ptr(),
155 self.memory[begin..next_end].as_mut_ptr(),
156 self.end - (begin + length),
157 );
158 self.end = next_end;
159 }
160 Some(self.available_data())
161 }
162
163 pub fn replace_slice(&mut self, data: &[u8], start: usize, length: usize) -> Option<usize> {
164 let data_len = data.len();
165 if start + length > self.available_data()
166 || self.position + start + data_len > self.capacity
167 {
168 return None;
169 }
170
171 unsafe {
177 let begin = self.position + start;
178 let slice_end = begin + data_len;
179 if data_len < length {
181 ptr::copy(
182 data.as_ptr(),
183 self.memory[begin..slice_end].as_mut_ptr(),
184 data_len,
185 );
186
187 ptr::copy(
188 self.memory[start + length..self.end].as_ptr(),
189 self.memory[slice_end..].as_mut_ptr(),
190 self.end - (start + length),
191 );
192 self.end -= length - data_len;
193
194 } else {
196 ptr::copy(
197 self.memory[start + length..self.end].as_ptr(),
198 self.memory[start + data_len..].as_mut_ptr(),
199 self.end - (start + length),
200 );
201 ptr::copy(
202 data.as_ptr(),
203 self.memory[begin..slice_end].as_mut_ptr(),
204 data_len,
205 );
206 self.end += data_len - length;
207 }
208 }
209 Some(self.available_data())
210 }
211
212 pub fn insert_slice(&mut self, data: &[u8], start: usize) -> Option<usize> {
213 let data_len = data.len();
214 if start > self.available_data() || self.position + self.end + data_len > self.capacity {
215 return None;
216 }
217
218 unsafe {
224 let begin = self.position + start;
225 let slice_end = begin + data_len;
226 ptr::copy(
227 self.memory[start..self.end].as_ptr(),
228 self.memory[start + data_len..].as_mut_ptr(),
229 self.end - start,
230 );
231 ptr::copy(
232 data.as_ptr(),
233 self.memory[begin..slice_end].as_mut_ptr(),
234 data_len,
235 );
236 self.end += data_len;
237 }
238 Some(self.available_data())
239 }
240}
241
242impl Write for Buffer {
243 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
244 match self.space().write(buf) {
245 Ok(size) => {
246 self.fill(size);
247 Ok(size)
248 }
249 err => err,
250 }
251 }
252
253 fn flush(&mut self) -> io::Result<()> {
254 Ok(())
255 }
256}
257
258impl Read for Buffer {
259 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
260 let len = cmp::min(self.available_data(), buf.len());
261 unsafe {
267 ptr::copy(
268 self.memory[self.position..self.position + len].as_ptr(),
269 buf.as_mut_ptr(),
270 len,
271 );
272 self.position += len;
273 }
274 Ok(len)
275 }
276}
277
278impl Reset for Buffer {
279 fn reset(&mut self) {
280 self.reset();
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use std::io::Write;
287
288 use super::*;
289
290 #[test]
291 fn fill_and_consume() {
292 let mut b = Buffer::with_capacity(10);
293 assert_eq!(b.available_data(), 0);
294 assert_eq!(b.available_space(), 10);
295 let res = b.write(&b"abcd"[..]);
296 assert_eq!(res.ok(), Some(4));
297 assert_eq!(b.available_data(), 4);
298 assert_eq!(b.available_space(), 6);
299
300 assert_eq!(b.data(), &b"abcd"[..]);
301
302 b.consume(2);
303 assert_eq!(b.available_data(), 2);
304 assert_eq!(b.available_space(), 6);
305 assert_eq!(b.data(), &b"cd"[..]);
306
307 b.shift();
308 assert_eq!(b.available_data(), 2);
309 assert_eq!(b.available_space(), 8);
310 assert_eq!(b.data(), &b"cd"[..]);
311
312 assert_eq!(b.write(&b"efghijklmnop"[..]).ok(), Some(8));
313 assert_eq!(b.available_data(), 10);
314 assert_eq!(b.available_space(), 0);
315 assert_eq!(b.data(), &b"cdefghijkl"[..]);
316 b.shift();
317 assert_eq!(b.available_data(), 10);
318 assert_eq!(b.available_space(), 0);
319 assert_eq!(b.data(), &b"cdefghijkl"[..]);
320 }
321
322 #[test]
323 fn delete() {
324 let mut b = Buffer::with_capacity(10);
325 let _ = b.write(&b"abcdefgh"[..]).expect("should write");
326 assert_eq!(b.available_data(), 8);
327 assert_eq!(b.available_space(), 2);
328
329 assert_eq!(b.delete_slice(2, 3), Some(5));
330 assert_eq!(b.available_data(), 5);
331 assert_eq!(b.available_space(), 5);
332 assert_eq!(b.data(), &b"abfgh"[..]);
333
334 assert_eq!(b.delete_slice(5, 2), None);
335 assert_eq!(b.delete_slice(4, 2), None);
336 }
337
338 #[test]
339 fn replace() {
340 let mut b = Buffer::with_capacity(10);
341 let _ = b.write(&b"abcdefgh"[..]).expect("should write");
342 assert_eq!(b.available_data(), 8);
343 assert_eq!(b.available_space(), 2);
344
345 assert_eq!(b.replace_slice(&b"ABC"[..], 2, 3), Some(8));
346 assert_eq!(b.available_data(), 8);
347 assert_eq!(b.available_space(), 2);
348 assert_eq!(b.data(), &b"abABCfgh"[..]);
349
350 assert_eq!(b.replace_slice(&b"XYZ"[..], 8, 3), None);
351 assert_eq!(b.replace_slice(&b"XYZ"[..], 6, 3), None);
352
353 assert_eq!(b.replace_slice(&b"XYZ"[..], 2, 4), Some(7));
354 assert_eq!(b.available_data(), 7);
355 assert_eq!(b.available_space(), 3);
356 assert_eq!(b.data(), &b"abXYZgh"[..]);
357
358 assert_eq!(b.replace_slice(&b"123"[..], 2, 2), Some(8));
359 assert_eq!(b.available_data(), 8);
360 assert_eq!(b.available_space(), 2);
361 assert_eq!(b.data(), &b"ab123Zgh"[..]);
362 }
363}