sozu_command_lib/buffer/
growable.rs

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