chunked_buffer/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use alloc::boxed::Box;
6use alloc::collections::VecDeque;
7use alloc::vec::Vec;
8use core::cmp::min;
9use core::ops::{Index, IndexMut};
10
11/// The default chunk size
12pub const DEFAULT_CHUNK_SIZE: usize = 256;
13
14/// A deque style buffer that can be written to and read from.
15/// See `GenericChunkedBuffer` for more details.
16pub type ChunkedBuffer = GenericChunkedBuffer<DEFAULT_CHUNK_SIZE>;
17
18/// A deque style buffer that can be written to and read from.
19///
20/// The buffer is composed of a series of fixed size chunks.
21///
22/// This structure is useful for memory constrained environments.  It limits the size of contiguous
23/// allocations and incrementally releases memory as the buffer is consumed.
24///
25/// Example code:
26/// ```
27/// use chunked_buffer::ChunkedBuffer;
28///
29/// let mut buf = ChunkedBuffer::new();
30/// buf.write(&[1, 2, 3]);
31/// let mut dest = [0; 10];
32/// let n = buf.read(&mut dest);
33/// assert_eq!(n, 3);
34/// assert_eq!(dest, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]);
35/// ```
36///
37// Invariants:
38// - `chunks` is never empty
39// - all chunks are the same size
40// - the read position is always in the first chunk
41// - the write position is always in the last chunk
42pub struct GenericChunkedBuffer<const CHUNK_SIZE: usize> {
43    // the inclusive position of the first octet in the first chunk
44    write_pos: usize,
45    // the exclusive position of the last octet written in the last chunk
46    read_pos: usize,
47    chunks: VecDeque<Box<[u8; CHUNK_SIZE]>>,
48}
49
50impl<const CHUNK_SIZE: usize> GenericChunkedBuffer<CHUNK_SIZE> {
51    /// Create a new, empty buffer
52    pub fn new() -> Self {
53        let mut s = GenericChunkedBuffer {
54            write_pos: 0,
55            read_pos: 0,
56            chunks: VecDeque::new(),
57        };
58        s.chunks.push_back(Box::new([0; CHUNK_SIZE]));
59        s
60    }
61
62    /// The number of bytes in the buffer
63    pub fn len(&self) -> usize {
64        (self.chunks.len() - 1) * CHUNK_SIZE + self.write_pos - self.read_pos
65    }
66
67    /// Returns true if the buffer is empty
68    pub fn is_empty(&self) -> bool {
69        self.chunks.len() == 1 && self.write_pos == self.read_pos
70    }
71
72    /// Consumes as many bytes as possible from the start of the buffer
73    /// and writes them to `dest`
74    pub fn read(&mut self, dest: &mut [u8]) -> usize {
75        let mut nread = 0;
76        while nread < dest.len() && !self.is_empty() {
77            let chunk = &*self.chunks[0];
78            let start = self.read_pos;
79            let mut end = min(CHUNK_SIZE, start + dest.len() - nread);
80            if self.chunks.len() == 1 {
81                end = end.min(self.write_pos);
82            }
83            let n = end - start;
84            dest[nread..nread + n].copy_from_slice(&chunk[start..end]);
85            if end == CHUNK_SIZE {
86                self.read_pos = 0;
87                self.chunks.pop_front();
88                // self.chunks cannot be empty here, because we must have created a new chunk
89                // when we wrote the last byte
90            } else {
91                self.read_pos = end;
92            }
93            nread += n;
94        }
95        nread
96    }
97
98    /// pushes all the bytes in `src` to the end of the buffer
99    pub fn write(&mut self, src: &[u8]) {
100        let mut nwritten = 0;
101        while nwritten < src.len() {
102            let chunk = &mut **self.chunks.back_mut().unwrap();
103            let start = self.write_pos;
104            let end = min(CHUNK_SIZE, start + src.len() - nwritten);
105            let n = end - start;
106            chunk[start..end].copy_from_slice(&src[nwritten..nwritten + n]);
107            nwritten += n;
108            if end == CHUNK_SIZE {
109                self.write_pos = 0;
110                self.chunks.push_back(Box::new([0; CHUNK_SIZE]));
111            } else {
112                self.write_pos = end;
113            }
114        }
115    }
116
117    /// Returns an iterator over u8 contained in buffer
118    pub fn iter(&self) -> Iter<CHUNK_SIZE> {
119        Iter::new(self)
120    }
121
122    /// Returns an iterator over the chunks contained in buffer
123    pub fn iter_chunks(&self) -> IterChunk<CHUNK_SIZE> {
124        IterChunk::new(self)
125    }
126
127    /// Converts the buffer into a vector
128    pub fn to_vec(&self) -> Vec<u8> {
129        let mut vec = Vec::with_capacity(self.len());
130        for chunk in self.iter_chunks() {
131            vec.extend_from_slice(chunk);
132        }
133        vec
134    }
135}
136
137impl<const CHUNK_SIZE: usize> Default for GenericChunkedBuffer<CHUNK_SIZE> {
138    fn default() -> Self {
139        Self::new()
140    }
141}
142
143impl<const CHUNK_SIZE: usize> Index<usize> for GenericChunkedBuffer<CHUNK_SIZE> {
144    type Output = u8;
145
146    fn index(&self, index: usize) -> &Self::Output {
147        if self.is_empty() {
148            panic!("indexed into an empty buffer");
149        }
150        if index >= self.len() {
151            panic!("out of bounds access");
152        }
153        let pos = index % CHUNK_SIZE;
154        let index = index / CHUNK_SIZE;
155        &self.chunks[index][pos]
156    }
157}
158
159impl<const CHUNK_SIZE: usize> IndexMut<usize> for GenericChunkedBuffer<CHUNK_SIZE> {
160    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
161        if self.is_empty() {
162            panic!("indexed into an empty buffer");
163        }
164        if index >= self.len() {
165            panic!("out of bounds access");
166        }
167        let pos = index % CHUNK_SIZE;
168        let index = index / CHUNK_SIZE;
169        &mut self.chunks[index][pos]
170    }
171}
172
173pub struct Iter<'a, const CHUNK_SIZE: usize> {
174    nread: usize,
175    index: usize,
176    read_pos: usize,
177    buf: &'a GenericChunkedBuffer<CHUNK_SIZE>,
178}
179
180impl<'a, const CHUNK_SIZE: usize> Iter<'a, CHUNK_SIZE> {
181    fn new(buf: &'a GenericChunkedBuffer<CHUNK_SIZE>) -> Self {
182        Iter {
183            nread: 0,
184            index: 0,
185            read_pos: buf.read_pos,
186            buf,
187        }
188    }
189}
190
191impl<const CHUNK_SIZE: usize> Iterator for Iter<'_, CHUNK_SIZE> {
192    type Item = u8;
193    fn next(&mut self) -> Option<Self::Item> {
194        if self.nread == self.buf.len() {
195            None
196        } else {
197            let byte = self.buf.chunks[self.index][self.read_pos];
198            self.nread += 1;
199            self.read_pos += 1;
200            if self.read_pos == CHUNK_SIZE {
201                self.read_pos = 0;
202                self.index += 1;
203            }
204            Some(byte)
205        }
206    }
207}
208
209pub struct IterChunk<'a, const CHUNK_SIZE: usize> {
210    index: usize,
211    buf: &'a GenericChunkedBuffer<CHUNK_SIZE>,
212}
213
214impl<'a, const CHUNK_SIZE: usize> IterChunk<'a, CHUNK_SIZE> {
215    fn new(buf: &'a GenericChunkedBuffer<CHUNK_SIZE>) -> Self {
216        IterChunk { index: 0, buf }
217    }
218}
219
220impl<'a, const CHUNK_SIZE: usize> Iterator for IterChunk<'a, CHUNK_SIZE> {
221    type Item = &'a [u8];
222    fn next(&mut self) -> Option<Self::Item> {
223        if self.index == self.buf.chunks.len() {
224            None
225        } else {
226            let begin = if self.index == 0 {
227                self.buf.read_pos
228            } else {
229                0
230            };
231            let end = if self.index + 1 == self.buf.chunks.len() {
232                self.buf.write_pos
233            } else {
234                CHUNK_SIZE
235            };
236            let slice = &self.buf.chunks[self.index][begin..end];
237            self.index += 1;
238            if slice.is_empty() {
239                None
240            } else {
241                Some(slice)
242            }
243        }
244    }
245}
246
247#[cfg(test)]
248mod tests {
249    use super::*;
250
251    type Buf = GenericChunkedBuffer<4>;
252
253    #[test]
254    fn test() {
255        let mut buf = Buf::new();
256        assert_eq!(buf.len(), 0);
257        assert!(buf.is_empty());
258
259        let mut dest = [0; 10];
260        assert_eq!(buf.read(&mut dest), 0);
261
262        buf.write(&[1, 2, 3]);
263        assert_eq!(buf.len(), 3);
264        assert!(!buf.is_empty());
265
266        let mut dest = [0; 10];
267        assert_eq!(buf.read(&mut dest), 3);
268        assert_eq!(dest, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]);
269        assert_eq!(buf.len(), 0);
270        assert!(buf.is_empty());
271
272        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
273        assert_eq!(buf.len(), 10);
274        assert!(!buf.is_empty());
275
276        let mut dest = [0; 9];
277        assert_eq!(buf.read(&mut dest), 9);
278        assert_eq!(dest, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
279        assert_eq!(buf.len(), 1);
280
281        let mut dest = [0; 9];
282        assert_eq!(buf.read(&mut dest), 1);
283        assert_eq!(dest, [10, 0, 0, 0, 0, 0, 0, 0, 0]);
284        assert_eq!(buf.len(), 0);
285        assert!(buf.is_empty());
286
287        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
288        assert_eq!(buf.len(), 10);
289        assert!(!buf.is_empty());
290
291        let mut dest = [0; 5];
292        assert_eq!(buf.read(&mut dest), 5);
293        assert_eq!(dest, [1, 2, 3, 4, 5]);
294        assert_eq!(buf.len(), 5);
295        assert!(!buf.is_empty());
296
297        let mut dest = [0; 5];
298        assert_eq!(buf.read(&mut dest), 5);
299        assert_eq!(dest, [6, 7, 8, 9, 10]);
300        assert_eq!(buf.len(), 0);
301        assert!(buf.is_empty());
302
303        // at chunk boundary
304        let mut dest = [0; 5];
305        buf.write(&[99]);
306        assert_eq!(buf.len(), 1);
307        assert_eq!(buf.read(&mut dest), 1);
308        assert_eq!(dest, [99, 0, 0, 0, 0]);
309    }
310    #[test]
311    fn test_iterator() {
312        // empty buffer
313        let mut buf = Buf::new();
314        let mut i = buf.iter();
315        assert_eq!(i.next(), None);
316        assert_eq!(i.next(), None);
317        assert_eq!(i.next(), None);
318
319        // empty write
320        buf = Buf::new();
321        buf.write(&[]);
322        i = buf.iter();
323        assert_eq!(i.next(), None);
324        assert_eq!(i.next(), None);
325        assert_eq!(i.next(), None);
326
327        // first chunk not filled
328        buf = Buf::new();
329        buf.write(&[1, 2, 3]);
330        i = buf.iter();
331        for count in 1..4 {
332            assert_eq!(i.next(), Some(count));
333        }
334        assert_eq!(i.next(), None);
335        assert_eq!(i.next(), None);
336        assert_eq!(i.next(), None);
337
338        // first chunk filled
339        buf = Buf::new();
340        buf.write(&[1, 2, 3, 4]);
341        i = buf.iter();
342        for count in 1..5 {
343            assert_eq!(i.next(), Some(count));
344        }
345        assert_eq!(i.next(), None);
346        assert_eq!(i.next(), None);
347        assert_eq!(i.next(), None);
348
349        // third chunk not filled
350        buf = Buf::new();
351        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
352        i = buf.iter();
353        for count in 1..11 {
354            assert_eq!(i.next(), Some(count));
355        }
356        assert_eq!(i.next(), None);
357        assert_eq!(i.next(), None);
358        assert_eq!(i.next(), None);
359
360        // third chunk filled
361        buf = Buf::new();
362        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
363        i = buf.iter();
364        for count in 1..13 {
365            assert_eq!(i.next(), Some(count));
366        }
367        assert_eq!(i.next(), None);
368        assert_eq!(i.next(), None);
369        assert_eq!(i.next(), None);
370
371        // fourth chunk not filled
372        buf = Buf::new();
373        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
374        i = buf.iter();
375        for count in 1..14 {
376            assert_eq!(i.next(), Some(count));
377        }
378        assert_eq!(i.next(), None);
379        assert_eq!(i.next(), None);
380        assert_eq!(i.next(), None);
381    }
382    #[test]
383    fn test_iter_chunks() {
384        // empty buffer
385        let mut buf = Buf::new();
386        let mut i = buf.iter_chunks();
387        assert_eq!(i.next(), None);
388        assert_eq!(i.next(), None);
389        assert_eq!(i.next(), None);
390
391        // empty write
392        buf = Buf::new();
393        buf.write(&[]);
394        i = buf.iter_chunks();
395        assert_eq!(i.next(), None);
396        assert_eq!(i.next(), None);
397        assert_eq!(i.next(), None);
398
399        // first chunk not filled
400        buf = Buf::new();
401        buf.write(&[1, 2, 3]);
402        i = buf.iter_chunks();
403        assert_eq!(i.next(), Some(&[1, 2, 3][..]));
404        assert_eq!(i.next(), None);
405        assert_eq!(i.next(), None);
406        assert_eq!(i.next(), None);
407
408        // first chunk filled
409        buf = Buf::new();
410        buf.write(&[1, 2, 3, 4]);
411        i = buf.iter_chunks();
412        assert_eq!(i.next(), Some(&[1, 2, 3, 4][..]));
413        assert_eq!(i.next(), None);
414        assert_eq!(i.next(), None);
415        assert_eq!(i.next(), None);
416
417        // third chunk not filled
418        buf = Buf::new();
419        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
420        i = buf.iter_chunks();
421        assert_eq!(i.next(), Some(&[1, 2, 3, 4][..]));
422        assert_eq!(i.next(), Some(&[5, 6, 7, 8][..]));
423        assert_eq!(i.next(), Some(&[9, 10][..]));
424        assert_eq!(i.next(), None);
425        assert_eq!(i.next(), None);
426        assert_eq!(i.next(), None);
427
428        // third chunk filled
429        buf = Buf::new();
430        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
431        i = buf.iter_chunks();
432        assert_eq!(i.next(), Some(&[1, 2, 3, 4][..]));
433        assert_eq!(i.next(), Some(&[5, 6, 7, 8][..]));
434        assert_eq!(i.next(), Some(&[9, 10, 11, 12][..]));
435        assert_eq!(i.next(), None);
436        assert_eq!(i.next(), None);
437        assert_eq!(i.next(), None);
438
439        // fourth chunk not filled
440        buf = Buf::new();
441        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
442        i = buf.iter_chunks();
443        assert_eq!(i.next(), Some(&[1, 2, 3, 4][..]));
444        assert_eq!(i.next(), Some(&[5, 6, 7, 8][..]));
445        assert_eq!(i.next(), Some(&[9, 10, 11, 12][..]));
446        assert_eq!(i.next(), Some(&[13][..]));
447        assert_eq!(i.next(), None);
448        assert_eq!(i.next(), None);
449        assert_eq!(i.next(), None);
450    }
451    #[test]
452    fn test_index() {
453        let mut buf = Buf::new();
454        buf.write(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
455        for i in 0..14 {
456            assert_eq!(buf[i], i as u8);
457        }
458    }
459    #[test]
460    #[should_panic]
461    fn test_index_panic_on_empty() {
462        let buf = Buf::new();
463        buf[0];
464    }
465    #[test]
466    #[should_panic]
467    fn test_index_out_of_bounds() {
468        let mut buf = Buf::new();
469        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
470        buf[13];
471    }
472    #[test]
473    fn test_index_mut() {
474        let mut buf = Buf::new();
475        buf.write(&[0u8; 14]);
476        for i in 0..14 {
477            buf[i] = i as u8;
478        }
479        let mut want = Buf::new();
480        want.write(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
481        assert_eq!(buf.to_vec(), want.to_vec());
482    }
483    #[test]
484    #[should_panic]
485    fn test_index_mut_panic_on_empty() {
486        let mut buf = Buf::new();
487        buf[0] = 3;
488    }
489    #[test]
490    #[should_panic]
491    fn test_index_mut_out_of_bounds() {
492        let mut buf = Buf::new();
493        buf.write(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
494        buf[13] = 3;
495    }
496}