1use netstack3_base::{Payload, SackBlocks, SeqNum};
10
11use arrayvec::ArrayVec;
12use core::fmt::Debug;
13use core::ops::Range;
14use packet::InnerPacketBuilder;
15
16use crate::internal::base::BufferSizes;
17use crate::internal::seq_ranges::{SeqRange, SeqRanges};
18
19pub trait Buffer: Debug + Sized {
21 fn limits(&self) -> BufferLimits;
26
27 fn target_capacity(&self) -> usize;
39
40 fn request_capacity(&mut self, size: usize);
46}
47
48pub trait ReceiveBuffer: Buffer {
50 fn write_at<P: Payload>(&mut self, offset: usize, data: &P) -> usize;
54
55 fn make_readable(&mut self, count: usize, has_outstanding: bool);
66}
67
68pub trait SendBuffer: Buffer {
70 type Payload<'a>: InnerPacketBuilder + Payload + Debug + 'a;
72
73 fn mark_read(&mut self, count: usize);
80
81 fn peek_with<'a, F, R>(&'a mut self, offset: usize, f: F) -> R
89 where
90 F: FnOnce(Self::Payload<'a>) -> R;
91}
92
93#[derive(Eq, PartialEq, Debug, Copy, Clone)]
95pub struct BufferLimits {
96 pub capacity: usize,
98
99 pub len: usize,
101}
102
103#[derive(Debug)]
105#[cfg_attr(test, derive(PartialEq, Eq))]
106pub(super) struct Assembler {
107 nxt: SeqNum,
111 generation: usize,
115 outstanding: SeqRanges<usize>,
120}
121
122impl Assembler {
123 pub(crate) const MAX_NUM_OUTSTANDING_RANGES: usize = 64;
129
130 pub(super) fn new(nxt: SeqNum) -> Self {
132 Self { outstanding: SeqRanges::default(), generation: 0, nxt }
133 }
134
135 pub(super) fn nxt(&self) -> SeqNum {
137 self.nxt
138 }
139
140 pub(super) fn has_out_of_order(&self) -> bool {
143 !self.outstanding.is_empty()
144 }
145
146 pub(super) fn insert(&mut self, Range { start, end }: Range<SeqNum>) -> usize {
158 assert!(!start.after(end));
159 assert!(!start.before(self.nxt));
160 if start == end {
161 return 0;
162 }
163
164 let Self { outstanding, nxt, generation } = self;
165 *generation = *generation + 1;
166 let _: bool = outstanding.insert(start..end, *generation);
167
168 if let Some(advanced) = outstanding.pop_front_if(|r| r.start() == *nxt) {
169 *nxt = advanced.end();
170 usize::try_from(advanced.len()).unwrap()
171 } else {
172 if outstanding.len() > Self::MAX_NUM_OUTSTANDING_RANGES {
175 let _evicted: Option<SeqRange<usize>> = outstanding.pop_back();
176 }
177 0
178 }
179 }
180
181 pub(super) fn has_outstanding(&self) -> bool {
182 let Self { outstanding, nxt: _, generation: _ } = self;
183 !outstanding.is_empty()
184 }
185
186 pub(crate) fn sack_blocks(&self, size_limits: SackBlockSizeLimiters) -> SackBlocks {
202 let Self { nxt: _, generation: _, outstanding } = self;
203 if outstanding.is_empty() {
205 return SackBlocks::default();
206 }
207
208 let mut heap = ArrayVec::<&SeqRange<_>, { SackBlocks::MAX_BLOCKS }>::new();
212 let num_blocks_allowed = size_limits.num_blocks_allowed();
213
214 for block in outstanding.iter() {
215 if heap.len() >= num_blocks_allowed {
216 if heap.last().is_some_and(|l| l.meta() < block.meta()) {
217 let _: Option<_> = heap.pop();
219 } else {
220 continue;
223 }
224 }
225
226 heap.push(block);
227 heap.sort_by(|a, b| b.meta().cmp(&a.meta()))
229 }
230
231 SackBlocks::from_iter(heap.into_iter().map(|block| block.to_sack_block()))
232 }
233}
234
235pub(crate) struct SackBlockSizeLimiters {
236 pub(crate) timestamp_enabled: bool,
237}
238
239impl SackBlockSizeLimiters {
240 fn num_blocks_allowed(&self) -> usize {
241 let Self { timestamp_enabled } = self;
242 if *timestamp_enabled {
243 SackBlocks::MAX_BLOCKS_WITH_TIMESTAMP
244 } else {
245 SackBlocks::MAX_BLOCKS
246 }
247 }
248}
249
250pub trait IntoBuffers<R: ReceiveBuffer, S: SendBuffer> {
253 fn into_buffers(self, buffer_sizes: BufferSizes) -> (R, S);
255}
256
257#[cfg(any(test, feature = "testutils"))]
258impl<R: Default + ReceiveBuffer, S: Default + SendBuffer> IntoBuffers<R, S> for () {
259 fn into_buffers(self, buffer_sizes: BufferSizes) -> (R, S) {
260 let BufferSizes { send: _, receive: _ } = buffer_sizes;
262 Default::default()
263 }
264}
265
266#[cfg(any(test, feature = "testutils"))]
267pub(crate) mod testutil {
268 use super::*;
269
270 use alloc::sync::Arc;
271 use alloc::vec;
272 use alloc::vec::Vec;
273 use core::cmp;
274
275 use either::Either;
276 use netstack3_base::sync::Mutex;
277 use netstack3_base::{FragmentedPayload, PayloadLen, WindowSize};
278
279 use crate::internal::socket::accept_queue::ListenerNotifier;
280
281 #[derive(Clone, PartialEq, Eq)]
298 pub struct RingBuffer {
299 pub(super) storage: Vec<u8>,
300 pub(super) head: usize,
305 pub(super) len: usize,
310 }
311
312 impl Debug for RingBuffer {
313 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
314 let Self { storage, head, len } = self;
315 f.debug_struct("RingBuffer")
316 .field("storage (len, cap)", &(storage.len(), storage.capacity()))
317 .field("head", head)
318 .field("len", len)
319 .finish()
320 }
321 }
322
323 impl Default for RingBuffer {
324 fn default() -> Self {
325 Self::new(WindowSize::DEFAULT.into())
326 }
327 }
328
329 impl RingBuffer {
330 pub fn new(capacity: usize) -> Self {
332 Self { storage: vec![0; capacity], head: 0, len: 0 }
333 }
334
335 pub fn reset(&mut self) {
337 let Self { storage: _, head, len } = self;
338 *head = 0;
339 *len = 0;
340 }
341
342 fn with_readable<'a, F, R>(storage: &'a Vec<u8>, start: usize, len: usize, f: F) -> R
344 where
345 F: for<'b> FnOnce(&'b [&'a [u8]]) -> R,
346 {
347 let end = start + len;
349 if end > storage.len() {
350 let first_part = &storage[start..storage.len()];
351 let second_part = &storage[0..len - first_part.len()];
352 f(&[first_part, second_part][..])
353 } else {
354 let all_bytes = &storage[start..end];
355 f(&[all_bytes][..])
356 }
357 }
358
359 pub fn read_with<F>(&mut self, f: F) -> usize
367 where
368 F: for<'a, 'b> FnOnce(&'b [&'a [u8]]) -> usize,
369 {
370 let Self { storage, head, len } = self;
371 if storage.len() == 0 {
372 return f(&[&[]]);
373 }
374 let nread = RingBuffer::with_readable(storage, *head, *len, f);
375 assert!(nread <= *len);
376 *len -= nread;
377 *head = (*head + nread) % storage.len();
378 nread
379 }
380
381 pub fn writable_regions(&mut self) -> impl IntoIterator<Item = &mut [u8]> {
383 let BufferLimits { capacity, len } = self.limits();
384 let available = capacity - len;
385 let Self { storage, head, len } = self;
386
387 let mut write_start = *head + *len;
388 if write_start >= storage.len() {
389 write_start -= storage.len()
390 }
391 let write_end = write_start + available;
392 if write_end <= storage.len() {
393 Either::Left([&mut self.storage[write_start..write_end]].into_iter())
394 } else {
395 let (b1, b2) = self.storage[..].split_at_mut(write_start);
396 let b2_len = b2.len();
397 Either::Right([b2, &mut b1[..(available - b2_len)]].into_iter())
398 }
399 }
400 }
401
402 impl Buffer for RingBuffer {
403 fn limits(&self) -> BufferLimits {
404 let Self { storage, len, head: _ } = self;
405 let capacity = storage.len();
406 BufferLimits { len: *len, capacity }
407 }
408
409 fn target_capacity(&self) -> usize {
410 let Self { storage, len: _, head: _ } = self;
411 storage.len()
412 }
413
414 fn request_capacity(&mut self, size: usize) {
415 unimplemented!("capacity request for {size} not supported")
416 }
417 }
418
419 impl ReceiveBuffer for RingBuffer {
420 fn write_at<P: Payload>(&mut self, offset: usize, data: &P) -> usize {
421 let BufferLimits { capacity, len } = self.limits();
422 let available = capacity - len;
423 let Self { storage, head, len } = self;
424 if storage.len() == 0 {
425 return 0;
426 }
427
428 if offset > available {
429 return 0;
430 }
431 let start_at = (*head + *len + offset) % storage.len();
432 let to_write = cmp::min(data.len(), available);
433 let first_len = cmp::min(to_write, storage.len() - start_at);
435 data.partial_copy(0, &mut storage[start_at..start_at + first_len]);
436 if to_write > first_len {
439 data.partial_copy(first_len, &mut storage[0..to_write - first_len]);
440 }
441 to_write
442 }
443
444 fn make_readable(&mut self, count: usize, _has_outstanding: bool) {
445 let BufferLimits { capacity, len } = self.limits();
446 debug_assert!(count <= capacity - len);
447 self.len += count;
448 }
449 }
450
451 impl SendBuffer for RingBuffer {
452 type Payload<'a> = FragmentedPayload<'a, 2>;
453
454 fn mark_read(&mut self, count: usize) {
455 let Self { storage, head, len } = self;
456 assert!(count <= *len);
457 *len -= count;
458 *head = (*head + count) % storage.len();
459 }
460
461 fn peek_with<'a, F, R>(&'a mut self, offset: usize, f: F) -> R
462 where
463 F: FnOnce(Self::Payload<'a>) -> R,
464 {
465 let Self { storage, head, len } = self;
466 if storage.len() == 0 {
467 return f(FragmentedPayload::new_empty());
468 }
469 assert!(offset <= *len);
470 RingBuffer::with_readable(
471 storage,
472 (*head + offset) % storage.len(),
473 *len - offset,
474 |readable| f(readable.iter().map(|x| *x).collect()),
475 )
476 }
477 }
478
479 impl RingBuffer {
480 pub(crate) fn enqueue_data(&mut self, data: &[u8]) -> usize {
484 let nwritten = self.write_at(0, &data);
485 self.make_readable(nwritten, false);
486 nwritten
487 }
488 }
489
490 impl Buffer for Arc<Mutex<RingBuffer>> {
491 fn limits(&self) -> BufferLimits {
492 self.lock().limits()
493 }
494
495 fn target_capacity(&self) -> usize {
496 self.lock().target_capacity()
497 }
498
499 fn request_capacity(&mut self, size: usize) {
500 self.lock().request_capacity(size)
501 }
502 }
503
504 impl ReceiveBuffer for Arc<Mutex<RingBuffer>> {
505 fn write_at<P: Payload>(&mut self, offset: usize, data: &P) -> usize {
506 self.lock().write_at(offset, data)
507 }
508
509 fn make_readable(&mut self, count: usize, has_outstanding: bool) {
510 self.lock().make_readable(count, has_outstanding)
511 }
512 }
513
514 #[derive(Debug, Default)]
516 pub struct TestSendBuffer {
517 fake_stream: Arc<Mutex<Vec<u8>>>,
518 ring: RingBuffer,
519 }
520
521 impl TestSendBuffer {
522 pub fn new(fake_stream: Arc<Mutex<Vec<u8>>>, ring: RingBuffer) -> TestSendBuffer {
525 Self { fake_stream, ring }
526 }
527
528 pub fn enqueue_data(&mut self, data: &[u8]) {
530 self.fake_stream.lock().extend_from_slice(data);
531 }
532 }
533
534 impl Buffer for TestSendBuffer {
535 fn limits(&self) -> BufferLimits {
536 let Self { fake_stream, ring } = self;
537 let BufferLimits { capacity: ring_capacity, len: ring_len } = ring.limits();
538 let guard = fake_stream.lock();
539 let len = ring_len + guard.len();
540 let capacity = ring_capacity + guard.capacity();
541 BufferLimits { len, capacity }
542 }
543
544 fn target_capacity(&self) -> usize {
545 let Self { fake_stream: _, ring } = self;
546 ring.target_capacity()
547 }
548
549 fn request_capacity(&mut self, size: usize) {
550 let Self { fake_stream: _, ring } = self;
551 ring.request_capacity(size)
552 }
553 }
554
555 impl SendBuffer for TestSendBuffer {
556 type Payload<'a> = FragmentedPayload<'a, 2>;
557
558 fn mark_read(&mut self, count: usize) {
559 let Self { fake_stream: _, ring } = self;
560 ring.mark_read(count)
561 }
562
563 fn peek_with<'a, F, R>(&'a mut self, offset: usize, f: F) -> R
564 where
565 F: FnOnce(Self::Payload<'a>) -> R,
566 {
567 let Self { fake_stream, ring } = self;
568 let mut guard = fake_stream.lock();
569 if !guard.is_empty() {
570 let BufferLimits { capacity, len } = ring.limits();
572 let len = (capacity - len).min(guard.len());
573 let rest = guard.split_off(len);
574 let first = core::mem::replace(&mut *guard, rest);
575 assert_eq!(ring.enqueue_data(&first[..]), len);
576 }
577 ring.peek_with(offset, f)
578 }
579 }
580
581 fn arc_mutex_eq<T: PartialEq>(a: &Arc<Mutex<T>>, b: &Arc<Mutex<T>>) -> bool {
582 if Arc::ptr_eq(a, b) {
583 return true;
584 }
585 (&*a.lock()) == (&*b.lock())
586 }
587
588 #[derive(Clone, Debug, Default)]
590 pub struct ClientBuffers {
591 pub receive: Arc<Mutex<RingBuffer>>,
593 pub send: Arc<Mutex<Vec<u8>>>,
595 }
596
597 impl PartialEq for ClientBuffers {
598 fn eq(&self, ClientBuffers { receive: other_receive, send: other_send }: &Self) -> bool {
599 let Self { receive, send } = self;
600 arc_mutex_eq(receive, other_receive) && arc_mutex_eq(send, other_send)
601 }
602 }
603
604 impl Eq for ClientBuffers {}
605
606 impl ClientBuffers {
607 pub fn new(buffer_sizes: BufferSizes) -> Self {
609 let BufferSizes { send, receive } = buffer_sizes;
610 Self {
611 receive: Arc::new(Mutex::new(RingBuffer::new(receive))),
612 send: Arc::new(Mutex::new(Vec::with_capacity(send))),
613 }
614 }
615 }
616
617 #[derive(Debug, Clone, Eq, PartialEq)]
619 #[allow(missing_docs)]
620 pub enum ProvidedBuffers {
621 Buffers(WriteBackClientBuffers),
622 NoBuffers,
623 }
624
625 impl Default for ProvidedBuffers {
626 fn default() -> Self {
627 Self::NoBuffers
628 }
629 }
630
631 impl From<WriteBackClientBuffers> for ProvidedBuffers {
632 fn from(buffers: WriteBackClientBuffers) -> Self {
633 ProvidedBuffers::Buffers(buffers)
634 }
635 }
636
637 impl From<ProvidedBuffers> for WriteBackClientBuffers {
638 fn from(extra: ProvidedBuffers) -> Self {
639 match extra {
640 ProvidedBuffers::Buffers(buffers) => buffers,
641 ProvidedBuffers::NoBuffers => Default::default(),
642 }
643 }
644 }
645
646 impl From<ProvidedBuffers> for () {
647 fn from(_: ProvidedBuffers) -> Self {
648 ()
649 }
650 }
651
652 impl From<()> for ProvidedBuffers {
653 fn from(_: ()) -> Self {
654 Default::default()
655 }
656 }
657
658 #[derive(Debug, Default, Clone)]
661 pub struct WriteBackClientBuffers(pub Arc<Mutex<Option<ClientBuffers>>>);
662
663 impl PartialEq for WriteBackClientBuffers {
664 fn eq(&self, Self(other): &Self) -> bool {
665 let Self(this) = self;
666 arc_mutex_eq(this, other)
667 }
668 }
669
670 impl Eq for WriteBackClientBuffers {}
671
672 impl IntoBuffers<Arc<Mutex<RingBuffer>>, TestSendBuffer> for ProvidedBuffers {
673 fn into_buffers(
674 self,
675 buffer_sizes: BufferSizes,
676 ) -> (Arc<Mutex<RingBuffer>>, TestSendBuffer) {
677 let buffers = ClientBuffers::new(buffer_sizes);
678 if let ProvidedBuffers::Buffers(b) = self {
679 *b.0.as_ref().lock() = Some(buffers.clone());
680 }
681 let ClientBuffers { receive, send } = buffers;
682 (receive, TestSendBuffer::new(send, Default::default()))
683 }
684 }
685
686 impl ListenerNotifier for ProvidedBuffers {
687 fn new_incoming_connections(&mut self, _: usize) {}
688 }
689
690 #[derive(Debug)]
691 pub struct RepeatingPayload {
692 len: usize,
693 }
694
695 impl RepeatingPayload {
696 const REPEATING_BYTE: u8 = 0xAA;
697 }
698
699 impl PayloadLen for RepeatingPayload {
700 fn len(&self) -> usize {
701 self.len
702 }
703 }
704
705 impl Payload for RepeatingPayload {
706 fn slice(self, range: Range<u32>) -> Self {
707 Self { len: usize::try_from(range.end - range.start).unwrap() }
708 }
709
710 fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
711 assert!(offset < self.len);
712 assert_eq!(dst.len() - offset, self.len);
713 dst.fill(Self::REPEATING_BYTE);
714 }
715
716 fn partial_copy_uninit(&self, offset: usize, dst: &mut [core::mem::MaybeUninit<u8>]) {
717 assert!(offset < self.len);
718 assert_eq!(dst.len() - offset, self.len);
719 dst.fill(core::mem::MaybeUninit::new(Self::REPEATING_BYTE));
720 }
721
722 fn new_empty() -> Self {
723 Self { len: 0 }
724 }
725 }
726
727 impl InnerPacketBuilder for RepeatingPayload {
728 fn bytes_len(&self) -> usize {
729 self.len
730 }
731
732 fn serialize(&self, buffer: &mut [u8]) {
733 buffer.fill(Self::REPEATING_BYTE)
734 }
735 }
736
737 #[derive(Default, Debug, Eq, PartialEq)]
739 pub struct InfiniteSendBuffer;
740
741 impl InfiniteSendBuffer {
742 const LEN: usize = usize::MAX as usize;
743 }
744
745 impl Buffer for InfiniteSendBuffer {
746 fn limits(&self) -> BufferLimits {
747 BufferLimits { capacity: Self::LEN, len: Self::LEN }
748 }
749
750 fn target_capacity(&self) -> usize {
751 Self::LEN
752 }
753
754 fn request_capacity(&mut self, size: usize) {
755 unimplemented!("can't change capacity of infinite send buffer to {size}")
756 }
757 }
758
759 impl SendBuffer for InfiniteSendBuffer {
760 type Payload<'a> = RepeatingPayload;
761
762 fn mark_read(&mut self, _count: usize) {}
763
764 fn peek_with<'a, F, R>(&'a mut self, offset: usize, f: F) -> R
765 where
766 F: FnOnce(Self::Payload<'a>) -> R,
767 {
768 f(RepeatingPayload { len: Self::LEN - offset })
769 }
770 }
771
772 #[derive(Default, Debug, Eq, PartialEq)]
775 pub struct RepeatingSendBuffer(usize);
776
777 impl RepeatingSendBuffer {
778 pub fn new(length: usize) -> Self {
780 Self(length)
781 }
782 }
783
784 impl Buffer for RepeatingSendBuffer {
785 fn limits(&self) -> BufferLimits {
786 let Self(len) = self;
787 BufferLimits { capacity: usize::MAX, len: *len }
788 }
789
790 fn target_capacity(&self) -> usize {
791 usize::MAX
792 }
793
794 fn request_capacity(&mut self, size: usize) {
795 unimplemented!("can't change capacity of repeatable send buffer to {size}")
796 }
797 }
798
799 impl SendBuffer for RepeatingSendBuffer {
800 type Payload<'a> = RepeatingPayload;
801
802 fn mark_read(&mut self, count: usize) {
803 let Self(len) = self;
804 *len = *len - count;
805 }
806
807 fn peek_with<'a, F, R>(&'a mut self, offset: usize, f: F) -> R
808 where
809 F: FnOnce(Self::Payload<'a>) -> R,
810 {
811 let Self(len) = self;
812 f(RepeatingPayload { len: *len - offset })
813 }
814 }
815}
816
817#[cfg(test)]
818mod test {
819 use alloc::vec;
820 use alloc::vec::Vec;
821
822 use netstack3_base::FragmentedPayload;
823 use proptest::strategy::{Just, Strategy};
824 use proptest::test_runner::Config;
825 use proptest::{prop_assert, prop_assert_eq, proptest};
826 use proptest_support::failed_seeds_no_std;
827 use test_case::test_case;
828 use testutil::RingBuffer;
829
830 use super::*;
831
832 fn contains_range(assembler: &Assembler, range: Range<SeqNum>) -> bool {
833 assembler.outstanding.iter().any(|r| r.start() == range.start && r.end() == range.end)
834 }
835
836 proptest! {
837 #![proptest_config(Config {
838 failure_persistence: failed_seeds_no_std!(
840 "cc f621ca7d3a2b108e0dc41f7169ad028f4329b79e90e73d5f68042519a9f63999",
841 "cc c449aebed201b4ec4f137f3c224f20325f4cfee0b7fd596d9285176b6d811aa9"
842 ),
843 ..Config::default()
844 })]
845
846 #[test]
847 fn ring_buffer_make_readable((mut rb, avail) in ring_buffer::with_written()) {
848 let old_storage = rb.storage.clone();
849 let old_head = rb.head;
850 let old_len = rb.limits().len;
851 rb.make_readable(avail, false);
852 let RingBuffer { storage, head, len } = rb;
854 prop_assert_eq!(len, old_len + avail);
855 prop_assert_eq!(head, old_head);
856 prop_assert_eq!(storage, old_storage);
857 }
858
859 #[test]
860 fn ring_buffer_write_at((mut rb, offset, data) in ring_buffer::with_offset_data()) {
861 let old_head = rb.head;
862 let old_len = rb.limits().len;
863 prop_assert_eq!(rb.write_at(offset, &&data[..]), data.len());
864 prop_assert_eq!(rb.head, old_head);
865 prop_assert_eq!(rb.limits().len, old_len);
866 for i in 0..data.len() {
867 let masked = (rb.head + rb.len + offset + i) % rb.storage.len();
868 prop_assert_eq!(rb.storage[masked], data[i]);
870 rb.storage[masked] = 0;
871 }
872 prop_assert_eq!(&rb.storage, &vec![0; rb.storage.len()]);
874 }
875
876 #[test]
877 fn ring_buffer_read_with((mut rb, expected, consume) in ring_buffer::with_read_data()) {
878 prop_assert_eq!(rb.limits().len, expected.len());
879 let nread = rb.read_with(|readable| {
880 assert!(readable.len() == 1 || readable.len() == 2);
881 let got = readable.concat();
882 assert_eq!(got, expected);
883 consume
884 });
885 prop_assert_eq!(nread, consume);
886 prop_assert_eq!(rb.limits().len, expected.len() - consume);
887 }
888
889 #[test]
890 fn ring_buffer_mark_read((mut rb, readable) in ring_buffer::with_readable()) {
891 const BYTE_TO_WRITE: u8 = 0x42;
892 let written = rb.writable_regions().into_iter().fold(0, |acc, slice| {
893 slice.fill(BYTE_TO_WRITE);
894 acc + slice.len()
895 });
896 let old_storage = rb.storage.clone();
897 let old_head = rb.head;
898 let old_len = rb.limits().len;
899
900 rb.mark_read(readable);
901 let new_writable = rb.writable_regions().into_iter().fold(Vec::new(), |mut acc, slice| {
902 acc.extend_from_slice(slice);
903 acc
904 });
905 for (i, x) in new_writable.iter().enumerate().take(written) {
906 prop_assert_eq!(*x, BYTE_TO_WRITE, "i={}, rb={:?}", i, rb);
907 }
908 prop_assert!(new_writable.len() >= written);
909
910 let RingBuffer { storage, head, len } = rb;
911 prop_assert_eq!(len, old_len - readable);
912 prop_assert_eq!(head, (old_head + readable) % old_storage.len());
913 prop_assert_eq!(storage, old_storage);
914 }
915
916 #[test]
917 fn ring_buffer_peek_with((mut rb, expected, offset) in ring_buffer::with_read_data()) {
918 prop_assert_eq!(rb.limits().len, expected.len());
919 rb.peek_with(offset, |readable| {
920 prop_assert_eq!(readable.to_vec(), &expected[offset..]);
921 Ok(())
922 })?;
923 prop_assert_eq!(rb.limits().len, expected.len());
924 }
925
926 #[test]
927 fn ring_buffer_writable_regions(mut rb in ring_buffer::arb_ring_buffer()) {
928 const BYTE_TO_WRITE: u8 = 0x42;
929 let writable_len = rb.writable_regions().into_iter().fold(0, |acc, slice| {
930 slice.fill(BYTE_TO_WRITE);
931 acc + slice.len()
932 });
933 let BufferLimits {len, capacity} = rb.limits();
934 prop_assert_eq!(writable_len + len, capacity);
935 for i in 0..capacity {
936 let expected = if i < len {
937 0
938 } else {
939 BYTE_TO_WRITE
940 };
941 let idx = (rb.head + i) % rb.storage.len();
942 prop_assert_eq!(rb.storage[idx], expected);
943 }
944 }
945 }
946
947 #[test_case([Range { start: 0, end: 0 }]
948 => Assembler { outstanding: SeqRanges::default(), nxt: SeqNum::new(0), generation: 0 })]
949 #[test_case([Range { start: 0, end: 10 }]
950 => Assembler { outstanding: SeqRanges::default(), nxt: SeqNum::new(10), generation: 1 })]
951 #[test_case([Range{ start: 10, end: 15 }, Range { start: 5, end: 10 }]
952 => Assembler {
953 outstanding: [
954 SeqRange::new(SeqNum::new(5)..SeqNum::new(15), 2).unwrap()
955 ].into_iter().collect(),
956 nxt: SeqNum::new(0),
957 generation: 2,
958 })
959 ]
960 #[test_case([Range{ start: 10, end: 15 }, Range { start: 0, end: 5 }, Range { start: 5, end: 10 }]
961 => Assembler { outstanding: SeqRanges::default(), nxt: SeqNum::new(15), generation: 3 })]
962 #[test_case([Range{ start: 10, end: 15 }, Range { start: 5, end: 10 }, Range { start: 0, end: 5 }]
963 => Assembler { outstanding: SeqRanges::default(), nxt: SeqNum::new(15), generation: 3 })]
964 #[test_case([Range{ start: 10, end: 15 }, Range { start: 10, end: 15 }, Range { start: 11, end: 12 }]
965 => Assembler {
966 outstanding: [
967 SeqRange::new(SeqNum::new(10)..SeqNum::new(15), 3).unwrap()
968 ].into_iter().collect(),
969 nxt: SeqNum::new(0), generation: 3 })]
970 fn assembler_examples(ops: impl IntoIterator<Item = Range<u32>>) -> Assembler {
971 let mut assembler = Assembler::new(SeqNum::new(0));
972 for Range { start, end } in ops.into_iter() {
973 let _advanced = assembler.insert(SeqNum::new(start)..SeqNum::new(end));
974 }
975 assembler
976 }
977
978 #[test_case(&[] => Vec::<Range<u32>>::new(); "empty")]
979 #[test_case(&[1..2] => vec![1..2]; "single")]
980 #[test_case(&[1..2, 3..4] => vec![3..4, 1..2]; "latest first")]
981 #[test_case(&[1..2, 3..4, 5..6, 7..8, 9..10]
982 => vec![9..10, 7..8, 5..6, 3..4]; "max len")]
983 #[test_case(&[1..2, 3..4, 5..6, 7..8, 9..10, 6..7]
984 => vec![5..8, 9..10, 3..4, 1..2]; "gap fill")]
985 #[test_case(&[1..2, 3..4, 5..6, 7..8, 9..10, 1..8]
986 => vec![1..8, 9..10]; "large gap fill")]
987 fn assembler_sack_blocks(ops: &[Range<u32>]) -> Vec<Range<u32>> {
988 let mut assembler = Assembler::new(SeqNum::new(0));
989 for Range { start, end } in ops {
990 let _: usize = assembler.insert(SeqNum::new(*start)..SeqNum::new(*end));
991 }
992 assembler
993 .sack_blocks(SackBlockSizeLimiters { timestamp_enabled: false })
994 .try_iter()
995 .map(|r| r.expect("invalid block").into_range_u32())
996 .collect()
997 }
998
999 #[test_case(false => vec![10..11, 7..8, 4..5, 1..2]; "4_blocks_with_timestamp_disabled")]
1000 #[test_case(true => vec![10..11, 7..8, 4..5]; "3_blocks_with_timestamp_disabled")]
1001 fn assembler_sack_blocks_with_timestamp(timestamp_enabled: bool) -> Vec<Range<u32>> {
1002 let mut assembler = Assembler::new(SeqNum::new(0));
1003 for Range { start, end } in [1..2, 4..5, 7..8, 10..11] {
1004 let _: usize = assembler.insert(SeqNum::new(start)..SeqNum::new(end));
1005 }
1006 assembler
1007 .sack_blocks(SackBlockSizeLimiters { timestamp_enabled })
1008 .try_iter()
1009 .map(|r| r.expect("invalid_block").into_range_u32())
1010 .collect()
1011 }
1012
1013 #[test]
1015 fn assembler_max_outstanding_ranges() {
1016 const MAX: usize = Assembler::MAX_NUM_OUTSTANDING_RANGES;
1017
1018 const PERIOD: u32 = 20;
1020 const LEN: u32 = 10;
1021 const OFFSET: u32 = 10;
1022 let nth_range = |n| {
1023 SeqNum::new(PERIOD * (n as u32) + OFFSET)
1024 ..SeqNum::new(PERIOD * (n as u32) + OFFSET + LEN)
1025 };
1026
1027 let mut assembler = Assembler::new(SeqNum::new(0));
1029 for n in 0..MAX {
1030 assert_eq!(assembler.insert(nth_range(n)), 0);
1031 }
1032 assert_eq!(assembler.outstanding.len(), MAX);
1033 assert_eq!(assembler.outstanding.last().unwrap().start(), nth_range(MAX - 1).start);
1034
1035 assert_eq!(assembler.insert(nth_range(MAX)), 0);
1037 assert_eq!(assembler.outstanding.len(), MAX);
1038 assert_eq!(assembler.outstanding.last().unwrap().start(), nth_range(MAX - 1).start);
1039
1040 assert_eq!(assembler.insert(SeqNum::new(0)..SeqNum::new(1)), 1);
1043 assert_eq!(assembler.outstanding.len(), MAX);
1044 assert_eq!(assembler.outstanding.last().unwrap().start(), nth_range(MAX - 1).start);
1045
1046 let middle_disjoint = SeqNum::new(PERIOD + 2)..SeqNum::new(PERIOD + OFFSET - 2);
1049 assert_eq!(assembler.insert(middle_disjoint.clone()), 0);
1050 assert_eq!(assembler.outstanding.len(), MAX);
1051 assert_eq!(assembler.outstanding.last().unwrap().start(), nth_range(MAX - 2).start);
1052 assert!(contains_range(&assembler, middle_disjoint));
1053
1054 let extending_range1 = nth_range(10).end..nth_range(10).end + 1;
1057 assert_eq!(assembler.insert(extending_range1.clone()), 0);
1058 assert_eq!(assembler.outstanding.len(), MAX);
1059 assert!(contains_range(&assembler, nth_range(10).start..extending_range1.end));
1060
1061 let extending_range2 = extending_range1.start..nth_range(11).start;
1064 assert_eq!(assembler.insert(extending_range2), 0);
1065 assert_eq!(assembler.outstanding.len(), MAX - 1);
1066 assert!(contains_range(&assembler, nth_range(10).start..nth_range(11).end));
1067 }
1068
1069 #[test]
1070 fn ring_buffer_wrap_around() {
1072 const CAPACITY: usize = 16;
1073 let mut rb = RingBuffer::new(CAPACITY);
1074
1075 const BUF_SIZE: usize = 10;
1077 assert_eq!(rb.enqueue_data(&[0xAA; BUF_SIZE]), BUF_SIZE);
1078 rb.peek_with(0, |payload| {
1079 assert_eq!(payload, FragmentedPayload::new_contiguous(&[0xAA; BUF_SIZE]))
1080 });
1081 rb.mark_read(BUF_SIZE);
1082
1083 assert_eq!(rb.enqueue_data(&[0xBB; BUF_SIZE]), BUF_SIZE);
1085 rb.peek_with(0, |payload| {
1086 assert_eq!(
1087 payload,
1088 FragmentedPayload::new([
1089 &[0xBB; (CAPACITY - BUF_SIZE)],
1090 &[0xBB; (BUF_SIZE * 2 - CAPACITY)]
1091 ])
1092 )
1093 });
1094 rb.mark_read(BUF_SIZE);
1097
1098 assert_eq!(rb.enqueue_data(&[0xCC; BUF_SIZE]), BUF_SIZE);
1100 rb.peek_with(0, |payload| {
1101 assert_eq!(payload, FragmentedPayload::new_contiguous(&[0xCC; BUF_SIZE]))
1102 });
1103
1104 let read = rb.read_with(|segments| {
1107 assert_eq!(segments, [[0xCC; BUF_SIZE]]);
1108 BUF_SIZE
1109 });
1110 assert_eq!(read, BUF_SIZE);
1111 }
1112
1113 #[test]
1114 fn ring_buffer_example() {
1115 let mut rb = RingBuffer::new(16);
1116 assert_eq!(rb.write_at(5, &"World".as_bytes()), 5);
1117 assert_eq!(rb.write_at(0, &"Hello".as_bytes()), 5);
1118 rb.make_readable(10, false);
1119 assert_eq!(
1120 rb.read_with(|readable| {
1121 assert_eq!(readable, &["HelloWorld".as_bytes()]);
1122 5
1123 }),
1124 5
1125 );
1126 assert_eq!(
1127 rb.read_with(|readable| {
1128 assert_eq!(readable, &["World".as_bytes()]);
1129 readable[0].len()
1130 }),
1131 5
1132 );
1133 assert_eq!(rb.write_at(0, &"HelloWorld".as_bytes()), 10);
1134 rb.make_readable(10, false);
1135 assert_eq!(
1136 rb.read_with(|readable| {
1137 assert_eq!(readable, &["HelloW".as_bytes(), "orld".as_bytes()]);
1138 6
1139 }),
1140 6
1141 );
1142 assert_eq!(rb.limits().len, 4);
1143 assert_eq!(
1144 rb.read_with(|readable| {
1145 assert_eq!(readable, &["orld".as_bytes()]);
1146 4
1147 }),
1148 4
1149 );
1150 assert_eq!(rb.limits().len, 0);
1151
1152 assert_eq!(rb.enqueue_data("Hello".as_bytes()), 5);
1153 assert_eq!(rb.limits().len, 5);
1154
1155 rb.peek_with(3, |readable| {
1156 assert_eq!(readable.to_vec(), "lo".as_bytes());
1157 });
1158
1159 rb.mark_read(2);
1160
1161 rb.peek_with(0, |readable| {
1162 assert_eq!(readable.to_vec(), "llo".as_bytes());
1163 });
1164 }
1165
1166 mod ring_buffer {
1167 use super::*;
1168 const MAX_CAP: usize = 32;
1171
1172 fn arb_ring_buffer_args() -> impl Strategy<Value = (usize, usize, usize)> {
1173 (1..=MAX_CAP).prop_flat_map(|cap| {
1176 let max_len = cap;
1177 (Just(cap), 0..cap, 0..=max_len)
1179 })
1180 }
1181
1182 pub(super) fn arb_ring_buffer() -> impl Strategy<Value = RingBuffer> {
1183 arb_ring_buffer_args().prop_map(|(cap, head, len)| RingBuffer {
1184 storage: vec![0; cap],
1185 head,
1186 len,
1187 })
1188 }
1189
1190 pub(super) fn with_readable() -> impl Strategy<Value = (RingBuffer, usize)> {
1192 arb_ring_buffer_args().prop_flat_map(|(cap, head, len)| {
1193 (Just(RingBuffer { storage: vec![0; cap], head, len }), 0..=len)
1194 })
1195 }
1196
1197 pub(super) fn with_written() -> impl Strategy<Value = (RingBuffer, usize)> {
1199 arb_ring_buffer_args().prop_flat_map(|(cap, head, len)| {
1200 let rb = RingBuffer { storage: vec![0; cap], head, len };
1201 let max_written = cap - len;
1202 (Just(rb), 0..=max_written)
1203 })
1204 }
1205
1206 pub(super) fn with_offset_data() -> impl Strategy<Value = (RingBuffer, usize, Vec<u8>)> {
1208 arb_ring_buffer_args().prop_flat_map(|(cap, head, len)| {
1209 let writable_len = cap - len;
1210 (0..=writable_len).prop_flat_map(move |offset| {
1211 (0..=writable_len - offset).prop_flat_map(move |data_len| {
1212 (
1213 Just(RingBuffer { storage: vec![0; cap], head, len }),
1214 Just(offset),
1215 proptest::collection::vec(1..=u8::MAX, data_len),
1216 )
1217 })
1218 })
1219 })
1220 }
1221
1222 pub(super) fn with_read_data() -> impl Strategy<Value = (RingBuffer, Vec<u8>, usize)> {
1225 arb_ring_buffer_args().prop_flat_map(|(cap, head, len)| {
1226 proptest::collection::vec(1..=u8::MAX, len).prop_flat_map(move |data| {
1227 let mut rb = RingBuffer { storage: vec![0; cap], head, len: 0 };
1229 assert_eq!(rb.write_at(0, &&data[..]), len);
1230 rb.make_readable(len, false);
1231 (Just(rb), Just(data), 0..=len)
1232 })
1233 })
1234 }
1235 }
1236}