1use core::borrow::{Borrow, BorrowMut};
2use core::{cmp, ptr};
3
4pub 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 pub fn clear(&mut self) {
27 self.rpos = 0;
28 self.wpos = 0;
29 }
30
31 pub fn available_read(&self) -> usize {
33 self.wpos - self.rpos
34 }
35
36 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 pub fn write(&mut self, data: &[u8]) -> usize {
47 if data.len() > self.available_write_without_discard() && self.rpos > 0 {
48 self.discard_already_read_data();
50 }
51
52 let count = cmp::min(self.available_write_without_discard(), data.len());
53 if count == 0 {
54 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 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 if max_count > self.available_write() {
76 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 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
125pub 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}