usbd_serial/
buffer.rs

1use core::borrow::{Borrow, BorrowMut};
2use core::{cmp, ptr};
3
4/// A mediocre buffer that allows for block access without extra copies but memmoves more than
5/// necessary.
6///
7/// wpos points to the first byte that can be written rpos points at the next byte that can be read
8///
9/// invariants: 0 <= rpos <= wpos <= data.len()
10pub struct Buffer<S: BorrowMut<[u8]>> {
11    store: S,
12    rpos: usize,
13    wpos: usize,
14}
15
16impl<S: BorrowMut<[u8]>> Buffer<S> {
17    pub fn new(store: S) -> Self {
18        Self {
19            store,
20            rpos: 0,
21            wpos: 0,
22        }
23    }
24
25    // Clears the buffer
26    pub fn clear(&mut self) {
27        self.rpos = 0;
28        self.wpos = 0;
29    }
30
31    // Amount of bytes available for reading
32    pub fn available_read(&self) -> usize {
33        self.wpos - self.rpos
34    }
35
36    // Amount of space in bytes available for writing
37    pub fn available_write(&self) -> usize {
38        self.available_write_without_discard() + self.rpos
39    }
40
41    fn available_write_without_discard(&self) -> usize {
42        self.store.borrow().len() - self.wpos
43    }
44
45    // Writes as much as possible of data to the buffer and returns the number of bytes written
46    pub fn write(&mut self, data: &[u8]) -> usize {
47        if data.len() > self.available_write_without_discard() && self.rpos > 0 {
48            // data doesn't fit in already available space, and there is data to discard
49            self.discard_already_read_data();
50        }
51
52        let count = cmp::min(self.available_write_without_discard(), data.len());
53        if count == 0 {
54            // Buffer is full (or data is empty)
55            return 0;
56        }
57
58        self.store.borrow_mut()[self.wpos..self.wpos + count].copy_from_slice(&data[..count]);
59
60        self.wpos += count;
61        count
62    }
63
64    // Reserves max_count bytes of space for writing, and passes a slice pointing to them to a
65    // closure for writing. The closure should return the number of bytes actually written and is
66    // allowed to write less than max_bytes. If the callback returns an error, any written data is
67    // ignored.
68    pub fn write_all<E>(
69        &mut self,
70        max_count: usize,
71        f: impl FnOnce(&mut [u8]) -> Result<usize, E>,
72    ) -> Result<usize, E> {
73        if max_count > self.available_write_without_discard() {
74            // Data doesn't fit in currently available space
75            if max_count > self.available_write() {
76                // Data doesn't fit even if we discard already read data
77                return Ok(0);
78            }
79
80            self.discard_already_read_data();
81        }
82
83        assert!(self.available_write_without_discard() >= max_count);
84
85        f(&mut self.store.borrow_mut()[self.wpos..self.wpos + max_count]).map(|count| {
86            self.wpos += count;
87            count
88        })
89    }
90
91    // Takes up to max_count bytes from the buffer and passes a slice pointing to them to a closure
92    // for reading. The closure should return the number of bytes actually read and is allowed to
93    // read less than max_bytes. If the callback returns an error, the data is not discarded from
94    // the buffer.
95    pub fn read<E>(
96        &mut self,
97        max_count: usize,
98        f: impl FnOnce(&[u8]) -> Result<usize, E>,
99    ) -> Result<usize, E> {
100        let count = cmp::min(max_count, self.available_read());
101
102        f(&self.store.borrow()[self.rpos..self.rpos + count]).map(|count| {
103            self.rpos += count;
104            count
105        })
106    }
107
108    fn discard_already_read_data(&mut self) {
109        let data = self.store.borrow_mut();
110        if self.rpos != data.len() {
111            unsafe {
112                ptr::copy(
113                    &data[self.rpos] as *const u8,
114                    &mut data[0] as *mut u8,
115                    self.available_read(),
116                );
117            }
118        }
119
120        self.wpos -= self.rpos;
121        self.rpos = 0;
122    }
123}
124
125/// Default backing store for the mediocre buffer
126pub struct DefaultBufferStore([u8; 128]);
127
128impl Default for DefaultBufferStore {
129    fn default() -> Self {
130        Self([0u8; 128])
131    }
132}
133
134impl Borrow<[u8]> for DefaultBufferStore {
135    fn borrow(&self) -> &[u8] {
136        &self.0
137    }
138}
139
140impl BorrowMut<[u8]> for DefaultBufferStore {
141    fn borrow_mut(&mut self) -> &mut [u8] {
142        &mut self.0
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use core::convert::Infallible;
149
150    extern crate std;
151
152    const DATA: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
153    const LEN: usize = 5;
154    type Buf = crate::buffer::Buffer<[u8; LEN]>;
155
156    #[test]
157    fn write() {
158        let mut b = Buf::new([0; LEN]);
159
160        assert_eq!(b.write(&DATA[0..2]), 2);
161        assert_eq!(b.available_write(), LEN - 2);
162        assert_eq!(b.available_read(), 2);
163
164        assert_eq!(b.write(&DATA[0..5]), 3);
165        assert_eq!(b.available_write(), 0);
166        assert_eq!(b.available_read(), LEN);
167    }
168
169    #[test]
170    fn read() {
171        let mut b = Buf::new([0; LEN]);
172
173        assert_eq!(b.write(&DATA[0..4]), 4);
174
175        b.read(3, |data| {
176            assert_eq!(data, &DATA[0..3]);
177            Ok::<usize, Infallible>(3)
178        })
179        .unwrap();
180        b.read(1, |data| {
181            assert_eq!(data, &DATA[3..4]);
182            Ok::<usize, Infallible>(1)
183        })
184        .unwrap();
185        b.read(1, |data| {
186            assert_eq!(data, &[]);
187            Ok::<usize, Infallible>(1)
188        })
189        .unwrap();
190    }
191
192    #[test]
193    fn clear() {
194        let mut b = Buf::new([0; LEN]);
195
196        b.write(&DATA[0..2]);
197        b.clear();
198
199        assert_eq!(b.available_write(), LEN);
200        assert_eq!(b.available_read(), 0);
201    }
202
203    #[test]
204    fn discard() {
205        let mut b = Buf::new([0; LEN]);
206
207        assert_eq!(b.write(&DATA[0..4]), 4);
208        b.read(2, |data| {
209            assert_eq!(data, &DATA[0..2]);
210            Ok::<usize, Infallible>(2)
211        })
212        .unwrap();
213
214        assert_eq!(b.write(&DATA[4..7]), 3);
215        b.read(5, |data| {
216            assert_eq!(data, &DATA[2..7]);
217            Ok::<usize, Infallible>(5)
218        })
219        .unwrap();
220
221        assert_eq!(b.available_read(), 0);
222    }
223}