1use managed::ManagedSlice;
2
3use crate::storage::{Full, RingBuffer};
4
5use super::Empty;
6
7#[derive(Debug, Clone, Copy)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10pub struct PacketMetadata<H> {
11 size: usize,
12 header: Option<H>,
13}
14
15impl<H> PacketMetadata<H> {
16 pub const EMPTY: PacketMetadata<H> = PacketMetadata {
18 size: 0,
19 header: None,
20 };
21
22 fn padding(size: usize) -> PacketMetadata<H> {
23 PacketMetadata {
24 size: size,
25 header: None,
26 }
27 }
28
29 fn packet(size: usize, header: H) -> PacketMetadata<H> {
30 PacketMetadata {
31 size: size,
32 header: Some(header),
33 }
34 }
35
36 fn is_padding(&self) -> bool {
37 self.header.is_none()
38 }
39}
40
41#[derive(Debug)]
43pub struct PacketBuffer<'a, H: 'a> {
44 metadata_ring: RingBuffer<'a, PacketMetadata<H>>,
45 payload_ring: RingBuffer<'a, u8>,
46}
47
48impl<'a, H> PacketBuffer<'a, H> {
49 pub fn new<MS, PS>(metadata_storage: MS, payload_storage: PS) -> PacketBuffer<'a, H>
54 where
55 MS: Into<ManagedSlice<'a, PacketMetadata<H>>>,
56 PS: Into<ManagedSlice<'a, u8>>,
57 {
58 PacketBuffer {
59 metadata_ring: RingBuffer::new(metadata_storage),
60 payload_ring: RingBuffer::new(payload_storage),
61 }
62 }
63
64 pub fn is_empty(&self) -> bool {
66 self.metadata_ring.is_empty()
67 }
68
69 pub fn is_full(&self) -> bool {
71 self.metadata_ring.is_full()
72 }
73
74 pub fn enqueue(&mut self, size: usize, header: H) -> Result<&mut [u8], Full> {
81 if self.payload_ring.capacity() < size || self.metadata_ring.is_full() {
82 return Err(Full);
83 }
84
85 if self.payload_ring.is_empty() {
88 self.payload_ring.clear();
89 }
90
91 let window = self.payload_ring.window();
92 let contig_window = self.payload_ring.contiguous_window();
93
94 if window < size {
95 return Err(Full);
96 } else if contig_window < size {
97 if window - contig_window < size {
98 return Err(Full);
103 } else {
104 *self.metadata_ring.enqueue_one()? = PacketMetadata::padding(contig_window);
107 let _buf_enqueued = self.payload_ring.enqueue_many(contig_window);
110 }
111 }
112
113 *self.metadata_ring.enqueue_one()? = PacketMetadata::packet(size, header);
114
115 let payload_buf = self.payload_ring.enqueue_many(size);
116 debug_assert!(payload_buf.len() == size);
117 Ok(payload_buf)
118 }
119
120 pub fn enqueue_with_infallible<'b, F>(
123 &'b mut self,
124 max_size: usize,
125 header: H,
126 f: F,
127 ) -> Result<usize, Full>
128 where
129 F: FnOnce(&'b mut [u8]) -> usize,
130 {
131 if self.payload_ring.capacity() < max_size || self.metadata_ring.is_full() {
132 return Err(Full);
133 }
134
135 let window = self.payload_ring.window();
136 let contig_window = self.payload_ring.contiguous_window();
137
138 if window < max_size {
139 return Err(Full);
140 } else if contig_window < max_size {
141 if window - contig_window < max_size {
142 return Err(Full);
147 } else {
148 *self.metadata_ring.enqueue_one()? = PacketMetadata::padding(contig_window);
151 let _buf_enqueued = self.payload_ring.enqueue_many(contig_window);
154 }
155 }
156
157 let (size, _) = self
158 .payload_ring
159 .enqueue_many_with(|data| (f(&mut data[..max_size]), ()));
160
161 *self.metadata_ring.enqueue_one()? = PacketMetadata::packet(size, header);
162
163 Ok(size)
164 }
165
166 fn dequeue_padding(&mut self) {
167 let _ = self.metadata_ring.dequeue_one_with(|metadata| {
168 if metadata.is_padding() {
169 let _buf_dequeued = self.payload_ring.dequeue_many(metadata.size);
171 Ok(()) } else {
173 Err(()) }
175 });
176 }
177
178 pub fn dequeue_with<'c, R, E, F>(&'c mut self, f: F) -> Result<Result<R, E>, Empty>
181 where
182 F: FnOnce(&mut H, &'c mut [u8]) -> Result<R, E>,
183 {
184 self.dequeue_padding();
185
186 self.metadata_ring.dequeue_one_with(|metadata| {
187 self.payload_ring
188 .dequeue_many_with(|payload_buf| {
189 debug_assert!(payload_buf.len() >= metadata.size);
190
191 match f(
192 metadata.header.as_mut().unwrap(),
193 &mut payload_buf[..metadata.size],
194 ) {
195 Ok(val) => (metadata.size, Ok(val)),
196 Err(err) => (0, Err(err)),
197 }
198 })
199 .1
200 })
201 }
202
203 pub fn dequeue(&mut self) -> Result<(H, &mut [u8]), Empty> {
206 self.dequeue_padding();
207
208 let meta = self.metadata_ring.dequeue_one()?;
209
210 let payload_buf = self.payload_ring.dequeue_many(meta.size);
211 debug_assert!(payload_buf.len() == meta.size);
212 Ok((meta.header.take().unwrap(), payload_buf))
213 }
214
215 pub fn peek(&mut self) -> Result<(&H, &[u8]), Empty> {
220 self.dequeue_padding();
221
222 if let Some(metadata) = self.metadata_ring.get_allocated(0, 1).first() {
223 Ok((
224 metadata.header.as_ref().unwrap(),
225 self.payload_ring.get_allocated(0, metadata.size),
226 ))
227 } else {
228 Err(Empty)
229 }
230 }
231
232 pub fn packet_capacity(&self) -> usize {
234 self.metadata_ring.capacity()
235 }
236
237 pub fn payload_capacity(&self) -> usize {
239 self.payload_ring.capacity()
240 }
241
242 pub fn payload_bytes_count(&self) -> usize {
244 self.payload_ring.len()
245 }
246
247 #[allow(unused)]
249 pub(crate) fn reset(&mut self) {
250 self.payload_ring.clear();
251 self.metadata_ring.clear();
252 }
253}
254
255#[cfg(test)]
256mod test {
257 use super::*;
258
259 fn buffer() -> PacketBuffer<'static, ()> {
260 PacketBuffer::new(vec![PacketMetadata::EMPTY; 4], vec![0u8; 16])
261 }
262
263 #[test]
264 fn test_simple() {
265 let mut buffer = buffer();
266 buffer.enqueue(6, ()).unwrap().copy_from_slice(b"abcdef");
267 assert_eq!(buffer.enqueue(16, ()), Err(Full));
268 assert_eq!(buffer.metadata_ring.len(), 1);
269 assert_eq!(buffer.dequeue().unwrap().1, &b"abcdef"[..]);
270 assert_eq!(buffer.dequeue(), Err(Empty));
271 }
272
273 #[test]
274 fn test_peek() {
275 let mut buffer = buffer();
276 assert_eq!(buffer.peek(), Err(Empty));
277 buffer.enqueue(6, ()).unwrap().copy_from_slice(b"abcdef");
278 assert_eq!(buffer.metadata_ring.len(), 1);
279 assert_eq!(buffer.peek().unwrap().1, &b"abcdef"[..]);
280 assert_eq!(buffer.dequeue().unwrap().1, &b"abcdef"[..]);
281 assert_eq!(buffer.peek(), Err(Empty));
282 }
283
284 #[test]
285 fn test_padding() {
286 let mut buffer = buffer();
287 assert!(buffer.enqueue(6, ()).is_ok());
288 assert!(buffer.enqueue(8, ()).is_ok());
289 assert!(buffer.dequeue().is_ok());
290 buffer.enqueue(4, ()).unwrap().copy_from_slice(b"abcd");
291 assert_eq!(buffer.metadata_ring.len(), 3);
292 assert!(buffer.dequeue().is_ok());
293
294 assert_eq!(buffer.dequeue().unwrap().1, &b"abcd"[..]);
295 assert_eq!(buffer.metadata_ring.len(), 0);
296 }
297
298 #[test]
299 fn test_padding_with_large_payload() {
300 let mut buffer = buffer();
301 assert!(buffer.enqueue(12, ()).is_ok());
302 assert!(buffer.dequeue().is_ok());
303 buffer
304 .enqueue(12, ())
305 .unwrap()
306 .copy_from_slice(b"abcdefghijkl");
307 }
308
309 #[test]
310 fn test_dequeue_with() {
311 let mut buffer = buffer();
312 assert!(buffer.enqueue(6, ()).is_ok());
313 assert!(buffer.enqueue(8, ()).is_ok());
314 assert!(buffer.dequeue().is_ok());
315 buffer.enqueue(4, ()).unwrap().copy_from_slice(b"abcd");
316 assert_eq!(buffer.metadata_ring.len(), 3);
317 assert!(buffer.dequeue().is_ok());
318
319 assert!(matches!(
320 buffer.dequeue_with(|_, _| Result::<(), u32>::Err(123)),
321 Ok(Err(_))
322 ));
323 assert_eq!(buffer.metadata_ring.len(), 1);
324
325 assert!(
326 buffer
327 .dequeue_with(|&mut (), payload| {
328 assert_eq!(payload, &b"abcd"[..]);
329 Result::<(), ()>::Ok(())
330 })
331 .is_ok()
332 );
333 assert_eq!(buffer.metadata_ring.len(), 0);
334 }
335
336 #[test]
337 fn test_metadata_full_empty() {
338 let mut buffer = buffer();
339 assert!(buffer.is_empty());
340 assert!(!buffer.is_full());
341 assert!(buffer.enqueue(1, ()).is_ok());
342 assert!(!buffer.is_empty());
343 assert!(buffer.enqueue(1, ()).is_ok());
344 assert!(buffer.enqueue(1, ()).is_ok());
345 assert!(!buffer.is_full());
346 assert!(!buffer.is_empty());
347 assert!(buffer.enqueue(1, ()).is_ok());
348 assert!(buffer.is_full());
349 assert!(!buffer.is_empty());
350 assert_eq!(buffer.metadata_ring.len(), 4);
351 assert_eq!(buffer.enqueue(1, ()), Err(Full));
352 }
353
354 #[test]
355 fn test_window_too_small() {
356 let mut buffer = buffer();
357 assert!(buffer.enqueue(4, ()).is_ok());
358 assert!(buffer.enqueue(8, ()).is_ok());
359 assert!(buffer.dequeue().is_ok());
360 assert_eq!(buffer.enqueue(16, ()), Err(Full));
361 assert_eq!(buffer.metadata_ring.len(), 1);
362 }
363
364 #[test]
365 fn test_contiguous_window_too_small() {
366 let mut buffer = buffer();
367 assert!(buffer.enqueue(4, ()).is_ok());
368 assert!(buffer.enqueue(8, ()).is_ok());
369 assert!(buffer.dequeue().is_ok());
370 assert_eq!(buffer.enqueue(8, ()), Err(Full));
371 assert_eq!(buffer.metadata_ring.len(), 1);
372 }
373
374 #[test]
375 fn test_contiguous_window_wrap() {
376 let mut buffer = buffer();
377 assert!(buffer.enqueue(15, ()).is_ok());
378 assert!(buffer.dequeue().is_ok());
379 assert!(buffer.enqueue(16, ()).is_ok());
380 }
381
382 #[test]
383 fn test_capacity_too_small() {
384 let mut buffer = buffer();
385 assert_eq!(buffer.enqueue(32, ()), Err(Full));
386 }
387
388 #[test]
389 fn test_contig_window_prioritized() {
390 let mut buffer = buffer();
391 assert!(buffer.enqueue(4, ()).is_ok());
392 assert!(buffer.dequeue().is_ok());
393 assert!(buffer.enqueue(5, ()).is_ok());
394 }
395
396 #[test]
397 fn clear() {
398 let mut buffer = buffer();
399
400 assert!(buffer.is_empty());
402 assert!(buffer.enqueue(6, ()).is_ok());
403
404 assert!(!buffer.is_empty());
406 buffer.reset();
407 assert!(buffer.is_empty());
408 }
409}