1use super::{
8 buf::{IoBuf, IoBufMut},
9 panic_advance,
10 pool::BufferPool,
11};
12use bytes::{Buf, BufMut, Bytes, BytesMut};
13use commonware_codec::{BufsMut, EncodeSize, Write};
14use std::{collections::VecDeque, io::IoSlice, num::NonZeroUsize};
15
16#[derive(Clone, Debug)]
18pub struct IoBufs {
19 inner: IoBufsInner,
20}
21
22#[derive(Clone, Debug)]
29enum IoBufsInner {
30 Single(IoBuf),
32 Pair([IoBuf; 2]),
34 Triple([IoBuf; 3]),
36 Chunked(VecDeque<IoBuf>),
38}
39
40impl Default for IoBufs {
41 fn default() -> Self {
42 Self {
43 inner: IoBufsInner::Single(IoBuf::default()),
44 }
45 }
46}
47
48impl IoBufs {
49 fn from_chunks_iter(chunks: impl IntoIterator<Item = IoBuf>) -> Self {
53 let mut iter = chunks.into_iter().filter(|buf| !buf.is_empty());
54 let first = match iter.next() {
55 Some(first) => first,
56 None => return Self::default(),
57 };
58 let second = match iter.next() {
59 Some(second) => second,
60 None => {
61 return Self {
62 inner: IoBufsInner::Single(first),
63 };
64 }
65 };
66 let third = match iter.next() {
67 Some(third) => third,
68 None => {
69 return Self {
70 inner: IoBufsInner::Pair([first, second]),
71 };
72 }
73 };
74 let fourth = match iter.next() {
75 Some(fourth) => fourth,
76 None => {
77 return Self {
78 inner: IoBufsInner::Triple([first, second, third]),
79 };
80 }
81 };
82
83 let mut bufs = VecDeque::with_capacity(4);
84 bufs.push_back(first);
85 bufs.push_back(second);
86 bufs.push_back(third);
87 bufs.push_back(fourth);
88 bufs.extend(iter);
89
90 Self {
91 inner: IoBufsInner::Chunked(bufs),
92 }
93 }
94
95 fn canonicalize(&mut self) {
97 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
98 self.inner = match inner {
99 IoBufsInner::Single(buf) => {
100 if buf.is_empty() {
101 IoBufsInner::Single(IoBuf::default())
102 } else {
103 IoBufsInner::Single(buf)
104 }
105 }
106 IoBufsInner::Pair([a, b]) => Self::from_chunks_iter([a, b]).inner,
107 IoBufsInner::Triple([a, b, c]) => Self::from_chunks_iter([a, b, c]).inner,
108 IoBufsInner::Chunked(bufs) => Self::from_chunks_iter(bufs).inner,
109 };
110 }
111
112 pub const fn as_single(&self) -> Option<&IoBuf> {
116 match &self.inner {
117 IoBufsInner::Single(buf) => Some(buf),
118 _ => None,
119 }
120 }
121
122 pub fn try_into_single(self) -> Result<IoBuf, Self> {
128 match self.inner {
129 IoBufsInner::Single(buf) => Ok(buf),
130 inner => Err(Self { inner }),
131 }
132 }
133
134 #[inline]
136 pub fn len(&self) -> usize {
137 self.remaining()
138 }
139
140 #[inline]
142 pub fn chunk_count(&self) -> usize {
143 match &self.inner {
145 IoBufsInner::Single(buf) => {
146 if buf.is_empty() {
147 0
148 } else {
149 1
150 }
151 }
152 IoBufsInner::Pair(_) => 2,
153 IoBufsInner::Triple(_) => 3,
154 IoBufsInner::Chunked(bufs) => bufs.len(),
155 }
156 }
157
158 #[inline]
160 pub fn is_empty(&self) -> bool {
161 self.remaining() == 0
162 }
163
164 #[inline]
168 pub const fn is_single(&self) -> bool {
169 matches!(self.inner, IoBufsInner::Single(_))
170 }
171
172 #[inline]
174 pub fn for_each_chunk(&self, mut f: impl FnMut(&[u8])) {
175 match &self.inner {
176 IoBufsInner::Single(buf) => {
177 let chunk = buf.as_ref();
178 if !chunk.is_empty() {
179 f(chunk);
180 }
181 }
182 IoBufsInner::Pair(pair) => {
183 for buf in pair {
184 let chunk = buf.as_ref();
185 if !chunk.is_empty() {
186 f(chunk);
187 }
188 }
189 }
190 IoBufsInner::Triple(triple) => {
191 for buf in triple {
192 let chunk = buf.as_ref();
193 if !chunk.is_empty() {
194 f(chunk);
195 }
196 }
197 }
198 IoBufsInner::Chunked(bufs) => {
199 for buf in bufs {
200 let chunk = buf.as_ref();
201 if !chunk.is_empty() {
202 f(chunk);
203 }
204 }
205 }
206 }
207 }
208
209 pub fn prepend(&mut self, buf: IoBuf) {
213 if buf.is_empty() {
214 return;
215 }
216 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
217 self.inner = match inner {
218 IoBufsInner::Single(existing) if existing.is_empty() => IoBufsInner::Single(buf),
219 IoBufsInner::Single(existing) => IoBufsInner::Pair([buf, existing]),
220 IoBufsInner::Pair([a, b]) => IoBufsInner::Triple([buf, a, b]),
221 IoBufsInner::Triple([a, b, c]) => {
222 let mut bufs = VecDeque::with_capacity(4);
223 bufs.push_back(buf);
224 bufs.push_back(a);
225 bufs.push_back(b);
226 bufs.push_back(c);
227 IoBufsInner::Chunked(bufs)
228 }
229 IoBufsInner::Chunked(mut bufs) => {
230 bufs.push_front(buf);
231 IoBufsInner::Chunked(bufs)
232 }
233 };
234 }
235
236 pub fn append(&mut self, buf: IoBuf) {
240 if buf.is_empty() {
241 return;
242 }
243 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
244 self.inner = match inner {
245 IoBufsInner::Single(existing) if existing.is_empty() => IoBufsInner::Single(buf),
246 IoBufsInner::Single(existing) => IoBufsInner::Pair([existing, buf]),
247 IoBufsInner::Pair([a, b]) => IoBufsInner::Triple([a, b, buf]),
248 IoBufsInner::Triple([a, b, c]) => {
249 let mut bufs = VecDeque::with_capacity(4);
250 bufs.push_back(a);
251 bufs.push_back(b);
252 bufs.push_back(c);
253 bufs.push_back(buf);
254 IoBufsInner::Chunked(bufs)
255 }
256 IoBufsInner::Chunked(mut bufs) => {
257 bufs.push_back(buf);
258 IoBufsInner::Chunked(bufs)
259 }
260 };
261 }
262
263 pub fn split_to(&mut self, at: usize) -> Self {
275 if at == 0 {
276 return Self::default();
277 }
278
279 let remaining = self.remaining();
280 assert!(
281 at <= remaining,
282 "split_to out of bounds: {:?} <= {:?}",
283 at,
284 remaining,
285 );
286
287 if at == remaining {
288 return std::mem::take(self);
289 }
290
291 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
292 match inner {
293 IoBufsInner::Single(mut buf) => {
294 let prefix = buf.split_to(at);
296 self.inner = IoBufsInner::Single(buf);
297 Self::from(prefix)
298 }
299 IoBufsInner::Pair([mut a, mut b]) => {
300 let a_len = a.remaining();
301 if at < a_len {
302 let prefix = a.split_to(at);
304 self.inner = IoBufsInner::Pair([a, b]);
305 return Self::from(prefix);
306 }
307 if at == a_len {
308 self.inner = IoBufsInner::Single(b);
310 return Self::from(a);
311 }
312
313 let b_prefix_len = at - a_len;
315 let b_prefix = b.split_to(b_prefix_len);
316 self.inner = IoBufsInner::Single(b);
317 Self {
318 inner: IoBufsInner::Pair([a, b_prefix]),
319 }
320 }
321 IoBufsInner::Triple([mut a, mut b, mut c]) => {
322 let a_len = a.remaining();
323 if at < a_len {
324 let prefix = a.split_to(at);
326 self.inner = IoBufsInner::Triple([a, b, c]);
327 return Self::from(prefix);
328 }
329 if at == a_len {
330 self.inner = IoBufsInner::Pair([b, c]);
332 return Self::from(a);
333 }
334
335 let mut remaining = at - a_len;
336 let b_len = b.remaining();
337 if remaining < b_len {
338 let b_prefix = b.split_to(remaining);
340 self.inner = IoBufsInner::Pair([b, c]);
341 return Self {
342 inner: IoBufsInner::Pair([a, b_prefix]),
343 };
344 }
345 if remaining == b_len {
346 self.inner = IoBufsInner::Single(c);
348 return Self {
349 inner: IoBufsInner::Pair([a, b]),
350 };
351 }
352
353 remaining -= b_len;
355 let c_prefix = c.split_to(remaining);
356 self.inner = IoBufsInner::Single(c);
357 Self {
358 inner: IoBufsInner::Triple([a, b, c_prefix]),
359 }
360 }
361 IoBufsInner::Chunked(mut bufs) => {
362 let mut remaining = at;
363 let mut out = VecDeque::new();
364
365 while remaining > 0 {
366 let mut front = bufs.pop_front().expect("split_to out of bounds");
367 let avail = front.remaining();
368 if avail == 0 {
369 continue;
371 }
372 if remaining < avail {
373 let prefix = front.split_to(remaining);
375 out.push_back(prefix);
376 bufs.push_front(front);
377 break;
378 }
379
380 out.push_back(front);
382 remaining -= avail;
383 }
384
385 self.inner = if bufs.len() >= 4 {
386 IoBufsInner::Chunked(bufs)
387 } else {
388 Self::from_chunks_iter(bufs).inner
389 };
390
391 if out.len() >= 4 {
392 Self {
393 inner: IoBufsInner::Chunked(out),
394 }
395 } else {
396 Self::from_chunks_iter(out)
397 }
398 }
399 }
400 }
401
402 #[inline]
408 pub fn coalesce(self) -> IoBuf {
409 match self.inner {
410 IoBufsInner::Single(buf) => buf,
411 inner => {
412 let bufs = Self { inner };
413 let mut out = IoBufMut::with_capacity(bufs.remaining());
414 bufs.for_each_chunk(|chunk| out.put_slice(chunk));
415 out.freeze()
416 }
417 }
418 }
419
420 pub fn coalesce_with_pool(self, pool: &BufferPool) -> IoBuf {
425 match self.inner {
426 IoBufsInner::Single(buf) => buf,
427 IoBufsInner::Pair([a, b]) => {
428 let total_len = a.remaining().saturating_add(b.remaining());
429 let mut result = pool.alloc(total_len);
430 result.put_slice(a.as_ref());
431 result.put_slice(b.as_ref());
432 result.freeze()
433 }
434 IoBufsInner::Triple([a, b, c]) => {
435 let total_len = a
436 .remaining()
437 .saturating_add(b.remaining())
438 .saturating_add(c.remaining());
439 let mut result = pool.alloc(total_len);
440 result.put_slice(a.as_ref());
441 result.put_slice(b.as_ref());
442 result.put_slice(c.as_ref());
443 result.freeze()
444 }
445 IoBufsInner::Chunked(bufs) => {
446 let total_len: usize = bufs
447 .iter()
448 .map(|b| b.remaining())
449 .fold(0, usize::saturating_add);
450 let mut result = pool.alloc(total_len);
451 for buf in bufs {
452 result.put_slice(buf.as_ref());
453 }
454 result.freeze()
455 }
456 }
457 }
458}
459
460impl Buf for IoBufs {
461 #[inline]
462 fn remaining(&self) -> usize {
463 match &self.inner {
464 IoBufsInner::Single(buf) => buf.remaining(),
465 IoBufsInner::Pair([a, b]) => a.remaining().saturating_add(b.remaining()),
466 IoBufsInner::Triple([a, b, c]) => a
467 .remaining()
468 .saturating_add(b.remaining())
469 .saturating_add(c.remaining()),
470 IoBufsInner::Chunked(bufs) => bufs
471 .iter()
472 .map(|b| b.remaining())
473 .fold(0, usize::saturating_add),
474 }
475 }
476
477 #[inline]
478 fn chunk(&self) -> &[u8] {
479 match &self.inner {
480 IoBufsInner::Single(buf) => buf.chunk(),
481 IoBufsInner::Pair([a, b]) => {
482 if a.remaining() > 0 {
483 a.chunk()
484 } else if b.remaining() > 0 {
485 b.chunk()
486 } else {
487 &[]
488 }
489 }
490 IoBufsInner::Triple([a, b, c]) => {
491 if a.remaining() > 0 {
492 a.chunk()
493 } else if b.remaining() > 0 {
494 b.chunk()
495 } else if c.remaining() > 0 {
496 c.chunk()
497 } else {
498 &[]
499 }
500 }
501 IoBufsInner::Chunked(bufs) => {
502 for buf in bufs.iter() {
503 if buf.remaining() > 0 {
504 return buf.chunk();
505 }
506 }
507 &[]
508 }
509 }
510 }
511
512 #[inline]
513 fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
514 if dst.is_empty() {
515 return 0;
516 }
517
518 match &self.inner {
519 IoBufsInner::Single(buf) => {
520 let chunk = buf.chunk();
521 if !chunk.is_empty() {
522 dst[0] = IoSlice::new(chunk);
523 return 1;
524 }
525 0
526 }
527 IoBufsInner::Pair([a, b]) => fill_vectored_from_chunks(dst, [a.chunk(), b.chunk()]),
528 IoBufsInner::Triple([a, b, c]) => {
529 fill_vectored_from_chunks(dst, [a.chunk(), b.chunk(), c.chunk()])
530 }
531 IoBufsInner::Chunked(bufs) => {
532 fill_vectored_from_chunks(dst, bufs.iter().map(|buf| buf.chunk()))
533 }
534 }
535 }
536
537 #[inline]
538 fn advance(&mut self, cnt: usize) {
539 let should_canonicalize = match &mut self.inner {
540 IoBufsInner::Single(buf) => {
541 buf.advance(cnt);
542 false
543 }
544 IoBufsInner::Pair(pair) => advance_small_chunks(pair.as_mut_slice(), cnt),
545 IoBufsInner::Triple(triple) => advance_small_chunks(triple.as_mut_slice(), cnt),
546 IoBufsInner::Chunked(bufs) => {
547 advance_chunked_front(bufs, cnt);
548 bufs.len() <= 3
549 }
550 };
551
552 if should_canonicalize {
553 self.canonicalize();
554 }
555 }
556
557 #[inline]
558 fn copy_to_bytes(&mut self, len: usize) -> Bytes {
559 let (result, needs_canonicalize) = match &mut self.inner {
560 IoBufsInner::Single(buf) => return buf.copy_to_bytes(len),
561 IoBufsInner::Pair(pair) => {
562 copy_to_bytes_small_chunks(pair, len, "IoBufs::copy_to_bytes: not enough data")
563 }
564 IoBufsInner::Triple(triple) => {
565 copy_to_bytes_small_chunks(triple, len, "IoBufs::copy_to_bytes: not enough data")
566 }
567 IoBufsInner::Chunked(bufs) => {
568 copy_to_bytes_chunked(bufs, len, "IoBufs::copy_to_bytes: not enough data")
569 }
570 };
571
572 if needs_canonicalize {
573 self.canonicalize();
574 }
575
576 result
577 }
578}
579
580impl From<IoBuf> for IoBufs {
582 fn from(buf: IoBuf) -> Self {
583 Self {
584 inner: IoBufsInner::Single(buf),
585 }
586 }
587}
588
589impl From<IoBufMut> for IoBufs {
591 fn from(buf: IoBufMut) -> Self {
592 Self {
593 inner: IoBufsInner::Single(buf.freeze()),
594 }
595 }
596}
597
598impl From<Bytes> for IoBufs {
600 fn from(bytes: Bytes) -> Self {
601 Self::from(IoBuf::from(bytes))
602 }
603}
604
605impl From<BytesMut> for IoBufs {
607 fn from(bytes: BytesMut) -> Self {
608 Self::from(IoBuf::from(bytes))
609 }
610}
611
612impl From<Vec<u8>> for IoBufs {
614 fn from(vec: Vec<u8>) -> Self {
615 Self::from(IoBuf::from(vec))
616 }
617}
618
619impl From<Vec<IoBuf>> for IoBufs {
621 fn from(bufs: Vec<IoBuf>) -> Self {
622 Self::from_chunks_iter(bufs)
623 }
624}
625
626impl<const N: usize> From<&'static [u8; N]> for IoBufs {
628 fn from(array: &'static [u8; N]) -> Self {
629 Self::from(IoBuf::from(array))
630 }
631}
632
633impl From<&'static [u8]> for IoBufs {
635 fn from(slice: &'static [u8]) -> Self {
636 Self::from(IoBuf::from(slice))
637 }
638}
639
640#[derive(Debug)]
665pub struct IoBufsMut {
666 inner: IoBufsMutInner,
667}
668
669#[derive(Debug)]
678enum IoBufsMutInner {
679 Single(IoBufMut),
681 Pair([IoBufMut; 2]),
683 Triple([IoBufMut; 3]),
685 Chunked(VecDeque<IoBufMut>),
687}
688
689impl Default for IoBufsMut {
690 fn default() -> Self {
691 Self {
692 inner: IoBufsMutInner::Single(IoBufMut::default()),
693 }
694 }
695}
696
697impl IoBufsMut {
698 fn from_chunks_iter(chunks: impl IntoIterator<Item = IoBufMut>) -> Self {
703 let mut iter = chunks.into_iter();
704 let first = match iter.next() {
705 Some(first) => first,
706 None => return Self::default(),
707 };
708 let second = match iter.next() {
709 Some(second) => second,
710 None => {
711 return Self {
712 inner: IoBufsMutInner::Single(first),
713 };
714 }
715 };
716 let third = match iter.next() {
717 Some(third) => third,
718 None => {
719 return Self {
720 inner: IoBufsMutInner::Pair([first, second]),
721 };
722 }
723 };
724 let fourth = match iter.next() {
725 Some(fourth) => fourth,
726 None => {
727 return Self {
728 inner: IoBufsMutInner::Triple([first, second, third]),
729 };
730 }
731 };
732
733 let mut bufs = VecDeque::with_capacity(4);
734 bufs.push_back(first);
735 bufs.push_back(second);
736 bufs.push_back(third);
737 bufs.push_back(fourth);
738 bufs.extend(iter);
739 Self {
740 inner: IoBufsMutInner::Chunked(bufs),
741 }
742 }
743
744 fn from_writable_chunks_iter(chunks: impl IntoIterator<Item = IoBufMut>) -> Self {
751 Self::from_chunks_iter(chunks.into_iter().filter(|buf| buf.capacity() > 0))
752 }
753
754 fn canonicalize(&mut self) {
761 let inner = std::mem::replace(&mut self.inner, IoBufsMutInner::Single(IoBufMut::default()));
762 self.inner = match inner {
763 IoBufsMutInner::Single(buf) => IoBufsMutInner::Single(buf),
764 IoBufsMutInner::Pair([a, b]) => Self::from_writable_chunks_iter([a, b]).inner,
765 IoBufsMutInner::Triple([a, b, c]) => Self::from_writable_chunks_iter([a, b, c]).inner,
766 IoBufsMutInner::Chunked(bufs) => Self::from_writable_chunks_iter(bufs).inner,
767 };
768 }
769
770 #[inline]
771 fn for_each_chunk_mut(&mut self, mut f: impl FnMut(&mut IoBufMut)) {
772 match &mut self.inner {
773 IoBufsMutInner::Single(buf) => f(buf),
774 IoBufsMutInner::Pair(pair) => {
775 for buf in pair.iter_mut() {
776 f(buf);
777 }
778 }
779 IoBufsMutInner::Triple(triple) => {
780 for buf in triple.iter_mut() {
781 f(buf);
782 }
783 }
784 IoBufsMutInner::Chunked(bufs) => {
785 for buf in bufs.iter_mut() {
786 f(buf);
787 }
788 }
789 }
790 }
791
792 pub const fn as_single(&self) -> Option<&IoBufMut> {
796 match &self.inner {
797 IoBufsMutInner::Single(buf) => Some(buf),
798 _ => None,
799 }
800 }
801
802 pub const fn as_single_mut(&mut self) -> Option<&mut IoBufMut> {
806 match &mut self.inner {
807 IoBufsMutInner::Single(buf) => Some(buf),
808 _ => None,
809 }
810 }
811
812 #[allow(clippy::result_large_err)]
817 pub fn try_into_single(self) -> Result<IoBufMut, Self> {
818 match self.inner {
819 IoBufsMutInner::Single(buf) => Ok(buf),
820 inner => Err(Self { inner }),
821 }
822 }
823
824 #[inline]
826 pub fn len(&self) -> usize {
827 self.remaining()
828 }
829
830 #[inline]
832 pub fn is_empty(&self) -> bool {
833 self.remaining() == 0
834 }
835
836 #[inline]
840 pub const fn is_single(&self) -> bool {
841 matches!(self.inner, IoBufsMutInner::Single(_))
842 }
843
844 pub fn freeze(self) -> IoBufs {
846 match self.inner {
847 IoBufsMutInner::Single(buf) => IoBufs::from(buf.freeze()),
848 IoBufsMutInner::Pair([a, b]) => IoBufs::from_chunks_iter([a.freeze(), b.freeze()]),
849 IoBufsMutInner::Triple([a, b, c]) => {
850 IoBufs::from_chunks_iter([a.freeze(), b.freeze(), c.freeze()])
851 }
852 IoBufsMutInner::Chunked(bufs) => {
853 IoBufs::from_chunks_iter(bufs.into_iter().map(IoBufMut::freeze))
854 }
855 }
856 }
857
858 fn coalesce_with<F>(self, allocate: F) -> IoBufMut
859 where
860 F: FnOnce(usize) -> IoBufMut,
861 {
862 match self.inner {
863 IoBufsMutInner::Single(buf) => buf,
864 IoBufsMutInner::Pair([a, b]) => {
865 let total_len = a.len().saturating_add(b.len());
866 let mut result = allocate(total_len);
867 result.put_slice(a.as_ref());
868 result.put_slice(b.as_ref());
869 result
870 }
871 IoBufsMutInner::Triple([a, b, c]) => {
872 let total_len = a.len().saturating_add(b.len()).saturating_add(c.len());
873 let mut result = allocate(total_len);
874 result.put_slice(a.as_ref());
875 result.put_slice(b.as_ref());
876 result.put_slice(c.as_ref());
877 result
878 }
879 IoBufsMutInner::Chunked(bufs) => {
880 let total_len: usize = bufs.iter().map(|b| b.len()).fold(0, usize::saturating_add);
881 let mut result = allocate(total_len);
882 for buf in bufs {
883 result.put_slice(buf.as_ref());
884 }
885 result
886 }
887 }
888 }
889
890 pub fn coalesce(self) -> IoBufMut {
894 self.coalesce_with(IoBufMut::with_capacity)
895 }
896
897 pub fn coalesce_with_pool(self, pool: &BufferPool) -> IoBufMut {
902 self.coalesce_with(|len| pool.alloc(len))
903 }
904
905 pub fn coalesce_with_pool_extra(self, pool: &BufferPool, extra: usize) -> IoBufMut {
910 match self.inner {
911 IoBufsMutInner::Single(buf) if buf.capacity() - buf.len() >= extra => buf,
912 IoBufsMutInner::Single(buf) => {
913 let mut result = pool.alloc(buf.len() + extra);
914 result.put_slice(buf.as_ref());
915 result
916 }
917 IoBufsMutInner::Pair([a, b]) => {
918 let total = a.len().saturating_add(b.len());
919 let mut result = pool.alloc(total + extra);
920 result.put_slice(a.as_ref());
921 result.put_slice(b.as_ref());
922 result
923 }
924 IoBufsMutInner::Triple([a, b, c]) => {
925 let total = a.len().saturating_add(b.len()).saturating_add(c.len());
926 let mut result = pool.alloc(total + extra);
927 result.put_slice(a.as_ref());
928 result.put_slice(b.as_ref());
929 result.put_slice(c.as_ref());
930 result
931 }
932 IoBufsMutInner::Chunked(bufs) => {
933 let total: usize = bufs.iter().map(|b| b.len()).fold(0, usize::saturating_add);
934 let mut result = pool.alloc(total + extra);
935 for buf in bufs {
936 result.put_slice(buf.as_ref());
937 }
938 result
939 }
940 }
941 }
942
943 pub fn capacity(&self) -> usize {
945 match &self.inner {
946 IoBufsMutInner::Single(buf) => buf.capacity(),
947 IoBufsMutInner::Pair([a, b]) => a.capacity().saturating_add(b.capacity()),
948 IoBufsMutInner::Triple([a, b, c]) => a
949 .capacity()
950 .saturating_add(b.capacity())
951 .saturating_add(c.capacity()),
952 IoBufsMutInner::Chunked(bufs) => bufs
953 .iter()
954 .map(|b| b.capacity())
955 .fold(0, usize::saturating_add),
956 }
957 }
958
959 pub(crate) unsafe fn set_len(&mut self, len: usize) {
973 let capacity = self.capacity();
974 assert!(
975 len <= capacity,
976 "set_len({len}) exceeds capacity({capacity})"
977 );
978 let mut remaining = len;
979 self.for_each_chunk_mut(|buf| {
980 let cap = buf.capacity();
981 let to_set = remaining.min(cap);
982 unsafe { buf.set_len(to_set) };
985 remaining -= to_set;
986 });
987 }
988
989 pub fn copy_from_slice(&mut self, src: &[u8]) {
995 assert_eq!(
996 src.len(),
997 self.len(),
998 "source slice length must match buffer length"
999 );
1000 let mut offset = 0;
1001 self.for_each_chunk_mut(|buf| {
1002 let len = buf.len();
1003 buf.as_mut().copy_from_slice(&src[offset..offset + len]);
1004 offset += len;
1005 });
1006 }
1007}
1008
1009impl Buf for IoBufsMut {
1010 #[inline]
1011 fn remaining(&self) -> usize {
1012 match &self.inner {
1013 IoBufsMutInner::Single(buf) => buf.remaining(),
1014 IoBufsMutInner::Pair([a, b]) => a.remaining().saturating_add(b.remaining()),
1015 IoBufsMutInner::Triple([a, b, c]) => a
1016 .remaining()
1017 .saturating_add(b.remaining())
1018 .saturating_add(c.remaining()),
1019 IoBufsMutInner::Chunked(bufs) => bufs
1020 .iter()
1021 .map(|b| b.remaining())
1022 .fold(0, usize::saturating_add),
1023 }
1024 }
1025
1026 #[inline]
1027 fn chunk(&self) -> &[u8] {
1028 match &self.inner {
1029 IoBufsMutInner::Single(buf) => buf.chunk(),
1030 IoBufsMutInner::Pair([a, b]) => {
1031 if a.remaining() > 0 {
1032 a.chunk()
1033 } else if b.remaining() > 0 {
1034 b.chunk()
1035 } else {
1036 &[]
1037 }
1038 }
1039 IoBufsMutInner::Triple([a, b, c]) => {
1040 if a.remaining() > 0 {
1041 a.chunk()
1042 } else if b.remaining() > 0 {
1043 b.chunk()
1044 } else if c.remaining() > 0 {
1045 c.chunk()
1046 } else {
1047 &[]
1048 }
1049 }
1050 IoBufsMutInner::Chunked(bufs) => {
1051 for buf in bufs.iter() {
1052 if buf.remaining() > 0 {
1053 return buf.chunk();
1054 }
1055 }
1056 &[]
1057 }
1058 }
1059 }
1060
1061 #[inline]
1062 fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
1063 if dst.is_empty() {
1064 return 0;
1065 }
1066
1067 match &self.inner {
1068 IoBufsMutInner::Single(buf) => {
1069 let chunk = buf.chunk();
1070 if !chunk.is_empty() {
1071 dst[0] = IoSlice::new(chunk);
1072 return 1;
1073 }
1074 0
1075 }
1076 IoBufsMutInner::Pair([a, b]) => fill_vectored_from_chunks(dst, [a.chunk(), b.chunk()]),
1077 IoBufsMutInner::Triple([a, b, c]) => {
1078 fill_vectored_from_chunks(dst, [a.chunk(), b.chunk(), c.chunk()])
1079 }
1080 IoBufsMutInner::Chunked(bufs) => {
1081 fill_vectored_from_chunks(dst, bufs.iter().map(|buf| buf.chunk()))
1082 }
1083 }
1084 }
1085
1086 #[inline]
1087 fn advance(&mut self, cnt: usize) {
1088 let should_canonicalize = match &mut self.inner {
1089 IoBufsMutInner::Single(buf) => {
1090 buf.advance(cnt);
1091 false
1092 }
1093 IoBufsMutInner::Pair(pair) => advance_small_chunks(pair.as_mut_slice(), cnt),
1094 IoBufsMutInner::Triple(triple) => advance_small_chunks(triple.as_mut_slice(), cnt),
1095 IoBufsMutInner::Chunked(bufs) => {
1096 advance_chunked_front(bufs, cnt);
1097 bufs.len() <= 3
1098 }
1099 };
1100
1101 if should_canonicalize {
1102 self.canonicalize();
1103 }
1104 }
1105
1106 #[inline]
1107 fn copy_to_bytes(&mut self, len: usize) -> Bytes {
1108 if len == 0 {
1112 return Bytes::new();
1113 }
1114 let (result, needs_canonicalize) = match &mut self.inner {
1115 IoBufsMutInner::Single(buf) => return buf.copy_to_bytes(len),
1116 IoBufsMutInner::Pair(pair) => {
1117 copy_to_bytes_small_chunks(pair, len, "IoBufsMut::copy_to_bytes: not enough data")
1118 }
1119 IoBufsMutInner::Triple(triple) => {
1120 copy_to_bytes_small_chunks(triple, len, "IoBufsMut::copy_to_bytes: not enough data")
1121 }
1122 IoBufsMutInner::Chunked(bufs) => {
1123 copy_to_bytes_chunked(bufs, len, "IoBufsMut::copy_to_bytes: not enough data")
1124 }
1125 };
1126
1127 if needs_canonicalize {
1128 self.canonicalize();
1129 }
1130
1131 result
1132 }
1133}
1134
1135unsafe impl BufMut for IoBufsMut {
1137 #[inline]
1138 fn remaining_mut(&self) -> usize {
1139 match &self.inner {
1140 IoBufsMutInner::Single(buf) => buf.remaining_mut(),
1141 IoBufsMutInner::Pair([a, b]) => a.remaining_mut().saturating_add(b.remaining_mut()),
1142 IoBufsMutInner::Triple([a, b, c]) => a
1143 .remaining_mut()
1144 .saturating_add(b.remaining_mut())
1145 .saturating_add(c.remaining_mut()),
1146 IoBufsMutInner::Chunked(bufs) => bufs
1147 .iter()
1148 .map(|b| b.remaining_mut())
1149 .fold(0, usize::saturating_add),
1150 }
1151 }
1152
1153 #[inline]
1154 unsafe fn advance_mut(&mut self, cnt: usize) {
1155 unsafe {
1158 let mut remaining = cnt;
1162 let advanced = match &mut self.inner {
1163 IoBufsMutInner::Single(buf) => {
1164 buf.advance_mut(cnt);
1165 return;
1166 }
1167 IoBufsMutInner::Pair(pair) => advance_mut_in_chunks(pair, &mut remaining),
1168 IoBufsMutInner::Triple(triple) => advance_mut_in_chunks(triple, &mut remaining),
1169 IoBufsMutInner::Chunked(bufs) => {
1170 let (first, second) = bufs.as_mut_slices();
1171 advance_mut_in_chunks(first, &mut remaining)
1172 || advance_mut_in_chunks(second, &mut remaining)
1173 }
1174 };
1175 if !advanced {
1176 panic_advance(cnt, cnt - remaining);
1177 }
1178 }
1179 }
1180
1181 #[inline]
1182 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
1183 match &mut self.inner {
1184 IoBufsMutInner::Single(buf) => buf.chunk_mut(),
1185 IoBufsMutInner::Pair(pair) => {
1186 if pair[0].remaining_mut() > 0 {
1187 pair[0].chunk_mut()
1188 } else if pair[1].remaining_mut() > 0 {
1189 pair[1].chunk_mut()
1190 } else {
1191 bytes::buf::UninitSlice::new(&mut [])
1192 }
1193 }
1194 IoBufsMutInner::Triple(triple) => {
1195 if triple[0].remaining_mut() > 0 {
1196 triple[0].chunk_mut()
1197 } else if triple[1].remaining_mut() > 0 {
1198 triple[1].chunk_mut()
1199 } else if triple[2].remaining_mut() > 0 {
1200 triple[2].chunk_mut()
1201 } else {
1202 bytes::buf::UninitSlice::new(&mut [])
1203 }
1204 }
1205 IoBufsMutInner::Chunked(bufs) => {
1206 for buf in bufs.iter_mut() {
1207 if buf.remaining_mut() > 0 {
1208 return buf.chunk_mut();
1209 }
1210 }
1211 bytes::buf::UninitSlice::new(&mut [])
1212 }
1213 }
1214 }
1215}
1216
1217impl From<IoBufMut> for IoBufsMut {
1219 fn from(buf: IoBufMut) -> Self {
1220 Self {
1221 inner: IoBufsMutInner::Single(buf),
1222 }
1223 }
1224}
1225
1226impl From<Vec<u8>> for IoBufsMut {
1231 fn from(vec: Vec<u8>) -> Self {
1232 Self {
1233 inner: IoBufsMutInner::Single(IoBufMut::from(vec)),
1234 }
1235 }
1236}
1237
1238impl From<BytesMut> for IoBufsMut {
1241 fn from(bytes: BytesMut) -> Self {
1242 Self {
1243 inner: IoBufsMutInner::Single(IoBufMut::from(bytes)),
1244 }
1245 }
1246}
1247
1248impl From<Vec<IoBufMut>> for IoBufsMut {
1250 fn from(bufs: Vec<IoBufMut>) -> Self {
1251 Self::from_writable_chunks_iter(bufs)
1252 }
1253}
1254
1255impl<const N: usize> From<[u8; N]> for IoBufsMut {
1257 fn from(array: [u8; N]) -> Self {
1258 Self {
1259 inner: IoBufsMutInner::Single(IoBufMut::from(array)),
1260 }
1261 }
1262}
1263
1264#[inline]
1268fn copy_to_bytes_small_chunks<B: Buf, const N: usize>(
1269 chunks: &mut [B; N],
1270 len: usize,
1271 not_enough_data_msg: &str,
1272) -> (Bytes, bool) {
1273 let total = chunks
1274 .iter()
1275 .map(|buf| buf.remaining())
1276 .fold(0, usize::saturating_add);
1277 assert!(total >= len, "{not_enough_data_msg}");
1278
1279 if chunks[0].remaining() >= len {
1280 let bytes = chunks[0].copy_to_bytes(len);
1281 return (bytes, chunks[0].remaining() == 0);
1282 }
1283
1284 let mut out = BytesMut::with_capacity(len);
1285 let mut remaining = len;
1286 for buf in chunks.iter_mut() {
1287 if remaining == 0 {
1288 break;
1289 }
1290 let to_copy = remaining.min(buf.remaining());
1291 out.extend_from_slice(&buf.chunk()[..to_copy]);
1292 buf.advance(to_copy);
1293 remaining -= to_copy;
1294 }
1295
1296 (out.freeze(), true)
1298}
1299
1300#[inline]
1304fn copy_to_bytes_chunked<B: Buf>(
1305 bufs: &mut VecDeque<B>,
1306 len: usize,
1307 not_enough_data_msg: &str,
1308) -> (Bytes, bool) {
1309 while bufs.front().is_some_and(|buf| buf.remaining() == 0) {
1310 bufs.pop_front();
1311 }
1312
1313 if bufs.front().is_none() {
1314 assert_eq!(len, 0, "{not_enough_data_msg}");
1315 return (Bytes::new(), true);
1318 }
1319
1320 if bufs.front().is_some_and(|front| front.remaining() >= len) {
1321 let front = bufs.front_mut().expect("front checked above");
1322 let bytes = front.copy_to_bytes(len);
1323 if front.remaining() == 0 {
1324 bufs.pop_front();
1325 }
1326 return (bytes, bufs.len() <= 3);
1327 }
1328
1329 let total = bufs
1330 .iter()
1331 .map(|buf| buf.remaining())
1332 .fold(0, usize::saturating_add);
1333 assert!(total >= len, "{not_enough_data_msg}");
1334
1335 let mut out = BytesMut::with_capacity(len);
1336 let mut remaining = len;
1337 while remaining > 0 {
1338 let front = bufs
1339 .front_mut()
1340 .expect("remaining > 0 implies non-empty bufs");
1341 let to_copy = remaining.min(front.remaining());
1342 out.extend_from_slice(&front.chunk()[..to_copy]);
1343 front.advance(to_copy);
1344 if front.remaining() == 0 {
1345 bufs.pop_front();
1346 }
1347 remaining -= to_copy;
1348 }
1349
1350 (out.freeze(), bufs.len() <= 3)
1351}
1352
1353#[inline]
1355fn advance_chunked_front<B: Buf>(bufs: &mut VecDeque<B>, mut cnt: usize) {
1356 while cnt > 0 {
1357 let front = bufs.front_mut().expect("cannot advance past end of buffer");
1358 let avail = front.remaining();
1359 if avail == 0 {
1360 bufs.pop_front();
1361 continue;
1362 }
1363 if cnt < avail {
1364 front.advance(cnt);
1365 break;
1366 }
1367 front.advance(avail);
1368 bufs.pop_front();
1369 cnt -= avail;
1370 }
1371}
1372
1373#[inline]
1378fn advance_small_chunks<B: Buf>(chunks: &mut [B], mut cnt: usize) -> bool {
1379 let mut idx = 0;
1380 let mut needs_canonicalize = false;
1381
1382 while cnt > 0 {
1383 let chunk = chunks
1384 .get_mut(idx)
1385 .expect("cannot advance past end of buffer");
1386 let avail = chunk.remaining();
1387 if avail == 0 {
1388 idx += 1;
1389 needs_canonicalize = true;
1390 continue;
1391 }
1392 if cnt < avail {
1393 chunk.advance(cnt);
1394 return needs_canonicalize;
1395 }
1396 chunk.advance(avail);
1397 cnt -= avail;
1398 idx += 1;
1399 needs_canonicalize = true;
1400 }
1401
1402 needs_canonicalize
1403}
1404
1405#[inline]
1414unsafe fn advance_mut_in_chunks<B: BufMut>(chunks: &mut [B], remaining: &mut usize) -> bool {
1415 if *remaining == 0 {
1416 return true;
1417 }
1418
1419 for buf in chunks.iter_mut() {
1420 let avail = buf.chunk_mut().len();
1421 if avail == 0 {
1422 continue;
1423 }
1424 if *remaining <= avail {
1425 unsafe { buf.advance_mut(*remaining) };
1427 *remaining = 0;
1428 return true;
1429 }
1430 unsafe { buf.advance_mut(avail) };
1432 *remaining -= avail;
1433 }
1434 false
1435}
1436
1437#[inline]
1442fn fill_vectored_from_chunks<'a, I>(dst: &mut [IoSlice<'a>], chunks: I) -> usize
1443where
1444 I: IntoIterator<Item = &'a [u8]>,
1445{
1446 let mut written = 0;
1447 for chunk in chunks
1448 .into_iter()
1449 .filter(|chunk| !chunk.is_empty())
1450 .take(dst.len())
1451 {
1452 dst[written] = IoSlice::new(chunk);
1453 written += 1;
1454 }
1455 written
1456}
1457
1458pub struct Builder {
1481 buf: IoBufMut,
1483 pushes: Vec<(usize, Bytes)>,
1486}
1487
1488impl Builder {
1489 pub fn new(pool: &BufferPool, capacity: NonZeroUsize) -> Self {
1499 Self {
1500 buf: pool.alloc(capacity.get()),
1501 pushes: Vec::new(),
1502 }
1503 }
1504
1505 pub fn finish(self) -> IoBufs {
1508 if self.pushes.is_empty() {
1509 return IoBufs::from(self.buf.freeze());
1510 }
1511
1512 let frozen = self.buf.freeze();
1513 let mut result = IoBufs::default();
1514 let mut pos = 0;
1515
1516 for (offset, pushed) in self.pushes {
1517 if offset > pos {
1518 result.append(frozen.slice(pos..offset));
1519 }
1520 result.append(IoBuf::from(pushed));
1523 pos = offset;
1524 }
1525
1526 if pos < frozen.len() {
1527 result.append(frozen.slice(pos..));
1528 }
1529
1530 result
1531 }
1532}
1533
1534unsafe impl BufMut for Builder {
1540 #[inline]
1541 fn remaining_mut(&self) -> usize {
1542 self.buf.remaining_mut()
1543 }
1544
1545 #[inline]
1546 unsafe fn advance_mut(&mut self, cnt: usize) {
1547 unsafe {
1549 self.buf.advance_mut(cnt);
1550 }
1551 }
1552
1553 #[inline]
1554 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
1555 self.buf.chunk_mut()
1556 }
1557}
1558
1559impl BufsMut for Builder {
1560 fn push(&mut self, bytes: impl Into<Bytes>) {
1561 let bytes = bytes.into();
1562 if !bytes.is_empty() {
1563 self.pushes.push((self.buf.len(), bytes));
1564 }
1565 }
1566}
1567
1568pub trait EncodeExt: EncodeSize + Write {
1573 fn encode_with_pool_mut(&self, pool: &BufferPool) -> IoBufMut {
1580 let len = self.encode_size();
1581 let mut buf = pool.alloc(len);
1582 self.write(&mut buf);
1583 assert_eq!(
1584 buf.len(),
1585 len,
1586 "write() did not write expected bytes into pooled buffer"
1587 );
1588 buf
1589 }
1590
1591 fn encode_with_pool(&self, pool: &BufferPool) -> IoBufs {
1603 let len = self.encode_size();
1604 let capacity = NonZeroUsize::new(self.encode_inline_size()).unwrap_or(NonZeroUsize::MIN);
1605 let mut builder = Builder::new(pool, capacity);
1606 self.write_bufs(&mut builder);
1607 let bufs = builder.finish();
1608 assert_eq!(
1609 bufs.remaining(),
1610 len,
1611 "write_bufs() did not write expected bytes"
1612 );
1613 bufs
1614 }
1615}
1616
1617impl<T: EncodeSize + Write> EncodeExt for T {}
1618
1619#[cfg(all(test, not(feature = "loom")))]
1620mod tests {
1621 use super::{super::pool::BufferPoolConfig, *};
1622 use bytes::{Bytes, BytesMut};
1623 use commonware_codec::{Encode, types::lazy::Lazy};
1624 use commonware_utils::range::NonEmptyRange;
1625 use std::collections::{BTreeMap, HashMap};
1626
1627 fn test_pool() -> BufferPool {
1628 cfg_if::cfg_if! {
1629 if #[cfg(miri)] {
1630 let pool_config = BufferPoolConfig::for_network()
1632 .with_pool_min_size(0)
1633 .with_max_per_class(commonware_utils::NZU32!(32));
1634 } else {
1635 let pool_config = BufferPoolConfig::for_network().with_pool_min_size(0);
1636 }
1637 }
1638 let mut registry = crate::telemetry::metrics::Registry::default();
1639 BufferPool::new(pool_config, &mut registry)
1640 }
1641
1642 fn assert_encode_with_pool_matches_encode<T: Encode + EncodeExt>(value: &T) {
1643 let pool = test_pool();
1644 let mut pooled = value.encode_with_pool(&pool);
1645 let baseline = value.encode();
1646 let mut pooled_bytes = vec![0u8; pooled.remaining()];
1647 pooled.copy_to_slice(&mut pooled_bytes);
1648 assert_eq!(pooled_bytes, baseline.as_ref());
1649 }
1650
1651 #[test]
1652 fn test_iobufs_for_each_chunk_single_and_empty() {
1653 let mut seen = Vec::new();
1656 IoBufs::from(b"hello").for_each_chunk(|chunk| seen.push(chunk.to_vec()));
1657 assert_eq!(seen, vec![b"hello".to_vec()]);
1658
1659 let mut count = 0;
1660 IoBufs::default().for_each_chunk(|_| count += 1);
1661 assert_eq!(count, 0);
1662 }
1663
1664 #[test]
1665 fn test_iobufs_shapes_and_read_paths() {
1666 let empty = IoBufs::from(Vec::<u8>::new());
1668 assert!(empty.is_empty());
1669 assert!(empty.is_single());
1670 assert!(empty.as_single().is_some());
1671
1672 let mut single = IoBufs::from(b"hello world");
1674 assert!(single.is_single());
1675 assert_eq!(single.chunk(), b"hello world");
1676 single.advance(6);
1677 assert_eq!(single.chunk(), b"world");
1678 assert_eq!(single.copy_to_bytes(5).as_ref(), b"world");
1679 assert_eq!(single.remaining(), 0);
1680
1681 let mut pair = IoBufs::from(IoBuf::from(b"a"));
1683 pair.append(IoBuf::from(b"b"));
1684 assert!(matches!(pair.inner, IoBufsInner::Pair(_)));
1685 assert!(pair.as_single().is_none());
1686
1687 let mut triple = IoBufs::from(IoBuf::from(b"a"));
1688 triple.append(IoBuf::from(b"b"));
1689 triple.append(IoBuf::from(b"c"));
1690 assert!(matches!(triple.inner, IoBufsInner::Triple(_)));
1691
1692 let mut chunked = IoBufs::from(IoBuf::from(b"a"));
1693 chunked.append(IoBuf::from(b"b"));
1694 chunked.append(IoBuf::from(b"c"));
1695 chunked.append(IoBuf::from(b"d"));
1696 assert!(matches!(chunked.inner, IoBufsInner::Chunked(_)));
1697
1698 let mut joined = IoBufs::from(b"middle");
1700 joined.prepend(IoBuf::from(b"start "));
1701 joined.append(IoBuf::from(b" end"));
1702 assert_eq!(joined.coalesce(), b"start middle end");
1703
1704 let mut prepend_noop = IoBufs::from(b"x");
1706 prepend_noop.prepend(IoBuf::default());
1707 assert_eq!(prepend_noop.coalesce(), b"x");
1708
1709 let mut prepend_into_empty = IoBufs::default();
1711 prepend_into_empty.prepend(IoBuf::from(b"z"));
1712 assert!(prepend_into_empty.is_single());
1713 assert_eq!(prepend_into_empty.coalesce(), b"z");
1714
1715 let mut prepend_pair = IoBufs::from(vec![IoBuf::from(b"b"), IoBuf::from(b"c")]);
1716 prepend_pair.prepend(IoBuf::from(b"a"));
1717 assert!(matches!(prepend_pair.inner, IoBufsInner::Triple(_)));
1718 assert_eq!(prepend_pair.coalesce(), b"abc");
1719
1720 let mut canonical_single = IoBufs::from(b"q");
1722 canonical_single.canonicalize();
1723 assert!(canonical_single.is_single());
1724 assert_eq!(canonical_single.coalesce(), b"q");
1725 }
1726
1727 #[test]
1728 fn test_iobufs_split_to_cases() {
1729 let mut bufs = IoBufs::from(b"hello");
1731
1732 let empty = bufs.split_to(0);
1733 assert!(empty.is_empty());
1734 assert_eq!(bufs.coalesce(), b"hello");
1735
1736 let mut bufs = IoBufs::from(b"hello");
1737 let all = bufs.split_to(5);
1738 assert_eq!(all.coalesce(), b"hello");
1739 assert!(bufs.is_single());
1740 assert!(bufs.is_empty());
1741
1742 let mut single_mid = IoBufs::from(b"hello");
1744 let single_prefix = single_mid.split_to(2);
1745 assert!(single_prefix.is_single());
1746 assert_eq!(single_prefix.coalesce(), b"he");
1747 assert_eq!(single_mid.coalesce(), b"llo");
1748
1749 let mut pair = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
1751 let pair_prefix = pair.split_to(1);
1752 assert!(pair_prefix.is_single());
1753 assert_eq!(pair_prefix.coalesce(), b"a");
1754 assert!(matches!(pair.inner, IoBufsInner::Pair(_)));
1755 assert_eq!(pair.coalesce(), b"bcd");
1756
1757 let mut pair = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
1758 let pair_prefix = pair.split_to(2);
1759 assert!(pair_prefix.is_single());
1760 assert_eq!(pair_prefix.coalesce(), b"ab");
1761 assert!(pair.is_single());
1762 assert_eq!(pair.coalesce(), b"cd");
1763
1764 let mut pair = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
1765 let pair_prefix = pair.split_to(3);
1766 assert!(matches!(pair_prefix.inner, IoBufsInner::Pair(_)));
1767 assert_eq!(pair_prefix.coalesce(), b"abc");
1768 assert!(pair.is_single());
1769 assert_eq!(pair.coalesce(), b"d");
1770
1771 let mut triple = IoBufs::from(vec![
1774 IoBuf::from(b"ab"),
1775 IoBuf::from(b"cd"),
1776 IoBuf::from(b"ef"),
1777 ]);
1778 let triple_prefix = triple.split_to(1);
1779 assert!(triple_prefix.is_single());
1780 assert_eq!(triple_prefix.coalesce(), b"a");
1781 assert!(matches!(triple.inner, IoBufsInner::Triple(_)));
1782 assert_eq!(triple.coalesce(), b"bcdef");
1783
1784 let mut triple = IoBufs::from(vec![
1785 IoBuf::from(b"ab"),
1786 IoBuf::from(b"cd"),
1787 IoBuf::from(b"ef"),
1788 ]);
1789 let triple_prefix = triple.split_to(2);
1790 assert!(triple_prefix.is_single());
1791 assert_eq!(triple_prefix.coalesce(), b"ab");
1792 assert!(matches!(triple.inner, IoBufsInner::Pair(_)));
1793 assert_eq!(triple.coalesce(), b"cdef");
1794
1795 let mut triple = IoBufs::from(vec![
1796 IoBuf::from(b"ab"),
1797 IoBuf::from(b"cd"),
1798 IoBuf::from(b"ef"),
1799 ]);
1800 let triple_prefix = triple.split_to(3);
1801 assert!(matches!(triple_prefix.inner, IoBufsInner::Pair(_)));
1802 assert_eq!(triple_prefix.coalesce(), b"abc");
1803 assert!(matches!(triple.inner, IoBufsInner::Pair(_)));
1804 assert_eq!(triple.coalesce(), b"def");
1805
1806 let mut triple = IoBufs::from(vec![
1807 IoBuf::from(b"ab"),
1808 IoBuf::from(b"cd"),
1809 IoBuf::from(b"ef"),
1810 ]);
1811 let triple_prefix = triple.split_to(4);
1812 assert!(matches!(triple_prefix.inner, IoBufsInner::Pair(_)));
1813 assert_eq!(triple_prefix.coalesce(), b"abcd");
1814 assert!(triple.is_single());
1815 assert_eq!(triple.coalesce(), b"ef");
1816
1817 let mut triple = IoBufs::from(vec![
1818 IoBuf::from(b"ab"),
1819 IoBuf::from(b"cd"),
1820 IoBuf::from(b"ef"),
1821 ]);
1822 let triple_prefix = triple.split_to(5);
1823 assert!(matches!(triple_prefix.inner, IoBufsInner::Triple(_)));
1824 assert_eq!(triple_prefix.coalesce(), b"abcde");
1825 assert!(triple.is_single());
1826 assert_eq!(triple.coalesce(), b"f");
1827
1828 let mut bufs = IoBufs::from(vec![
1830 IoBuf::from(b"ab"),
1831 IoBuf::from(b"cd"),
1832 IoBuf::from(b"ef"),
1833 IoBuf::from(b"gh"),
1834 ]);
1835 let prefix = bufs.split_to(4);
1836 assert!(matches!(prefix.inner, IoBufsInner::Pair(_)));
1837 assert_eq!(prefix.coalesce(), b"abcd");
1838 assert!(matches!(bufs.inner, IoBufsInner::Pair(_)));
1839 assert_eq!(bufs.coalesce(), b"efgh");
1840
1841 let mut bufs = IoBufs::from(vec![
1843 IoBuf::from(b"ab"),
1844 IoBuf::from(b"cd"),
1845 IoBuf::from(b"ef"),
1846 IoBuf::from(b"gh"),
1847 ]);
1848 let prefix = bufs.split_to(5);
1849 assert!(matches!(prefix.inner, IoBufsInner::Triple(_)));
1850 assert_eq!(prefix.coalesce(), b"abcde");
1851 assert!(matches!(bufs.inner, IoBufsInner::Pair(_)));
1852 assert_eq!(bufs.coalesce(), b"fgh");
1853
1854 let mut bufs = IoBufs::from(vec![
1856 IoBuf::from(b"a"),
1857 IoBuf::from(b"b"),
1858 IoBuf::from(b"c"),
1859 IoBuf::from(b"d"),
1860 IoBuf::from(b"e"),
1861 IoBuf::from(b"f"),
1862 IoBuf::from(b"g"),
1863 IoBuf::from(b"h"),
1864 ]);
1865 let prefix = bufs.split_to(4);
1866 assert!(matches!(prefix.inner, IoBufsInner::Chunked(_)));
1867 assert_eq!(prefix.coalesce(), b"abcd");
1868 assert!(matches!(bufs.inner, IoBufsInner::Chunked(_)));
1869 assert_eq!(bufs.coalesce(), b"efgh");
1870
1871 let mut bufs = IoBufs {
1873 inner: IoBufsInner::Chunked(VecDeque::from([
1874 IoBuf::default(),
1875 IoBuf::from(b"ab"),
1876 IoBuf::from(b"cd"),
1877 IoBuf::from(b"ef"),
1878 IoBuf::from(b"gh"),
1879 ])),
1880 };
1881 let prefix = bufs.split_to(3);
1882 assert_eq!(prefix.coalesce(), b"abc");
1883 assert_eq!(bufs.coalesce(), b"defgh");
1884 }
1885
1886 #[test]
1887 #[should_panic(expected = "split_to out of bounds")]
1888 fn test_iobufs_split_to_out_of_bounds() {
1889 let mut bufs = IoBufs::from(b"abc");
1890 let _ = bufs.split_to(4);
1891 }
1892
1893 #[test]
1894 fn test_iobufs_chunk_count() {
1895 assert_eq!(IoBufs::default().chunk_count(), 0);
1896 assert_eq!(IoBufs::from(IoBuf::from(b"a")).chunk_count(), 1);
1897 assert_eq!(
1898 IoBufs::from(vec![IoBuf::from(b"b"), IoBuf::from(b"c")]).chunk_count(),
1899 2
1900 );
1901 assert_eq!(
1902 IoBufs::from(vec![
1903 IoBuf::from(b"a"),
1904 IoBuf::from(b"b"),
1905 IoBuf::from(b"c")
1906 ])
1907 .chunk_count(),
1908 3
1909 );
1910 assert_eq!(
1911 IoBufs::from(vec![
1912 IoBuf::from(b"a"),
1913 IoBuf::from(b"b"),
1914 IoBuf::from(b"c"),
1915 IoBuf::from(b"d")
1916 ])
1917 .chunk_count(),
1918 4
1919 );
1920 }
1921
1922 #[test]
1923 fn test_iobufs_coalesce_after_advance() {
1924 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
1925 bufs.append(IoBuf::from(b" world"));
1926
1927 assert_eq!(bufs.len(), 11);
1928
1929 bufs.advance(3);
1930 assert_eq!(bufs.len(), 8);
1931
1932 assert_eq!(bufs.coalesce(), b"lo world");
1933 }
1934
1935 #[test]
1936 fn test_iobufs_coalesce_with_pool() {
1937 let pool = test_pool();
1938
1939 let buf = IoBuf::from(vec![1u8, 2, 3, 4, 5]);
1941 let original_ptr = buf.as_ptr();
1942 let bufs = IoBufs::from(buf);
1943 let coalesced = bufs.coalesce_with_pool(&pool);
1944 assert_eq!(coalesced, [1, 2, 3, 4, 5]);
1945 assert_eq!(coalesced.as_ptr(), original_ptr);
1946
1947 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
1949 bufs.append(IoBuf::from(b" world"));
1950 let coalesced = bufs.coalesce_with_pool(&pool);
1951 assert_eq!(coalesced, b"hello world");
1952
1953 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
1955 bufs.append(IoBuf::from(b" world"));
1956 bufs.advance(3);
1957 let coalesced = bufs.coalesce_with_pool(&pool);
1958 assert_eq!(coalesced, b"lo world");
1959
1960 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
1962 bufs.append(IoBuf::default());
1963 bufs.append(IoBuf::from(b" world"));
1964 let coalesced = bufs.coalesce_with_pool(&pool);
1965 assert_eq!(coalesced, b"hello world");
1966
1967 let bufs = IoBufs::default();
1969 let coalesced = bufs.coalesce_with_pool(&pool);
1970 assert!(coalesced.is_empty());
1971
1972 let bufs = IoBufs::from(vec![
1974 IoBuf::from(b"ab"),
1975 IoBuf::from(b"cd"),
1976 IoBuf::from(b"ef"),
1977 IoBuf::from(b"gh"),
1978 ]);
1979 let coalesced = bufs.coalesce_with_pool(&pool);
1980 assert_eq!(coalesced, b"abcdefgh");
1981 assert!(coalesced.is_pooled());
1982 }
1983
1984 #[test]
1985 fn test_iobufs_empty_chunks_and_copy_to_bytes_paths() {
1986 let mut bufs = IoBufs::default();
1988 bufs.append(IoBuf::from(b"hello"));
1989 bufs.append(IoBuf::default());
1990 bufs.append(IoBuf::from(b" "));
1991 bufs.append(IoBuf::default());
1992 bufs.append(IoBuf::from(b"world"));
1993 assert_eq!(bufs.len(), 11);
1994 assert_eq!(bufs.chunk(), b"hello");
1995 bufs.advance(5);
1996 assert_eq!(bufs.chunk(), b" ");
1997 bufs.advance(1);
1998 assert_eq!(bufs.chunk(), b"world");
1999
2000 let mut single = IoBufs::from(b"hello world");
2002 assert_eq!(single.copy_to_bytes(5).as_ref(), b"hello");
2003 assert_eq!(single.remaining(), 6);
2004
2005 let mut multi = IoBufs::from(b"hello");
2007 multi.prepend(IoBuf::from(b"say "));
2008 assert_eq!(multi.copy_to_bytes(7).as_ref(), b"say hel");
2009 assert_eq!(multi.copy_to_bytes(2).as_ref(), b"lo");
2010 }
2011
2012 #[test]
2013 fn test_iobufs_copy_to_bytes_pair_and_triple() {
2014 let mut pair = IoBufs::from(IoBuf::from(b"ab"));
2016 pair.append(IoBuf::from(b"cd"));
2017 let first = pair.copy_to_bytes(3);
2018 assert_eq!(&first[..], b"abc");
2019 assert!(pair.is_single());
2020 assert_eq!(pair.chunk(), b"d");
2021
2022 let mut triple = IoBufs::from(IoBuf::from(b"ab"));
2024 triple.append(IoBuf::from(b"cd"));
2025 triple.append(IoBuf::from(b"ef"));
2026 let first = triple.copy_to_bytes(5);
2027 assert_eq!(&first[..], b"abcde");
2028 assert!(triple.is_single());
2029 assert_eq!(triple.chunk(), b"f");
2030 }
2031
2032 #[test]
2033 fn test_iobufs_copy_to_bytes_chunked_four_plus() {
2034 let mut bufs = IoBufs::from(vec![
2035 IoBuf::from(b"ab"),
2036 IoBuf::from(b"cd"),
2037 IoBuf::from(b"ef"),
2038 IoBuf::from(b"gh"),
2039 ]);
2040
2041 let first = bufs.copy_to_bytes(1);
2043 assert_eq!(&first[..], b"a");
2044
2045 let second = bufs.copy_to_bytes(4);
2047 assert_eq!(&second[..], b"bcde");
2048
2049 let rest = bufs.copy_to_bytes(3);
2050 assert_eq!(&rest[..], b"fgh");
2051 assert_eq!(bufs.remaining(), 0);
2052 }
2053
2054 #[test]
2055 fn test_iobufs_copy_to_bytes_edge_cases() {
2056 let mut iobufs = IoBufs {
2060 inner: IoBufsInner::Chunked(VecDeque::from([
2061 IoBuf::default(),
2062 IoBuf::from(b"hel"),
2063 IoBuf::from(b"lo"),
2064 IoBuf::from(b" world"),
2065 ])),
2066 };
2067 assert_eq!(iobufs.copy_to_bytes(5).as_ref(), b"hello");
2068 assert_eq!(iobufs.remaining(), 6);
2069
2070 let mut boundary = IoBufs::from(IoBuf::from(b"hello"));
2072 boundary.append(IoBuf::from(b"world"));
2073 assert_eq!(boundary.copy_to_bytes(5).as_ref(), b"hello");
2074 assert_eq!(boundary.copy_to_bytes(5).as_ref(), b"world");
2075 assert_eq!(boundary.remaining(), 0);
2076 }
2077
2078 #[test]
2079 #[should_panic(expected = "cannot advance past end of buffer")]
2080 fn test_iobufs_advance_past_end() {
2081 let mut bufs = IoBufs::from(b"hel");
2082 bufs.append(IoBuf::from(b"lo"));
2083 bufs.advance(10);
2084 }
2085
2086 #[test]
2087 #[should_panic(expected = "not enough data")]
2088 fn test_iobufs_copy_to_bytes_past_end() {
2089 let mut bufs = IoBufs::from(b"hel");
2090 bufs.append(IoBuf::from(b"lo"));
2091 bufs.copy_to_bytes(10);
2092 }
2093
2094 #[test]
2095 fn test_iobufs_matches_bytes_chain() {
2096 let b1 = Bytes::from_static(b"hello");
2097 let b2 = Bytes::from_static(b" ");
2098 let b3 = Bytes::from_static(b"world");
2099
2100 let mut chain = b1.clone().chain(b2.clone()).chain(b3.clone());
2102 let mut iobufs = IoBufs::from(IoBuf::from(b1.clone()));
2103 iobufs.append(IoBuf::from(b2.clone()));
2104 iobufs.append(IoBuf::from(b3.clone()));
2105
2106 assert_eq!(chain.remaining(), iobufs.remaining());
2107 assert_eq!(chain.chunk(), iobufs.chunk());
2108
2109 chain.advance(3);
2110 iobufs.advance(3);
2111 assert_eq!(chain.remaining(), iobufs.remaining());
2112 assert_eq!(chain.chunk(), iobufs.chunk());
2113
2114 chain.advance(3);
2115 iobufs.advance(3);
2116 assert_eq!(chain.remaining(), iobufs.remaining());
2117 assert_eq!(chain.chunk(), iobufs.chunk());
2118
2119 let mut chain = b1.clone().chain(b2.clone()).chain(b3.clone());
2121 let mut iobufs = IoBufs::from(IoBuf::from(b1));
2122 iobufs.append(IoBuf::from(b2));
2123 iobufs.append(IoBuf::from(b3));
2124
2125 assert_eq!(chain.copy_to_bytes(3), iobufs.copy_to_bytes(3));
2126 assert_eq!(chain.copy_to_bytes(4), iobufs.copy_to_bytes(4));
2127 assert_eq!(
2128 chain.copy_to_bytes(chain.remaining()),
2129 iobufs.copy_to_bytes(iobufs.remaining())
2130 );
2131 assert_eq!(chain.remaining(), 0);
2132 assert_eq!(iobufs.remaining(), 0);
2133 }
2134
2135 #[test]
2136 fn test_iobufs_try_into_single() {
2137 let single = IoBufs::from(IoBuf::from(b"hello"));
2138 let single = single.try_into_single().expect("single expected");
2139 assert_eq!(single, b"hello");
2140
2141 let multi = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
2142 let multi = multi.try_into_single().expect_err("multi expected");
2143 assert_eq!(multi.coalesce(), b"abcd");
2144 }
2145
2146 #[test]
2147 fn test_iobufs_chunks_vectored_multiple_slices() {
2148 let single = IoBufs::from(IoBuf::from(b"xy"));
2150 let mut single_dst = [IoSlice::new(&[]); 2];
2151 let count = single.chunks_vectored(&mut single_dst);
2152 assert_eq!(count, 1);
2153 assert_eq!(&single_dst[0][..], b"xy");
2154
2155 let empty_single = IoBufs::default();
2157 let mut empty_single_dst = [IoSlice::new(&[]); 1];
2158 assert_eq!(empty_single.chunks_vectored(&mut empty_single_dst), 0);
2159
2160 let bufs = IoBufs::from(vec![
2161 IoBuf::from(b"ab"),
2162 IoBuf::from(b"cd"),
2163 IoBuf::from(b"ef"),
2164 IoBuf::from(b"gh"),
2165 ]);
2166
2167 let mut small = [IoSlice::new(&[]); 2];
2169 let count = bufs.chunks_vectored(&mut small);
2170 assert_eq!(count, 2);
2171 assert_eq!(&small[0][..], b"ab");
2172 assert_eq!(&small[1][..], b"cd");
2173
2174 let mut large = [IoSlice::new(&[]); 8];
2176 let count = bufs.chunks_vectored(&mut large);
2177 assert_eq!(count, 4);
2178 assert_eq!(&large[0][..], b"ab");
2179 assert_eq!(&large[1][..], b"cd");
2180 assert_eq!(&large[2][..], b"ef");
2181 assert_eq!(&large[3][..], b"gh");
2182
2183 let mut empty_dst: [IoSlice<'_>; 0] = [];
2185 assert_eq!(bufs.chunks_vectored(&mut empty_dst), 0);
2186
2187 let sparse = IoBufs {
2189 inner: IoBufsInner::Pair([IoBuf::default(), IoBuf::from(b"x")]),
2190 };
2191 let mut dst = [IoSlice::new(&[]); 2];
2192 let count = sparse.chunks_vectored(&mut dst);
2193 assert_eq!(count, 1);
2194 assert_eq!(&dst[0][..], b"x");
2195
2196 let sparse_triple = IoBufs {
2198 inner: IoBufsInner::Triple([IoBuf::default(), IoBuf::from(b"y"), IoBuf::from(b"z")]),
2199 };
2200 let mut dst = [IoSlice::new(&[]); 3];
2201 let count = sparse_triple.chunks_vectored(&mut dst);
2202 assert_eq!(count, 2);
2203 assert_eq!(&dst[0][..], b"y");
2204 assert_eq!(&dst[1][..], b"z");
2205
2206 let empty_chunked = IoBufs {
2208 inner: IoBufsInner::Chunked(VecDeque::from([IoBuf::default(), IoBuf::default()])),
2209 };
2210 let mut dst = [IoSlice::new(&[]); 2];
2211 assert_eq!(empty_chunked.chunks_vectored(&mut dst), 0);
2212 }
2213
2214 #[test]
2215 fn test_iobufsmut_freeze_chunked() {
2216 let buf1 = IoBufMut::from(b"hello".as_ref());
2218 let buf2 = IoBufMut::from(b" world".as_ref());
2219 let bufs = IoBufsMut::from(vec![buf1, buf2]);
2220 let mut frozen = bufs.freeze();
2221 assert!(!frozen.is_single());
2222 assert_eq!(frozen.chunk(), b"hello");
2223 frozen.advance(5);
2224 assert_eq!(frozen.chunk(), b" world");
2225 frozen.advance(6);
2226 assert_eq!(frozen.remaining(), 0);
2227
2228 let buf1 = IoBufMut::from(b"hello".as_ref());
2230 let empty = IoBufMut::default();
2231 let buf2 = IoBufMut::from(b" world".as_ref());
2232 let bufs = IoBufsMut::from(vec![buf1, empty, buf2]);
2233 let mut frozen = bufs.freeze();
2234 assert!(!frozen.is_single());
2235 assert_eq!(frozen.chunk(), b"hello");
2236 frozen.advance(5);
2237 assert_eq!(frozen.chunk(), b" world");
2238 frozen.advance(6);
2239 assert_eq!(frozen.remaining(), 0);
2240
2241 let empty1 = IoBufMut::default();
2243 let buf = IoBufMut::from(b"only one".as_ref());
2244 let empty2 = IoBufMut::default();
2245 let bufs = IoBufsMut::from(vec![empty1, buf, empty2]);
2246 let frozen = bufs.freeze();
2247 assert!(frozen.is_single());
2248 assert_eq!(frozen.coalesce(), b"only one");
2249
2250 let empty1 = IoBufMut::default();
2252 let empty2 = IoBufMut::default();
2253 let bufs = IoBufsMut::from(vec![empty1, empty2]);
2254 let frozen = bufs.freeze();
2255 assert!(frozen.is_single());
2256 assert!(frozen.is_empty());
2257 }
2258
2259 #[test]
2260 fn test_iobufsmut_from_vec() {
2261 let bufs = IoBufsMut::from(Vec::<IoBufMut>::new());
2263 assert!(bufs.is_single());
2264 assert!(bufs.is_empty());
2265
2266 let buf = IoBufMut::from(b"test");
2268 let bufs = IoBufsMut::from(vec![buf]);
2269 assert!(bufs.is_single());
2270 assert_eq!(bufs.chunk(), b"test");
2271
2272 let buf1 = IoBufMut::from(b"hello");
2274 let buf2 = IoBufMut::from(b" world");
2275 let bufs = IoBufsMut::from(vec![buf1, buf2]);
2276 assert!(!bufs.is_single());
2277 }
2278
2279 #[test]
2280 fn test_iobufsmut_fast_path_shapes() {
2281 let pair = IoBufsMut::from(vec![IoBufMut::from(b"a"), IoBufMut::from(b"b")]);
2282 assert!(matches!(pair.inner, IoBufsMutInner::Pair(_)));
2283
2284 let triple = IoBufsMut::from(vec![
2285 IoBufMut::from(b"a"),
2286 IoBufMut::from(b"b"),
2287 IoBufMut::from(b"c"),
2288 ]);
2289 assert!(matches!(triple.inner, IoBufsMutInner::Triple(_)));
2290
2291 let chunked = IoBufsMut::from(vec![
2292 IoBufMut::from(b"a"),
2293 IoBufMut::from(b"b"),
2294 IoBufMut::from(b"c"),
2295 IoBufMut::from(b"d"),
2296 ]);
2297 assert!(matches!(chunked.inner, IoBufsMutInner::Chunked(_)));
2298 }
2299
2300 #[test]
2301 fn test_iobufsmut_default() {
2302 let bufs = IoBufsMut::default();
2304 assert!(bufs.is_single());
2305 assert!(bufs.is_empty());
2306 assert_eq!(bufs.len(), 0);
2307 }
2308
2309 #[test]
2310 fn test_iobufsmut_from_array() {
2311 let bufs = IoBufsMut::from([1u8, 2, 3, 4, 5]);
2313 assert!(bufs.is_single());
2314 assert_eq!(bufs.len(), 5);
2315 assert_eq!(bufs.chunk(), &[1, 2, 3, 4, 5]);
2316 }
2317
2318 #[test]
2319 fn test_iobufsmut_buf_trait_chunked() {
2320 let buf1 = IoBufMut::from(b"hello");
2321 let buf2 = IoBufMut::from(b" ");
2322 let buf3 = IoBufMut::from(b"world");
2323 let mut bufs = IoBufsMut::from(vec![buf1, buf2, buf3]);
2324
2325 assert_eq!(bufs.remaining(), 11);
2326 assert_eq!(bufs.chunk(), b"hello");
2327
2328 bufs.advance(3);
2330 assert_eq!(bufs.remaining(), 8);
2331 assert_eq!(bufs.chunk(), b"lo");
2332
2333 bufs.advance(2);
2335 assert_eq!(bufs.remaining(), 6);
2336 assert_eq!(bufs.chunk(), b" ");
2337
2338 bufs.advance(1);
2340 assert_eq!(bufs.remaining(), 5);
2341 assert_eq!(bufs.chunk(), b"world");
2342
2343 bufs.advance(5);
2345 assert_eq!(bufs.remaining(), 0);
2346 }
2347
2348 #[test]
2349 #[should_panic(expected = "cannot advance past end of buffer")]
2350 fn test_iobufsmut_advance_past_end() {
2351 let buf1 = IoBufMut::from(b"hello");
2352 let buf2 = IoBufMut::from(b" world");
2353 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2354 bufs.advance(20);
2355 }
2356
2357 #[test]
2358 fn test_iobufsmut_bufmut_trait_single() {
2359 let mut bufs = IoBufsMut::from(IoBufMut::with_capacity(20));
2360 assert_eq!(bufs.remaining_mut(), 20);
2361
2362 bufs.put_slice(b"hello");
2363 assert_eq!(bufs.chunk(), b"hello");
2364 assert_eq!(bufs.len(), 5);
2365 assert_eq!(bufs.remaining_mut(), 15);
2366
2367 bufs.put_slice(b" world");
2368 assert_eq!(bufs.coalesce(), b"hello world");
2369 }
2370
2371 #[test]
2372 fn test_iobufsmut_zeroed_write() {
2373 let bufs = IoBufsMut::from(IoBufMut::zeroed(20));
2375 assert_eq!(bufs.len(), 20);
2376
2377 let mut coalesced = bufs.coalesce();
2379 coalesced.as_mut()[..5].copy_from_slice(b"hello");
2380 assert_eq!(&coalesced.as_ref()[..5], b"hello");
2381 }
2382
2383 #[test]
2384 fn test_iobufsmut_bufmut_put_slice() {
2385 let buf1 = IoBufMut::with_capacity(5);
2387 let buf2 = IoBufMut::with_capacity(6);
2388 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2389
2390 bufs.put_slice(b"hello");
2392 bufs.put_slice(b" world");
2393 assert_eq!(bufs.coalesce(), b"hello world");
2394 }
2395
2396 #[test]
2397 fn test_iobufs_advance_drains_buffers() {
2398 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
2399 bufs.append(IoBuf::from(b" "));
2400 bufs.append(IoBuf::from(b"world"));
2401
2402 bufs.advance(5);
2404 assert_eq!(bufs.remaining(), 6);
2405 assert_eq!(bufs.chunk(), b" ");
2406
2407 bufs.advance(4);
2409 assert_eq!(bufs.remaining(), 2);
2410 assert_eq!(bufs.chunk(), b"ld");
2411 }
2412
2413 #[test]
2414 fn test_iobufs_advance_exactly_to_boundary() {
2415 let mut bufs = IoBufs::from(IoBuf::from(b"abc"));
2416 bufs.append(IoBuf::from(b"def"));
2417
2418 bufs.advance(3);
2420 assert_eq!(bufs.remaining(), 3);
2421 assert_eq!(bufs.chunk(), b"def");
2422
2423 bufs.advance(3);
2425 assert_eq!(bufs.remaining(), 0);
2426 }
2427
2428 #[test]
2429 fn test_iobufs_advance_canonicalizes_pair_to_single() {
2430 let mut bufs = IoBufs::from(IoBuf::from(b"ab"));
2431 bufs.append(IoBuf::from(b"cd"));
2432 bufs.advance(2);
2433 assert!(bufs.is_single());
2434 assert_eq!(bufs.chunk(), b"cd");
2435 }
2436
2437 #[test]
2438 fn test_iobufsmut_with_empty_buffers() {
2439 let buf1 = IoBufMut::from(b"hello");
2440 let buf2 = IoBufMut::default();
2441 let buf3 = IoBufMut::from(b" world");
2442 let mut bufs = IoBufsMut::from(vec![buf1, buf2, buf3]);
2443
2444 assert_eq!(bufs.remaining(), 11);
2445 assert_eq!(bufs.chunk(), b"hello");
2446
2447 bufs.advance(5);
2449 assert_eq!(bufs.chunk(), b" world");
2451 assert_eq!(bufs.remaining(), 6);
2452 }
2453
2454 #[test]
2455 fn test_iobufsmut_advance_skips_leading_writable_empty_chunk() {
2456 let empty_writable = IoBufMut::with_capacity(4);
2459 let payload = IoBufMut::from(b"xy");
2460 let mut bufs = IoBufsMut::from(vec![empty_writable, payload]);
2461
2462 bufs.advance(1);
2463 assert_eq!(bufs.chunk(), b"y");
2464 assert_eq!(bufs.remaining(), 1);
2465 }
2466
2467 #[test]
2468 fn test_iobufsmut_read_ops_preserve_writable_capacity() {
2469 let mut a = IoBufMut::with_capacity(8);
2473 a.put_slice(&[1u8; 8]);
2474 let b = IoBufMut::with_capacity(8);
2475 let mut bufs = IoBufsMut::from(vec![a, b]);
2476 assert_eq!(bufs.remaining(), 8);
2477 assert_eq!(bufs.remaining_mut(), 8);
2478 bufs.advance(8);
2479 assert_eq!(bufs.remaining(), 0);
2480 assert_eq!(bufs.remaining_mut(), 8);
2481 bufs.put_slice(&[2u8; 8]);
2482 assert_eq!(bufs.copy_to_bytes(8).as_ref(), &[2u8; 8]);
2483
2484 let mut a = IoBufMut::with_capacity(8);
2486 a.put_slice(&[3u8; 8]);
2487 let b = IoBufMut::with_capacity(8);
2488 let mut bufs = IoBufsMut::from(vec![a, b]);
2489 assert_eq!(bufs.copy_to_bytes(8).as_ref(), &[3u8; 8]);
2490 assert_eq!(bufs.remaining_mut(), 8);
2491
2492 assert!(bufs.copy_to_bytes(0).is_empty());
2494 assert_eq!(bufs.remaining_mut(), 8);
2495 }
2496
2497 #[test]
2498 fn test_iobufsmut_from_vec_u8_preserves_capacity() {
2499 let mut vec = Vec::with_capacity(128);
2502 vec.extend_from_slice(b"abc");
2503 let cap = vec.capacity();
2504 let mut bufs = IoBufsMut::from(vec);
2505 assert_eq!(bufs.remaining(), 3);
2506 assert_eq!(bufs.capacity(), cap);
2507 bufs.put_slice(b"d");
2508 assert_eq!(bufs.copy_to_bytes(4).as_ref(), b"abcd");
2509
2510 let vec = Vec::<u8>::with_capacity(64);
2514 let len = vec.capacity();
2515 let mut bufs = IoBufsMut::from(vec);
2516 assert!(bufs.is_empty());
2517 assert_eq!(bufs.capacity(), len);
2518 unsafe { bufs.set_len(len) };
2520 bufs.copy_from_slice(&vec![9u8; len]);
2521 assert_eq!(bufs.copy_to_bytes(len).as_ref(), vec![9u8; len].as_slice());
2522
2523 let bufs = IoBufsMut::from(vec![1u8, 2, 3]);
2525 assert_eq!(bufs.remaining(), 3);
2526 assert_eq!(bufs.capacity(), 3);
2527 assert_eq!(bufs.chunk(), &[1, 2, 3]);
2528 }
2529
2530 #[test]
2531 fn test_iobufsmut_coalesce_after_advance() {
2532 let buf1 = IoBufMut::from(b"hello");
2534 let buf2 = IoBufMut::from(b" world");
2535 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2536
2537 bufs.advance(3);
2538 assert_eq!(bufs.coalesce(), b"lo world");
2539
2540 let buf1 = IoBufMut::from(b"hello");
2542 let buf2 = IoBufMut::from(b" world");
2543 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2544
2545 bufs.advance(5);
2546 assert_eq!(bufs.coalesce(), b" world");
2547 }
2548
2549 #[test]
2550 fn test_iobufsmut_copy_to_bytes() {
2551 let buf1 = IoBufMut::from(b"hello");
2552 let buf2 = IoBufMut::from(b" world");
2553 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2554
2555 let first = bufs.copy_to_bytes(7);
2557 assert_eq!(&first[..], b"hello w");
2558 assert_eq!(bufs.remaining(), 4);
2559
2560 let rest = bufs.copy_to_bytes(4);
2562 assert_eq!(&rest[..], b"orld");
2563 assert_eq!(bufs.remaining(), 0);
2564 }
2565
2566 #[test]
2567 fn test_iobufsmut_copy_to_bytes_chunked_four_plus() {
2568 let mut bufs = IoBufsMut::from(vec![
2569 IoBufMut::from(b"ab"),
2570 IoBufMut::from(b"cd"),
2571 IoBufMut::from(b"ef"),
2572 IoBufMut::from(b"gh"),
2573 ]);
2574
2575 bufs.advance(1);
2577 assert_eq!(bufs.chunk(), b"b");
2578 bufs.advance(1);
2579 assert_eq!(bufs.chunk(), b"cd");
2580
2581 let first = bufs.copy_to_bytes(1);
2583 assert_eq!(&first[..], b"c");
2584
2585 let second = bufs.copy_to_bytes(4);
2587 assert_eq!(&second[..], b"defg");
2588
2589 let rest = bufs.copy_to_bytes(1);
2590 assert_eq!(&rest[..], b"h");
2591 assert_eq!(bufs.remaining(), 0);
2592
2593 let mut bufs = IoBufsMut::from(vec![
2595 IoBufMut::from(b"a"),
2596 IoBufMut::from(b"b"),
2597 IoBufMut::from(b"c"),
2598 IoBufMut::from(b"d"),
2599 IoBufMut::from(b"e"),
2600 ]);
2601 assert!(matches!(bufs.inner, IoBufsMutInner::Chunked(_)));
2602 let first = bufs.copy_to_bytes(1);
2603 assert_eq!(&first[..], b"a");
2604 let next = bufs.copy_to_bytes(3);
2606 assert_eq!(&next[..], b"bcd");
2607 assert_eq!(bufs.chunk(), b"e");
2608 assert_eq!(bufs.remaining(), 1);
2609 }
2610
2611 #[test]
2612 fn test_iobufsmut_copy_to_bytes_canonicalizes_pair() {
2613 let mut bufs = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
2614 assert!(matches!(bufs.inner, IoBufsMutInner::Pair(_)));
2615
2616 let first = bufs.copy_to_bytes(2);
2617 assert_eq!(&first[..], b"ab");
2618
2619 assert!(bufs.is_single());
2620 assert_eq!(bufs.chunk(), b"cd");
2621 assert_eq!(bufs.remaining(), 2);
2622 }
2623
2624 #[test]
2625 fn test_iobufsmut_copy_from_slice_single() {
2626 let mut bufs = IoBufsMut::from(IoBufMut::zeroed(11));
2627 bufs.copy_from_slice(b"hello world");
2628 assert_eq!(bufs.coalesce(), b"hello world");
2629 }
2630
2631 #[test]
2632 fn test_iobufsmut_copy_from_slice_chunked() {
2633 let buf1 = IoBufMut::zeroed(5);
2634 let buf2 = IoBufMut::zeroed(6);
2635 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2636
2637 bufs.copy_from_slice(b"hello world");
2638
2639 assert_eq!(bufs.chunk(), b"hello");
2641 bufs.advance(5);
2642 assert_eq!(bufs.chunk(), b" world");
2643 bufs.advance(6);
2644 assert_eq!(bufs.remaining(), 0);
2645 }
2646
2647 #[test]
2648 #[should_panic(expected = "source slice length must match buffer length")]
2649 fn test_iobufsmut_copy_from_slice_wrong_length() {
2650 let mut bufs = IoBufsMut::from(IoBufMut::zeroed(5));
2651 bufs.copy_from_slice(b"hello world"); }
2653
2654 #[test]
2655 fn test_iobufsmut_matches_bytesmut_chain() {
2656 let mut bm1 = BytesMut::with_capacity(5);
2658 let mut bm2 = BytesMut::with_capacity(6);
2659 let mut bm3 = BytesMut::with_capacity(7);
2660
2661 let mut iobufs = IoBufsMut::from(vec![
2663 IoBufMut::with_capacity(5),
2664 IoBufMut::with_capacity(6),
2665 IoBufMut::with_capacity(7),
2666 ]);
2667
2668 assert_eq!(iobufs.chunk_mut().len(), 5);
2670
2671 (&mut bm1)
2673 .chain_mut(&mut bm2)
2674 .chain_mut(&mut bm3)
2675 .put_slice(b"hel");
2676 iobufs.put_slice(b"hel");
2677
2678 assert_eq!(iobufs.chunk_mut().len(), 2);
2679
2680 (&mut bm1)
2682 .chain_mut(&mut bm2)
2683 .chain_mut(&mut bm3)
2684 .put_slice(b"lo world!");
2685 iobufs.put_slice(b"lo world!");
2686
2687 assert_eq!(iobufs.chunk_mut().len(), 6);
2688
2689 let frozen = iobufs.freeze().coalesce();
2691 let mut chain_content = bm1.to_vec();
2692 chain_content.extend_from_slice(&bm2);
2693 chain_content.extend_from_slice(&bm3);
2694 assert_eq!(frozen, chain_content.as_slice());
2695 assert_eq!(frozen, b"hello world!");
2696 }
2697
2698 #[test]
2699 fn test_iobufsmut_buf_matches_bytes_chain() {
2700 let mut b1 = Bytes::from_static(b"hello");
2702 let mut b2 = Bytes::from_static(b" world");
2703 let b3 = Bytes::from_static(b"!");
2704
2705 let mut iobufs = IoBufsMut::from(vec![
2707 IoBufMut::from(b"hello"),
2708 IoBufMut::from(b" world"),
2709 IoBufMut::from(b"!"),
2710 ]);
2711
2712 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
2714 assert_eq!(chain_remaining, iobufs.remaining());
2715
2716 let chain_chunk = b1
2718 .clone()
2719 .chain(b2.clone())
2720 .chain(b3.clone())
2721 .chunk()
2722 .to_vec();
2723 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
2724
2725 b1.advance(3);
2727 iobufs.advance(3);
2728
2729 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
2730 assert_eq!(chain_remaining, iobufs.remaining());
2731
2732 let chain_chunk = b1
2733 .clone()
2734 .chain(b2.clone())
2735 .chain(b3.clone())
2736 .chunk()
2737 .to_vec();
2738 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
2739
2740 b1.advance(2);
2742 iobufs.advance(2);
2743
2744 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
2745 assert_eq!(chain_remaining, iobufs.remaining());
2746
2747 let chain_chunk = b1
2749 .clone()
2750 .chain(b2.clone())
2751 .chain(b3.clone())
2752 .chunk()
2753 .to_vec();
2754 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
2755
2756 b2.advance(6);
2758 iobufs.advance(6);
2759
2760 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
2761 assert_eq!(chain_remaining, iobufs.remaining());
2762
2763 let chain_chunk = b1.chain(b2).chain(b3).chunk().to_vec();
2765 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
2766
2767 let b1 = Bytes::from_static(b"hello");
2769 let b2 = Bytes::from_static(b" world");
2770 let b3 = Bytes::from_static(b"!");
2771 let mut iobufs = IoBufsMut::from(vec![
2772 IoBufMut::from(b"hello"),
2773 IoBufMut::from(b" world"),
2774 IoBufMut::from(b"!"),
2775 ]);
2776
2777 let chain_bytes = b1.chain(b2).chain(b3).copy_to_bytes(8);
2778 let iobufs_bytes = iobufs.copy_to_bytes(8);
2779 assert_eq!(chain_bytes, iobufs_bytes);
2780 assert_eq!(chain_bytes.as_ref(), b"hello wo");
2781 }
2782
2783 #[test]
2784 fn test_iobufsmut_chunks_vectored_multiple_slices() {
2785 let single = IoBufsMut::from(IoBufMut::from(b"xy"));
2787 let mut single_dst = [IoSlice::new(&[]); 2];
2788 let count = single.chunks_vectored(&mut single_dst);
2789 assert_eq!(count, 1);
2790 assert_eq!(&single_dst[0][..], b"xy");
2791
2792 let empty_single = IoBufsMut::default();
2794 let mut empty_single_dst = [IoSlice::new(&[]); 1];
2795 assert_eq!(empty_single.chunks_vectored(&mut empty_single_dst), 0);
2796
2797 let bufs = IoBufsMut::from(vec![
2798 IoBufMut::from(b"ab"),
2799 IoBufMut::from(b"cd"),
2800 IoBufMut::from(b"ef"),
2801 IoBufMut::from(b"gh"),
2802 ]);
2803
2804 let mut small = [IoSlice::new(&[]); 2];
2806 let count = bufs.chunks_vectored(&mut small);
2807 assert_eq!(count, 2);
2808 assert_eq!(&small[0][..], b"ab");
2809 assert_eq!(&small[1][..], b"cd");
2810
2811 let mut large = [IoSlice::new(&[]); 8];
2813 let count = bufs.chunks_vectored(&mut large);
2814 assert_eq!(count, 4);
2815 assert_eq!(&large[0][..], b"ab");
2816 assert_eq!(&large[1][..], b"cd");
2817 assert_eq!(&large[2][..], b"ef");
2818 assert_eq!(&large[3][..], b"gh");
2819
2820 let mut empty_dst: [IoSlice<'_>; 0] = [];
2822 assert_eq!(bufs.chunks_vectored(&mut empty_dst), 0);
2823
2824 let sparse = IoBufsMut {
2826 inner: IoBufsMutInner::Pair([IoBufMut::default(), IoBufMut::from(b"y")]),
2827 };
2828 let mut dst = [IoSlice::new(&[]); 2];
2829 let count = sparse.chunks_vectored(&mut dst);
2830 assert_eq!(count, 1);
2831 assert_eq!(&dst[0][..], b"y");
2832
2833 let sparse_triple = IoBufsMut {
2835 inner: IoBufsMutInner::Triple([
2836 IoBufMut::default(),
2837 IoBufMut::from(b"z"),
2838 IoBufMut::from(b"w"),
2839 ]),
2840 };
2841 let mut dst = [IoSlice::new(&[]); 3];
2842 let count = sparse_triple.chunks_vectored(&mut dst);
2843 assert_eq!(count, 2);
2844 assert_eq!(&dst[0][..], b"z");
2845 assert_eq!(&dst[1][..], b"w");
2846
2847 let empty_chunked = IoBufsMut {
2849 inner: IoBufsMutInner::Chunked(VecDeque::from([
2850 IoBufMut::default(),
2851 IoBufMut::default(),
2852 ])),
2853 };
2854 let mut dst = [IoSlice::new(&[]); 2];
2855 assert_eq!(empty_chunked.chunks_vectored(&mut dst), 0);
2856 }
2857
2858 #[test]
2859 fn test_iobufsmut_try_into_single() {
2860 let single = IoBufsMut::from(IoBufMut::from(b"hello"));
2861 let single = single.try_into_single().expect("single expected");
2862 assert_eq!(single, b"hello");
2863
2864 let multi = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
2865 let multi = multi.try_into_single().expect_err("multi expected");
2866 assert_eq!(multi.coalesce(), b"abcd");
2867 }
2868
2869 #[test]
2870 fn test_iobufsmut_freeze_after_advance() {
2871 let buf1 = IoBufMut::from(b"hello");
2873 let buf2 = IoBufMut::from(b" world");
2874 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2875
2876 bufs.advance(3);
2877 assert_eq!(bufs.len(), 8);
2878
2879 let frozen = bufs.freeze();
2880 assert_eq!(frozen.len(), 8);
2881 assert_eq!(frozen.coalesce(), b"lo world");
2882
2883 let buf1 = IoBufMut::from(b"hello");
2885 let buf2 = IoBufMut::from(b" world");
2886 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
2887
2888 bufs.advance(5);
2889 assert_eq!(bufs.len(), 6);
2890
2891 let frozen = bufs.freeze();
2894 assert!(frozen.is_single());
2895 assert_eq!(frozen.coalesce(), b" world");
2896 }
2897
2898 #[test]
2899 fn test_iobufsmut_coalesce_with_pool() {
2900 let pool = test_pool();
2901
2902 let mut buf = IoBufMut::from(b"hello");
2904 let original_ptr = buf.as_mut_ptr();
2905 let bufs = IoBufsMut::from(buf);
2906 let coalesced = bufs.coalesce_with_pool(&pool);
2907 assert_eq!(coalesced, b"hello");
2908 assert_eq!(coalesced.as_ref().as_ptr(), original_ptr);
2909
2910 let bufs = IoBufsMut::from(vec![IoBufMut::from(b"hello"), IoBufMut::from(b" world")]);
2912 let coalesced = bufs.coalesce_with_pool(&pool);
2913 assert_eq!(coalesced, b"hello world");
2914 assert!(coalesced.is_pooled());
2915
2916 let bufs = IoBufsMut::from(vec![
2918 IoBufMut::from(b"a"),
2919 IoBufMut::from(b"b"),
2920 IoBufMut::from(b"c"),
2921 IoBufMut::from(b"d"),
2922 ]);
2923 let coalesced = bufs.coalesce_with_pool(&pool);
2924 assert_eq!(coalesced, b"abcd");
2925 assert!(coalesced.is_pooled());
2926
2927 let mut buf = IoBufMut::with_capacity(100);
2929 buf.put_slice(b"hello");
2930 let original_ptr = buf.as_mut_ptr();
2931 let bufs = IoBufsMut::from(buf);
2932 let coalesced = bufs.coalesce_with_pool_extra(&pool, 10);
2933 assert_eq!(coalesced, b"hello");
2934 assert_eq!(coalesced.as_ref().as_ptr(), original_ptr);
2935
2936 let mut buf = IoBufMut::with_capacity(5);
2938 buf.put_slice(b"hello");
2939 let bufs = IoBufsMut::from(buf);
2940 let coalesced = bufs.coalesce_with_pool_extra(&pool, 100);
2941 assert_eq!(coalesced, b"hello");
2942 assert!(coalesced.capacity() >= 105);
2943 }
2944
2945 #[test]
2946 fn test_iobufs_additional_shape_and_conversion_paths() {
2947 let pool = test_pool();
2948
2949 let from_mut = IoBufs::from(IoBufMut::from(b"m"));
2951 assert_eq!(from_mut.chunk(), b"m");
2952 let from_bytes = IoBufs::from(Bytes::from_static(b"b"));
2953 assert_eq!(from_bytes.chunk(), b"b");
2954 let from_bytesmut = IoBufs::from(BytesMut::from(&b"bm"[..]));
2955 assert_eq!(from_bytesmut.chunk(), b"bm");
2956 let from_vec = IoBufs::from(vec![1u8, 2u8]);
2957 assert_eq!(from_vec.chunk(), &[1u8, 2]);
2958 let static_slice: &'static [u8] = b"slice";
2959 let from_static = IoBufs::from(static_slice);
2960 assert_eq!(from_static.chunk(), b"slice");
2961
2962 let mut single_empty = IoBufs::default();
2964 single_empty.canonicalize();
2965 assert!(single_empty.is_single());
2966
2967 let mut triple = IoBufs::from(vec![
2969 IoBuf::from(b"a".to_vec()),
2970 IoBuf::from(b"b".to_vec()),
2971 IoBuf::from(b"c".to_vec()),
2972 ]);
2973 assert!(triple.as_single().is_none());
2974 triple.prepend(IoBuf::from(vec![b'0']));
2975 triple.prepend(IoBuf::from(vec![b'1']));
2976 triple.append(IoBuf::from(vec![b'2']));
2977 assert_eq!(triple.copy_to_bytes(triple.remaining()).as_ref(), b"10abc2");
2978
2979 let mut triple_append = IoBufs::from(vec![
2981 IoBuf::from(b"x".to_vec()),
2982 IoBuf::from(b"y".to_vec()),
2983 IoBuf::from(b"z".to_vec()),
2984 ]);
2985 triple_append.append(IoBuf::from(vec![b'w']));
2986 assert_eq!(triple_append.coalesce(), b"xyzw");
2987
2988 let triple_pool = IoBufs::from(vec![
2990 IoBuf::from(b"a".to_vec()),
2991 IoBuf::from(b"b".to_vec()),
2992 IoBuf::from(b"c".to_vec()),
2993 ]);
2994 assert_eq!(triple_pool.coalesce_with_pool(&pool), b"abc");
2995
2996 let mut chunked_pool = IoBufs::from(vec![
2998 IoBuf::from(b"a".to_vec()),
2999 IoBuf::from(b"b".to_vec()),
3000 IoBuf::from(b"c".to_vec()),
3001 IoBuf::from(b"d".to_vec()),
3002 ]);
3003 assert_eq!(chunked_pool.remaining(), 4);
3004 chunked_pool.advance(1);
3005 assert_eq!(chunked_pool.coalesce_with_pool(&pool), b"bcd");
3006
3007 let pair_second = IoBufs {
3009 inner: IoBufsInner::Pair([IoBuf::default(), IoBuf::from(vec![1u8])]),
3010 };
3011 assert_eq!(pair_second.chunk(), &[1u8]);
3012 let pair_empty = IoBufs {
3013 inner: IoBufsInner::Pair([IoBuf::default(), IoBuf::default()]),
3014 };
3015 assert_eq!(pair_empty.chunk(), b"");
3016
3017 let triple_third = IoBufs {
3018 inner: IoBufsInner::Triple([
3019 IoBuf::default(),
3020 IoBuf::default(),
3021 IoBuf::from(vec![3u8]),
3022 ]),
3023 };
3024 assert_eq!(triple_third.chunk(), &[3u8]);
3025 let triple_second = IoBufs {
3026 inner: IoBufsInner::Triple([
3027 IoBuf::default(),
3028 IoBuf::from(vec![2u8]),
3029 IoBuf::default(),
3030 ]),
3031 };
3032 assert_eq!(triple_second.chunk(), &[2u8]);
3033 let triple_empty = IoBufs {
3034 inner: IoBufsInner::Triple([IoBuf::default(), IoBuf::default(), IoBuf::default()]),
3035 };
3036 assert_eq!(triple_empty.chunk(), b"");
3037
3038 let chunked_second = IoBufs {
3039 inner: IoBufsInner::Chunked(VecDeque::from([IoBuf::default(), IoBuf::from(vec![9u8])])),
3040 };
3041 assert_eq!(chunked_second.chunk(), &[9u8]);
3042 let chunked_empty = IoBufs {
3043 inner: IoBufsInner::Chunked(VecDeque::from([IoBuf::default()])),
3044 };
3045 assert_eq!(chunked_empty.chunk(), b"");
3046 }
3047
3048 #[test]
3049 fn test_iobufsmut_additional_shape_and_conversion_paths() {
3050 let mut single = IoBufsMut::from(IoBufMut::from(b"x"));
3052 assert!(single.as_single().is_some());
3053 assert!(single.as_single_mut().is_some());
3054 single.canonicalize();
3055 assert!(single.is_single());
3056
3057 let mut pair = IoBufsMut::from(vec![IoBufMut::from(b"a"), IoBufMut::from(b"b")]);
3058 assert!(pair.as_single().is_none());
3059 assert!(pair.as_single_mut().is_none());
3060
3061 let from_vec = IoBufsMut::from(vec![1u8, 2u8]);
3063 assert_eq!(from_vec.chunk(), &[1u8, 2]);
3064 let from_bytesmut = IoBufsMut::from(BytesMut::from(&b"cd"[..]));
3065 assert_eq!(from_bytesmut.chunk(), b"cd");
3066
3067 let mut chunked = IoBufsMut::from(vec![
3069 IoBufMut::with_capacity(1),
3070 IoBufMut::with_capacity(1),
3071 IoBufMut::with_capacity(1),
3072 IoBufMut::with_capacity(1),
3073 ]);
3074 unsafe { chunked.set_len(4) };
3076 chunked.copy_from_slice(b"wxyz");
3077 assert_eq!(chunked.capacity(), 4);
3078 assert_eq!(chunked.remaining(), 4);
3079 let frozen = chunked.freeze();
3080 assert_eq!(frozen.coalesce(), b"wxyz");
3081 }
3082
3083 #[test]
3084 fn test_iobufsmut_coalesce_multi_shape_paths() {
3085 let pool = test_pool();
3086
3087 let pair = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
3089 assert_eq!(pair.coalesce(), b"abcd");
3090 let pair = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
3091 let pair_extra = pair.coalesce_with_pool_extra(&pool, 3);
3092 assert_eq!(pair_extra, b"abcd");
3093 assert!(pair_extra.capacity() >= 7);
3094
3095 let triple = IoBufsMut::from(vec![
3097 IoBufMut::from(b"a"),
3098 IoBufMut::from(b"b"),
3099 IoBufMut::from(b"c"),
3100 ]);
3101 assert_eq!(triple.coalesce(), b"abc");
3102 let triple = IoBufsMut::from(vec![
3103 IoBufMut::from(b"a"),
3104 IoBufMut::from(b"b"),
3105 IoBufMut::from(b"c"),
3106 ]);
3107 let triple_extra = triple.coalesce_with_pool_extra(&pool, 2);
3108 assert_eq!(triple_extra, b"abc");
3109 assert!(triple_extra.capacity() >= 5);
3110
3111 let chunked = IoBufsMut::from(vec![
3113 IoBufMut::from(b"1"),
3114 IoBufMut::from(b"2"),
3115 IoBufMut::from(b"3"),
3116 IoBufMut::from(b"4"),
3117 ]);
3118 assert_eq!(chunked.coalesce(), b"1234");
3119 let chunked = IoBufsMut::from(vec![
3120 IoBufMut::from(b"1"),
3121 IoBufMut::from(b"2"),
3122 IoBufMut::from(b"3"),
3123 IoBufMut::from(b"4"),
3124 ]);
3125 let chunked_extra = chunked.coalesce_with_pool_extra(&pool, 5);
3126 assert_eq!(chunked_extra, b"1234");
3127 assert!(chunked_extra.capacity() >= 9);
3128 }
3129
3130 #[test]
3131 fn test_iobufsmut_noncanonical_chunk_and_chunk_mut_paths() {
3132 fn no_spare_capacity_buf(pool: &BufferPool) -> IoBufMut {
3133 let mut buf = pool.alloc(1);
3134 let cap = buf.capacity();
3135 unsafe { buf.set_len(cap) };
3137 buf
3138 }
3139 let pool = test_pool();
3140
3141 let pair_second = IoBufsMut {
3143 inner: IoBufsMutInner::Pair([IoBufMut::default(), IoBufMut::from(b"b")]),
3144 };
3145 assert_eq!(pair_second.chunk(), b"b");
3146 let pair_empty = IoBufsMut {
3147 inner: IoBufsMutInner::Pair([IoBufMut::default(), IoBufMut::default()]),
3148 };
3149 assert_eq!(pair_empty.chunk(), b"");
3150
3151 let triple_third = IoBufsMut {
3152 inner: IoBufsMutInner::Triple([
3153 IoBufMut::default(),
3154 IoBufMut::default(),
3155 IoBufMut::from(b"c"),
3156 ]),
3157 };
3158 assert_eq!(triple_third.chunk(), b"c");
3159 let triple_second = IoBufsMut {
3160 inner: IoBufsMutInner::Triple([
3161 IoBufMut::default(),
3162 IoBufMut::from(b"b"),
3163 IoBufMut::default(),
3164 ]),
3165 };
3166 assert_eq!(triple_second.chunk(), b"b");
3167 let triple_empty = IoBufsMut {
3168 inner: IoBufsMutInner::Triple([
3169 IoBufMut::default(),
3170 IoBufMut::default(),
3171 IoBufMut::default(),
3172 ]),
3173 };
3174 assert_eq!(triple_empty.chunk(), b"");
3175
3176 let chunked_second = IoBufsMut {
3177 inner: IoBufsMutInner::Chunked(VecDeque::from([
3178 IoBufMut::default(),
3179 IoBufMut::from(b"d"),
3180 ])),
3181 };
3182 assert_eq!(chunked_second.chunk(), b"d");
3183 let chunked_empty = IoBufsMut {
3184 inner: IoBufsMutInner::Chunked(VecDeque::from([IoBufMut::default()])),
3185 };
3186 assert_eq!(chunked_empty.chunk(), b"");
3187
3188 let mut pair_chunk_mut = IoBufsMut {
3190 inner: IoBufsMutInner::Pair([no_spare_capacity_buf(&pool), IoBufMut::with_capacity(2)]),
3191 };
3192 assert!(pair_chunk_mut.chunk_mut().len() >= 2);
3193
3194 let mut pair_chunk_mut_empty = IoBufsMut {
3195 inner: IoBufsMutInner::Pair([
3196 no_spare_capacity_buf(&pool),
3197 no_spare_capacity_buf(&pool),
3198 ]),
3199 };
3200 assert_eq!(pair_chunk_mut_empty.chunk_mut().len(), 0);
3201
3202 let mut triple_chunk_mut = IoBufsMut {
3203 inner: IoBufsMutInner::Triple([
3204 no_spare_capacity_buf(&pool),
3205 no_spare_capacity_buf(&pool),
3206 IoBufMut::with_capacity(3),
3207 ]),
3208 };
3209 assert!(triple_chunk_mut.chunk_mut().len() >= 3);
3210 let mut triple_chunk_mut_second = IoBufsMut {
3211 inner: IoBufsMutInner::Triple([
3212 no_spare_capacity_buf(&pool),
3213 IoBufMut::with_capacity(2),
3214 no_spare_capacity_buf(&pool),
3215 ]),
3216 };
3217 assert!(triple_chunk_mut_second.chunk_mut().len() >= 2);
3218
3219 let mut triple_chunk_mut_empty = IoBufsMut {
3220 inner: IoBufsMutInner::Triple([
3221 no_spare_capacity_buf(&pool),
3222 no_spare_capacity_buf(&pool),
3223 no_spare_capacity_buf(&pool),
3224 ]),
3225 };
3226 assert_eq!(triple_chunk_mut_empty.chunk_mut().len(), 0);
3227
3228 let mut chunked_chunk_mut = IoBufsMut {
3229 inner: IoBufsMutInner::Chunked(VecDeque::from([
3230 IoBufMut::default(),
3231 IoBufMut::with_capacity(4),
3232 ])),
3233 };
3234 assert!(chunked_chunk_mut.chunk_mut().len() >= 4);
3235
3236 let mut chunked_chunk_mut_empty = IoBufsMut {
3237 inner: IoBufsMutInner::Chunked(VecDeque::from([no_spare_capacity_buf(&pool)])),
3238 };
3239 assert_eq!(chunked_chunk_mut_empty.chunk_mut().len(), 0);
3240 }
3241
3242 #[test]
3243 fn test_iobuf_internal_chunk_helpers() {
3244 let mut empty_with_leading = VecDeque::from([IoBuf::default()]);
3248 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut empty_with_leading, 0, "x");
3249 assert!(bytes.is_empty());
3250 assert!(needs_canonicalize);
3251 assert!(empty_with_leading.is_empty());
3252
3253 let mut fast = VecDeque::from([
3255 IoBuf::from(b"ab".to_vec()),
3256 IoBuf::from(b"cd".to_vec()),
3257 IoBuf::from(b"ef".to_vec()),
3258 IoBuf::from(b"gh".to_vec()),
3259 ]);
3260 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut fast, 2, "x");
3261 assert_eq!(bytes.as_ref(), b"ab");
3262 assert!(needs_canonicalize);
3263 assert_eq!(fast.front().expect("front exists").as_ref(), b"cd");
3264
3265 let mut slow = VecDeque::from([
3267 IoBuf::from(b"a".to_vec()),
3268 IoBuf::from(b"bc".to_vec()),
3269 IoBuf::from(b"d".to_vec()),
3270 IoBuf::from(b"e".to_vec()),
3271 ]);
3272 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut slow, 3, "x");
3273 assert_eq!(bytes.as_ref(), b"abc");
3274 assert!(needs_canonicalize);
3275
3276 let mut empty_with_leading_mut = VecDeque::from([IoBufMut::default()]);
3277 let (bytes, needs_canonicalize) =
3278 copy_to_bytes_chunked(&mut empty_with_leading_mut, 0, "x");
3279 assert!(bytes.is_empty());
3280 assert!(needs_canonicalize);
3281 assert!(empty_with_leading_mut.is_empty());
3282
3283 let mut fast_mut = VecDeque::from([
3285 IoBufMut::from(b"ab"),
3286 IoBufMut::from(b"cd"),
3287 IoBufMut::from(b"ef"),
3288 IoBufMut::from(b"gh"),
3289 ]);
3290 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut fast_mut, 2, "x");
3291 assert_eq!(bytes.as_ref(), b"ab");
3292 assert!(needs_canonicalize);
3293 assert_eq!(fast_mut.front().expect("front exists").as_ref(), b"cd");
3294
3295 let mut slow_mut = VecDeque::from([
3296 IoBufMut::from(b"a"),
3297 IoBufMut::from(b"bc"),
3298 IoBufMut::from(b"de"),
3299 IoBufMut::from(b"f"),
3300 ]);
3301 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut slow_mut, 4, "x");
3302 assert_eq!(bytes.as_ref(), b"abcd");
3303 assert!(needs_canonicalize);
3304 assert_eq!(slow_mut.front().expect("front exists").as_ref(), b"e");
3305
3306 let mut advance_chunked = VecDeque::from([
3308 IoBuf::default(),
3309 IoBuf::from(b"abc".to_vec()),
3310 IoBuf::from(b"d".to_vec()),
3311 ]);
3312 advance_chunked_front(&mut advance_chunked, 2);
3313 assert_eq!(
3314 advance_chunked.front().expect("front exists").as_ref(),
3315 b"c"
3316 );
3317 advance_chunked_front(&mut advance_chunked, 2);
3318 assert!(advance_chunked.is_empty());
3319
3320 let mut advance_chunked_mut = VecDeque::from([
3322 IoBufMut::default(),
3323 IoBufMut::from(b"abc"),
3324 IoBufMut::from(b"d"),
3325 ]);
3326 advance_chunked_front(&mut advance_chunked_mut, 2);
3327 assert_eq!(
3328 advance_chunked_mut.front().expect("front exists").as_ref(),
3329 b"c"
3330 );
3331 advance_chunked_front(&mut advance_chunked_mut, 2);
3332 assert!(advance_chunked_mut.is_empty());
3333
3334 let mut small = [IoBuf::default(), IoBuf::from(b"abc".to_vec())];
3336 let needs_canonicalize = advance_small_chunks(&mut small, 2);
3337 assert!(needs_canonicalize);
3338 assert_eq!(small[1].as_ref(), b"c");
3339
3340 let mut small_exact = [
3341 IoBuf::from(b"a".to_vec()),
3342 IoBuf::from(b"b".to_vec()),
3343 IoBuf::from(b"c".to_vec()),
3344 ];
3345 let needs_canonicalize = advance_small_chunks(&mut small_exact, 3);
3346 assert!(needs_canonicalize);
3347 assert_eq!(small_exact[0].remaining(), 0);
3348 assert_eq!(small_exact[1].remaining(), 0);
3349 assert_eq!(small_exact[2].remaining(), 0);
3350
3351 let mut small_mut = [
3353 IoBufMut::from(b"a"),
3354 IoBufMut::from(b"bc"),
3355 IoBufMut::from(b"d"),
3356 ];
3357 let (bytes, needs_canonicalize) = copy_to_bytes_small_chunks(&mut small_mut, 3, "x");
3358 assert_eq!(bytes.as_ref(), b"abc");
3359 assert!(needs_canonicalize);
3360 assert_eq!(small_mut[2].as_ref(), b"d");
3361
3362 let mut writable = [IoBufMut::with_capacity(2), IoBufMut::with_capacity(1)];
3364 let mut remaining = 3usize;
3365 let all_advanced = unsafe { advance_mut_in_chunks(&mut writable, &mut remaining) };
3367 assert!(all_advanced);
3368 assert_eq!(remaining, 0);
3369
3370 let pool = test_pool();
3372 let mut full = pool.alloc(1);
3373 unsafe { full.set_len(full.capacity()) };
3375 let mut writable_after_full = [full, IoBufMut::with_capacity(2)];
3376 let mut remaining = 2usize;
3377 let all_advanced =
3379 unsafe { advance_mut_in_chunks(&mut writable_after_full, &mut remaining) };
3380 assert!(all_advanced);
3381 assert_eq!(remaining, 0);
3382
3383 let mut writable_short = [IoBufMut::with_capacity(1), IoBufMut::with_capacity(1)];
3384 let mut remaining = 3usize;
3385 let all_advanced = unsafe { advance_mut_in_chunks(&mut writable_short, &mut remaining) };
3387 assert!(!all_advanced);
3388 assert_eq!(remaining, 1);
3389 }
3390
3391 #[test]
3392 fn test_iobufsmut_advance_mut_success_paths() {
3393 let mut pair = IoBufsMut {
3395 inner: IoBufsMutInner::Pair([IoBufMut::with_capacity(2), IoBufMut::with_capacity(2)]),
3396 };
3397 unsafe { pair.advance_mut(3) };
3399 assert_eq!(pair.remaining(), 3);
3400
3401 let mut triple = IoBufsMut {
3403 inner: IoBufsMutInner::Triple([
3404 IoBufMut::with_capacity(1),
3405 IoBufMut::with_capacity(1),
3406 IoBufMut::with_capacity(1),
3407 ]),
3408 };
3409 unsafe { triple.advance_mut(2) };
3411 assert_eq!(triple.remaining(), 2);
3412
3413 let mut wrapped = VecDeque::with_capacity(5);
3415 wrapped.push_back(IoBufMut::with_capacity(1));
3416 wrapped.push_back(IoBufMut::with_capacity(1));
3417 wrapped.push_back(IoBufMut::with_capacity(1));
3418 wrapped.push_back(IoBufMut::with_capacity(1));
3419 wrapped.push_back(IoBufMut::with_capacity(1));
3420 let _ = wrapped.pop_front();
3421 wrapped.push_back(IoBufMut::with_capacity(1));
3422 let (first, second) = wrapped.as_slices();
3423 assert!(!first.is_empty());
3424 assert!(!second.is_empty());
3425
3426 let to_advance = first.len() + 1;
3428 let mut chunked = IoBufsMut {
3429 inner: IoBufsMutInner::Chunked(wrapped),
3430 };
3431 let before = chunked.remaining_mut();
3432 unsafe { chunked.advance_mut(to_advance) };
3434 assert_eq!(chunked.remaining(), to_advance);
3435 assert_eq!(chunked.remaining_mut(), before - to_advance);
3436 }
3437
3438 #[test]
3439 fn test_iobufsmut_advance_mut_zero_noop_when_full() {
3440 fn full_chunk(pool: &BufferPool) -> IoBufMut {
3441 let mut buf = pool.alloc(1);
3444 let cap = buf.capacity();
3445 unsafe { buf.set_len(cap) };
3447 buf
3448 }
3449
3450 let pool = test_pool();
3451
3452 let mut pair = IoBufsMut::from(vec![full_chunk(&pool), full_chunk(&pool)]);
3454 assert!(matches!(pair.inner, IoBufsMutInner::Pair(_)));
3455 assert_eq!(pair.remaining_mut(), 0);
3456 let before = pair.remaining();
3457 unsafe { pair.advance_mut(0) };
3459 assert_eq!(pair.remaining(), before);
3460
3461 let mut triple = IoBufsMut::from(vec![
3463 full_chunk(&pool),
3464 full_chunk(&pool),
3465 full_chunk(&pool),
3466 ]);
3467 assert!(matches!(triple.inner, IoBufsMutInner::Triple(_)));
3468 assert_eq!(triple.remaining_mut(), 0);
3469 let before = triple.remaining();
3470 unsafe { triple.advance_mut(0) };
3472 assert_eq!(triple.remaining(), before);
3473
3474 let mut chunked = IoBufsMut::from(vec![
3476 full_chunk(&pool),
3477 full_chunk(&pool),
3478 full_chunk(&pool),
3479 full_chunk(&pool),
3480 ]);
3481 assert!(matches!(chunked.inner, IoBufsMutInner::Chunked(_)));
3482 assert_eq!(chunked.remaining_mut(), 0);
3483 let before = chunked.remaining();
3484 unsafe { chunked.advance_mut(0) };
3486 assert_eq!(chunked.remaining(), before);
3487 }
3488
3489 #[test]
3490 #[should_panic(expected = "cannot advance past end of buffer")]
3491 fn test_iobufsmut_advance_mut_past_end_pair() {
3492 let mut pair = IoBufsMut {
3493 inner: IoBufsMutInner::Pair([IoBufMut::with_capacity(1), IoBufMut::with_capacity(1)]),
3494 };
3495 unsafe { pair.advance_mut(3) };
3497 }
3498
3499 #[test]
3500 #[should_panic(expected = "cannot advance past end of buffer")]
3501 fn test_iobufsmut_advance_mut_past_end_triple() {
3502 let mut triple = IoBufsMut {
3503 inner: IoBufsMutInner::Triple([
3504 IoBufMut::with_capacity(1),
3505 IoBufMut::with_capacity(1),
3506 IoBufMut::with_capacity(1),
3507 ]),
3508 };
3509 unsafe { triple.advance_mut(4) };
3511 }
3512
3513 #[test]
3514 #[should_panic(expected = "cannot advance past end of buffer")]
3515 fn test_iobufsmut_advance_mut_past_end_chunked() {
3516 let mut chunked = IoBufsMut {
3517 inner: IoBufsMutInner::Chunked(VecDeque::from([
3518 IoBufMut::with_capacity(1),
3519 IoBufMut::with_capacity(1),
3520 IoBufMut::with_capacity(1),
3521 IoBufMut::with_capacity(1),
3522 ])),
3523 };
3524 unsafe { chunked.advance_mut(5) };
3526 }
3527
3528 #[test]
3529 fn test_iobufsmut_set_len() {
3530 unsafe {
3532 let mut bufs = IoBufsMut::from(IoBufMut::with_capacity(16));
3534 bufs.set_len(10);
3535 assert_eq!(bufs.len(), 10);
3536
3537 let mut bufs = IoBufsMut::from(vec![
3539 IoBufMut::with_capacity(5),
3540 IoBufMut::with_capacity(10),
3541 ]);
3542 bufs.set_len(12);
3543 assert_eq!(bufs.len(), 12);
3544 assert_eq!(bufs.chunk().len(), 5);
3545 bufs.advance(5);
3546 assert_eq!(bufs.chunk().len(), 7);
3547 bufs.advance(7);
3548 assert_eq!(bufs.remaining(), 0);
3549
3550 let mut bufs = IoBufsMut::from(vec![
3552 IoBufMut::with_capacity(3),
3553 IoBufMut::with_capacity(20),
3554 IoBufMut::with_capacity(2),
3555 ]);
3556 bufs.set_len(18);
3557 assert_eq!(bufs.chunk().len(), 3);
3558 bufs.advance(3);
3559 assert_eq!(bufs.chunk().len(), 15);
3560 bufs.advance(15);
3561 assert_eq!(bufs.remaining(), 0);
3562
3563 let mut bufs =
3565 IoBufsMut::from(vec![IoBufMut::with_capacity(4), IoBufMut::with_capacity(4)]);
3566 bufs.set_len(8);
3567 assert_eq!(bufs.chunk().len(), 4);
3568 bufs.advance(4);
3569 assert_eq!(bufs.chunk().len(), 4);
3570 bufs.advance(4);
3571 assert_eq!(bufs.remaining(), 0);
3572
3573 let mut bufs =
3575 IoBufsMut::from(vec![IoBufMut::with_capacity(4), IoBufMut::with_capacity(4)]);
3576 bufs.set_len(0);
3577 assert_eq!(bufs.len(), 0);
3578 assert_eq!(bufs.chunk(), b"");
3579 }
3580 }
3581
3582 #[test]
3583 #[should_panic(expected = "set_len(9) exceeds capacity(8)")]
3584 fn test_iobufsmut_set_len_overflow() {
3585 let mut bufs =
3586 IoBufsMut::from(vec![IoBufMut::with_capacity(4), IoBufMut::with_capacity(4)]);
3587 unsafe { bufs.set_len(9) };
3589 }
3590
3591 #[test]
3592 fn test_encode_with_pool_matches_encode() {
3593 let value = vec![1u8, 2, 3, 4, 5, 6];
3594 assert_encode_with_pool_matches_encode(&value);
3595 }
3596
3597 #[test]
3598 fn test_encode_with_pool_mut_len_matches_encode_size() {
3599 let pool = test_pool();
3600 let value = vec![9u8, 8, 7, 6];
3601
3602 let buf = value.encode_with_pool_mut(&pool);
3603 assert_eq!(buf.len(), value.encode_size());
3604 }
3605
3606 struct UnderWriter;
3609
3610 impl Write for UnderWriter {
3611 fn write(&self, buf: &mut impl BufMut) {
3612 buf.put_slice(b"ab");
3613 }
3614 }
3615
3616 impl EncodeSize for UnderWriter {
3617 fn encode_size(&self) -> usize {
3618 4
3619 }
3620 }
3621
3622 #[test]
3623 #[should_panic(expected = "write() did not write expected bytes into pooled buffer")]
3624 fn test_encode_with_pool_mut_rejects_short_write() {
3625 let pool = test_pool();
3626 let _ = UnderWriter.encode_with_pool_mut(&pool);
3627 }
3628
3629 #[test]
3630 #[should_panic(expected = "write_bufs() did not write expected bytes")]
3631 fn test_encode_with_pool_rejects_short_write() {
3632 let pool = test_pool();
3633 let _ = UnderWriter.encode_with_pool(&pool);
3634 }
3635
3636 #[test]
3637 fn test_iobuf_encode_with_pool_matches_encode() {
3638 let value = IoBuf::from(vec![0xAB; 512]);
3639 assert_encode_with_pool_matches_encode(&value);
3640 }
3641
3642 #[test]
3643 fn test_nested_container_encode_with_pool_matches_encode() {
3644 let value = (
3645 Some(Bytes::from(vec![0xAA; 256])),
3646 vec![Bytes::from(vec![0xBB; 128]), Bytes::from(vec![0xCC; 64])],
3647 );
3648 assert_encode_with_pool_matches_encode(&value);
3649 }
3650
3651 #[test]
3652 fn test_map_encode_with_pool_matches_encode() {
3653 let mut btree = BTreeMap::new();
3654 btree.insert(2u8, Bytes::from(vec![0xDD; 96]));
3655 btree.insert(1u8, Bytes::from(vec![0xEE; 48]));
3656 assert_encode_with_pool_matches_encode(&btree);
3657
3658 let mut hash = HashMap::new();
3659 hash.insert(2u8, Bytes::from(vec![0x11; 96]));
3660 hash.insert(1u8, Bytes::from(vec![0x22; 48]));
3661 assert_encode_with_pool_matches_encode(&hash);
3662 }
3663
3664 #[test]
3665 fn test_lazy_encode_with_pool_matches_encode() {
3666 let value = Lazy::new(Bytes::from(vec![0x44; 200]));
3667 assert_encode_with_pool_matches_encode(&value);
3668 }
3669
3670 #[test]
3671 fn test_non_empty_range_encode_with_pool_matches_encode() {
3672 let range =
3673 NonEmptyRange::new(Bytes::from(vec![0x10; 32])..Bytes::from(vec![0x20; 48])).unwrap();
3674 assert_encode_with_pool_matches_encode(&range);
3675 }
3676
3677 mod builder_tests {
3678 use super::*;
3679 use commonware_codec::{BufsMut, Encode, Write};
3680
3681 fn builder(capacity: usize) -> Builder {
3682 Builder::new(&test_pool(), NonZeroUsize::new(capacity).unwrap())
3683 }
3684
3685 #[test]
3687 fn test_inline_only() {
3688 let mut b = builder(64);
3689 b.put_u32(42);
3690 b.put_u8(7);
3691 let mut r = b.finish();
3692 assert_eq!(r.remaining(), 5);
3693 assert_eq!(r.get_u32(), 42);
3694 assert_eq!(r.get_u8(), 7);
3695 }
3696
3697 #[test]
3699 fn test_push_only() {
3700 let mut b = builder(64);
3701 let data = Bytes::from(vec![0xAA; 1024]);
3702 b.push(data.clone());
3703 let mut r = b.finish();
3704 assert_eq!(r.remaining(), 1024);
3705 assert_eq!(r.copy_to_bytes(1024), data);
3706 }
3707
3708 #[test]
3710 fn test_push_is_zero_copy() {
3711 let mut b = builder(64);
3712 b.put_u16(99);
3713 let payload = Bytes::from(vec![0xDD; 1024]);
3714 b.push(payload.clone());
3715 let mut r = b.finish();
3716 r.advance(2);
3717 assert_eq!(r.chunk().as_ptr(), payload.as_ptr());
3718 }
3719
3720 #[test]
3722 fn test_inline_push_inline() {
3723 let mut b = builder(64);
3724 b.put_u16(99);
3725 let payload = Bytes::from(vec![0xBB; 512]);
3726 b.push(payload.clone());
3727 b.put_u8(1);
3728 let mut r = b.finish();
3729 assert_eq!(r.remaining(), 2 + 512 + 1);
3730 assert_eq!(r.get_u16(), 99);
3731 assert_eq!(r.copy_to_bytes(512), payload);
3732 assert_eq!(r.get_u8(), 1);
3733 }
3734
3735 #[test]
3737 fn test_write_bufs_matches_write() {
3738 let data = Bytes::from(vec![0xCC; 256]);
3739 let mut b = builder(64);
3740 data.write_bufs(&mut b);
3741 let mut bufs = b.finish();
3742
3743 let mut out = vec![0u8; bufs.remaining()];
3744 bufs.copy_to_slice(&mut out);
3745 assert_eq!(out, data.encode().as_ref());
3746 }
3747
3748 #[test]
3750 fn test_empty() {
3751 let bufs = builder(64).finish();
3752 assert_eq!(bufs.remaining(), 0);
3753 }
3754
3755 #[test]
3759 #[should_panic(expected = "advance out of bounds")]
3760 fn test_inline_overflow_panics() {
3761 let mut b = builder(1);
3762 let cap = b.remaining_mut();
3763 b.put_slice(&vec![0xFF; cap]);
3764 b.put_u8(1); }
3766
3767 #[test]
3769 fn test_empty_push_ignored() {
3770 let mut b = builder(64);
3771 b.push(Bytes::new());
3772 b.put_u8(1);
3773 let bufs = b.finish();
3774 assert_eq!(bufs.remaining(), 1);
3775 }
3776
3777 #[test]
3779 fn test_multiple_pushes() {
3780 let mut b = builder(64);
3781 let a = Bytes::from(vec![0xAA; 100]);
3782 let c = Bytes::from(vec![0xCC; 200]);
3783 b.push(a.clone());
3784 b.push(c.clone());
3785 let mut r = b.finish();
3786 assert_eq!(r.remaining(), 300);
3787 assert_eq!(r.copy_to_bytes(100), a);
3788 assert_eq!(r.copy_to_bytes(200), c);
3789 }
3790
3791 #[test]
3793 #[should_panic(expected = "advance out of bounds")]
3794 fn test_put_exceeding_capacity_panics() {
3795 let mut b = builder(1);
3796 let cap = b.remaining_mut();
3797 let src = Bytes::from(vec![0xAB; cap + 1]);
3798 b.put(src);
3799 }
3800
3801 #[test]
3803 #[should_panic(expected = "advance out of bounds")]
3804 fn test_put_slice_exceeding_capacity_panics() {
3805 let mut b = builder(1);
3806 let cap = b.remaining_mut();
3807 b.put_slice(&vec![0xFE; cap + 1]);
3808 }
3809
3810 #[test]
3813 fn test_multi_field_struct_equivalence() {
3814 let header: u16 = 0xCAFE;
3815 let payload = Bytes::from(vec![0xDD; 1024]);
3816 let trailer: u32 = 0xDEADBEEF;
3817
3818 let size = header.encode_size() + payload.encode_size() + trailer.encode_size();
3820 let mut flat = BytesMut::with_capacity(size);
3821 header.write(&mut flat);
3822 payload.write(&mut flat);
3823 trailer.write(&mut flat);
3824
3825 let mut b = builder(64);
3827 header.write(&mut b);
3828 payload.write_bufs(&mut b);
3829 trailer.write(&mut b);
3830 let mut bufs = b.finish();
3831
3832 let mut out = vec![0u8; bufs.remaining()];
3833 bufs.copy_to_slice(&mut out);
3834 assert_eq!(out, flat.as_ref());
3835 }
3836
3837 #[test]
3839 fn test_encode_with_pool_matches_encode() {
3840 let pool = test_pool();
3841 let data = Bytes::from(vec![0xEE; 500]);
3842 let mut pooled = data.encode_with_pool(&pool);
3843 let baseline = data.encode();
3844 let mut out = vec![0u8; pooled.remaining()];
3845 pooled.copy_to_slice(&mut out);
3846 assert_eq!(out, baseline.as_ref());
3847 }
3848
3849 #[test]
3851 fn test_chunk_mut_and_advance_mut() {
3852 let mut b = builder(64);
3853 let initial = b.remaining_mut();
3854 assert!(initial >= 64);
3855 let chunk = b.chunk_mut();
3856 chunk[0..1].copy_from_slice(&[0xAB]);
3857 unsafe { b.advance_mut(1) };
3859 assert_eq!(b.remaining_mut(), initial - 1);
3860 let mut r = b.finish();
3861 assert_eq!(r.remaining(), 1);
3862 assert_eq!(r.get_u8(), 0xAB);
3863 }
3864
3865 #[test]
3868 #[should_panic(expected = "advance out of bounds")]
3869 fn test_write_past_full_panics() {
3870 let mut b = builder(1);
3871 let cap = b.remaining_mut();
3872 b.put_slice(&vec![0xFF; cap]); assert_eq!(b.remaining_mut(), 0);
3874 b.put_u8(0x42); }
3876
3877 #[test]
3880 fn test_push_at_start_with_trailer() {
3881 let mut b = builder(64);
3882 let payload = Bytes::from(vec![0xCC; 32]);
3883 b.push(payload.clone());
3884 b.put_u8(0x01);
3885 let mut r = b.finish();
3886 assert_eq!(r.remaining(), 33);
3887 assert_eq!(r.copy_to_bytes(32), payload);
3888 assert_eq!(r.get_u8(), 0x01);
3889 }
3890 }
3891}