sozu_command_lib/buffer/
fixed.rs

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