1mod buffer;
18mod freelist;
19mod pool;
20
21pub(crate) use buffer::AlignedBuffer;
22use buffer::{AlignedBuf, AlignedBufMut, PooledBuf, PooledBufMut};
23use bytes::{Buf, BufMut, Bytes, BytesMut};
24use commonware_codec::{util::at_least, BufsMut, EncodeSize, Error, RangeCfg, Read, Write};
25use crossbeam_utils::CachePadded;
26pub use pool::{BufferPool, BufferPoolConfig, BufferPoolThreadCache, PoolError};
27use std::{collections::VecDeque, io::IoSlice, mem::align_of, num::NonZeroUsize, ops::RangeBounds};
28
29#[allow(clippy::missing_const_for_fn)]
34pub fn page_size() -> usize {
35 #[cfg(unix)]
36 {
37 let size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
39 if size <= 0 {
40 4096 } else {
42 size as usize
43 }
44 }
45
46 #[cfg(not(unix))]
47 {
48 4096
49 }
50}
51
52pub const fn cache_line_size() -> usize {
54 align_of::<CachePadded<u8>>()
55}
56
57#[cfg(feature = "bench")]
58pub mod bench {
59 pub use super::{buffer::PooledBuffer, freelist::Freelist};
60}
61
62#[derive(Clone, Debug)]
79pub struct IoBuf {
80 inner: IoBufInner,
81}
82
83#[derive(Clone, Debug)]
90enum IoBufInner {
91 Bytes(Bytes),
92 Aligned(AlignedBuf),
93 Pooled(PooledBuf),
94}
95
96impl IoBuf {
97 pub fn copy_from_slice(data: &[u8]) -> Self {
102 Self {
103 inner: IoBufInner::Bytes(Bytes::copy_from_slice(data)),
104 }
105 }
106
107 #[inline]
109 const fn from_pooled(pooled: PooledBuf) -> Self {
110 Self {
111 inner: IoBufInner::Pooled(pooled),
112 }
113 }
114
115 #[inline]
117 const fn from_aligned(aligned: AlignedBuf) -> Self {
118 Self {
119 inner: IoBufInner::Aligned(aligned),
120 }
121 }
122
123 #[inline]
132 pub const fn is_pooled(&self) -> bool {
133 match &self.inner {
134 IoBufInner::Bytes(_) => false,
135 IoBufInner::Aligned(_) => false,
136 IoBufInner::Pooled(_) => true,
137 }
138 }
139
140 #[inline]
142 pub fn len(&self) -> usize {
143 self.remaining()
144 }
145
146 #[inline]
148 pub fn is_empty(&self) -> bool {
149 self.remaining() == 0
150 }
151
152 #[inline]
154 pub fn as_ptr(&self) -> *const u8 {
155 match &self.inner {
156 IoBufInner::Bytes(b) => b.as_ptr(),
157 IoBufInner::Aligned(a) => a.as_ptr(),
158 IoBufInner::Pooled(p) => p.as_ptr(),
159 }
160 }
161
162 #[inline]
167 pub fn slice(&self, range: impl RangeBounds<usize>) -> Self {
168 match &self.inner {
169 IoBufInner::Bytes(b) => Self {
170 inner: IoBufInner::Bytes(b.slice(range)),
171 },
172 IoBufInner::Aligned(a) => a
173 .slice(range)
174 .map_or_else(Self::default, Self::from_aligned),
175 IoBufInner::Pooled(p) => p.slice(range).map_or_else(Self::default, Self::from_pooled),
176 }
177 }
178
179 pub fn split_to(&mut self, at: usize) -> Self {
190 if at == 0 {
191 return Self::default();
192 }
193
194 if at == self.remaining() {
195 return std::mem::take(self);
196 }
197
198 match &mut self.inner {
199 IoBufInner::Bytes(b) => Self {
200 inner: IoBufInner::Bytes(b.split_to(at)),
201 },
202 IoBufInner::Aligned(a) => Self::from_aligned(a.split_to(at)),
203 IoBufInner::Pooled(p) => Self::from_pooled(p.split_to(at)),
204 }
205 }
206
207 pub fn try_into_mut(self) -> Result<IoBufMut, Self> {
219 match self.inner {
220 IoBufInner::Bytes(bytes) => bytes
221 .try_into_mut()
222 .map(|mut_bytes| IoBufMut {
223 inner: IoBufMutInner::Bytes(mut_bytes),
224 })
225 .map_err(|bytes| Self {
226 inner: IoBufInner::Bytes(bytes),
227 }),
228 IoBufInner::Aligned(aligned) => aligned
229 .try_into_mut()
230 .map(|mut_aligned| IoBufMut {
231 inner: IoBufMutInner::Aligned(mut_aligned),
232 })
233 .map_err(|aligned| Self {
234 inner: IoBufInner::Aligned(aligned),
235 }),
236 IoBufInner::Pooled(pooled) => pooled
237 .try_into_mut()
238 .map(|mut_pooled| IoBufMut {
239 inner: IoBufMutInner::Pooled(mut_pooled),
240 })
241 .map_err(|pooled| Self {
242 inner: IoBufInner::Pooled(pooled),
243 }),
244 }
245 }
246
247 pub fn into_mut_with_pool(self, pool: &BufferPool) -> IoBufMut {
253 match self.try_into_mut() {
254 Ok(buf) => buf,
255 Err(buf) => {
256 let mut result = pool.alloc(buf.len());
257 result.put_slice(buf.as_ref());
258 result
259 }
260 }
261 }
262}
263
264impl AsRef<[u8]> for IoBuf {
265 #[inline]
266 fn as_ref(&self) -> &[u8] {
267 match &self.inner {
268 IoBufInner::Bytes(b) => b.as_ref(),
269 IoBufInner::Aligned(a) => a.as_ref(),
270 IoBufInner::Pooled(p) => p.as_ref(),
271 }
272 }
273}
274
275impl Default for IoBuf {
276 fn default() -> Self {
277 Self {
278 inner: IoBufInner::Bytes(Bytes::new()),
279 }
280 }
281}
282
283impl PartialEq for IoBuf {
284 fn eq(&self, other: &Self) -> bool {
285 self.as_ref() == other.as_ref()
286 }
287}
288
289impl Eq for IoBuf {}
290
291impl PartialEq<[u8]> for IoBuf {
292 #[inline]
293 fn eq(&self, other: &[u8]) -> bool {
294 self.as_ref() == other
295 }
296}
297
298impl PartialEq<&[u8]> for IoBuf {
299 #[inline]
300 fn eq(&self, other: &&[u8]) -> bool {
301 self.as_ref() == *other
302 }
303}
304
305impl<const N: usize> PartialEq<[u8; N]> for IoBuf {
306 #[inline]
307 fn eq(&self, other: &[u8; N]) -> bool {
308 self.as_ref() == other
309 }
310}
311
312impl<const N: usize> PartialEq<&[u8; N]> for IoBuf {
313 #[inline]
314 fn eq(&self, other: &&[u8; N]) -> bool {
315 self.as_ref() == *other
316 }
317}
318
319impl Buf for IoBuf {
320 #[inline]
321 fn remaining(&self) -> usize {
322 match &self.inner {
323 IoBufInner::Bytes(b) => b.remaining(),
324 IoBufInner::Aligned(a) => a.remaining(),
325 IoBufInner::Pooled(p) => p.remaining(),
326 }
327 }
328
329 #[inline]
330 fn chunk(&self) -> &[u8] {
331 match &self.inner {
332 IoBufInner::Bytes(b) => b.chunk(),
333 IoBufInner::Aligned(a) => a.chunk(),
334 IoBufInner::Pooled(p) => p.chunk(),
335 }
336 }
337
338 #[inline]
339 fn advance(&mut self, cnt: usize) {
340 match &mut self.inner {
341 IoBufInner::Bytes(b) => b.advance(cnt),
342 IoBufInner::Aligned(a) => a.advance(cnt),
343 IoBufInner::Pooled(p) => p.advance(cnt),
344 }
345 }
346
347 #[inline]
348 fn copy_to_bytes(&mut self, len: usize) -> Bytes {
349 match &mut self.inner {
350 IoBufInner::Bytes(b) => b.copy_to_bytes(len),
351 IoBufInner::Aligned(a) => a.copy_to_bytes(len),
352 IoBufInner::Pooled(p) => {
353 if len != 0 && len == p.remaining() {
357 let inner = std::mem::replace(&mut self.inner, IoBufInner::Bytes(Bytes::new()));
358 match inner {
359 IoBufInner::Pooled(p) => p.into_bytes(),
360 _ => unreachable!(),
361 }
362 } else {
363 p.copy_to_bytes(len)
364 }
365 }
366 }
367 }
368}
369
370impl From<Bytes> for IoBuf {
371 fn from(bytes: Bytes) -> Self {
372 Self {
373 inner: IoBufInner::Bytes(bytes),
374 }
375 }
376}
377
378impl From<Vec<u8>> for IoBuf {
379 fn from(vec: Vec<u8>) -> Self {
380 Self {
381 inner: IoBufInner::Bytes(Bytes::from(vec)),
382 }
383 }
384}
385
386impl<const N: usize> From<&'static [u8; N]> for IoBuf {
387 fn from(array: &'static [u8; N]) -> Self {
388 Self {
389 inner: IoBufInner::Bytes(Bytes::from_static(array)),
390 }
391 }
392}
393
394impl From<&'static [u8]> for IoBuf {
395 fn from(slice: &'static [u8]) -> Self {
396 Self {
397 inner: IoBufInner::Bytes(Bytes::from_static(slice)),
398 }
399 }
400}
401
402impl From<IoBuf> for Vec<u8> {
408 fn from(buf: IoBuf) -> Self {
409 match buf.inner {
410 IoBufInner::Bytes(bytes) => Self::from(bytes),
411 IoBufInner::Aligned(aligned) => aligned.as_ref().to_vec(),
412 IoBufInner::Pooled(pooled) => pooled.as_ref().to_vec(),
413 }
414 }
415}
416
417impl From<IoBuf> for Bytes {
421 fn from(buf: IoBuf) -> Self {
422 match buf.inner {
423 IoBufInner::Bytes(bytes) => bytes,
424 IoBufInner::Aligned(aligned) => Self::from_owner(aligned),
425 IoBufInner::Pooled(pooled) => Self::from_owner(pooled),
426 }
427 }
428}
429
430impl Write for IoBuf {
431 #[inline]
432 fn write(&self, buf: &mut impl BufMut) {
433 self.len().write(buf);
434 buf.put_slice(self.as_ref());
435 }
436
437 #[inline]
438 fn write_bufs(&self, buf: &mut impl BufsMut) {
439 self.len().write(buf);
440 buf.push(self.clone());
441 }
442}
443
444impl EncodeSize for IoBuf {
445 #[inline]
446 fn encode_size(&self) -> usize {
447 self.len().encode_size() + self.len()
448 }
449
450 #[inline]
451 fn encode_inline_size(&self) -> usize {
452 self.len().encode_size()
453 }
454}
455
456impl Read for IoBuf {
457 type Cfg = RangeCfg<usize>;
458
459 #[inline]
460 fn read_cfg(buf: &mut impl Buf, range: &Self::Cfg) -> Result<Self, Error> {
461 let len = usize::read_cfg(buf, range)?;
462 at_least(buf, len)?;
463 Ok(Self::from(buf.copy_to_bytes(len)))
464 }
465}
466
467#[cfg(feature = "arbitrary")]
468impl arbitrary::Arbitrary<'_> for IoBuf {
469 fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
470 let len = u.arbitrary_len::<u8>()?;
471 let data: Vec<u8> = u.arbitrary_iter()?.take(len).collect::<Result<_, _>>()?;
472 Ok(Self::from(data))
473 }
474}
475
476#[derive(Debug)]
487pub struct IoBufMut {
488 inner: IoBufMutInner,
489}
490
491#[derive(Debug)]
494enum IoBufMutInner {
495 Bytes(BytesMut),
496 Aligned(AlignedBufMut),
497 Pooled(PooledBufMut),
498}
499
500impl Default for IoBufMut {
501 fn default() -> Self {
502 Self {
503 inner: IoBufMutInner::Bytes(BytesMut::new()),
504 }
505 }
506}
507
508impl IoBufMut {
509 #[inline]
511 pub fn with_capacity(capacity: usize) -> Self {
512 Self {
513 inner: IoBufMutInner::Bytes(BytesMut::with_capacity(capacity)),
514 }
515 }
516
517 #[inline]
526 pub fn with_alignment(capacity: usize, alignment: NonZeroUsize) -> Self {
527 if capacity == 0 {
528 return Self::with_capacity(0);
529 }
530 let buffer = AlignedBuffer::new(capacity, alignment.get());
531 Self::from_aligned(AlignedBufMut::new(buffer))
532 }
533
534 #[inline]
540 pub fn zeroed_with_alignment(len: usize, alignment: NonZeroUsize) -> Self {
541 if len == 0 {
542 return Self::zeroed(0);
543 }
544 let buffer = AlignedBuffer::new_zeroed(len, alignment.get());
545 let mut buffer = Self::from_aligned(AlignedBufMut::new(buffer));
546 unsafe { buffer.set_len(len) };
548 buffer
549 }
550
551 #[inline]
557 pub fn zeroed(len: usize) -> Self {
558 Self {
559 inner: IoBufMutInner::Bytes(BytesMut::zeroed(len)),
560 }
561 }
562
563 #[inline]
565 const fn from_pooled(pooled: PooledBufMut) -> Self {
566 Self {
567 inner: IoBufMutInner::Pooled(pooled),
568 }
569 }
570
571 #[inline]
573 const fn from_aligned(aligned: AlignedBufMut) -> Self {
574 Self {
575 inner: IoBufMutInner::Aligned(aligned),
576 }
577 }
578
579 #[inline]
588 pub const fn is_pooled(&self) -> bool {
589 match &self.inner {
590 IoBufMutInner::Bytes(_) => false,
591 IoBufMutInner::Aligned(_) => false,
592 IoBufMutInner::Pooled(_) => true,
593 }
594 }
595
596 #[inline]
611 pub unsafe fn set_len(&mut self, len: usize) {
612 assert!(
613 len <= self.capacity(),
614 "set_len({len}) exceeds capacity({})",
615 self.capacity()
616 );
617 match &mut self.inner {
618 IoBufMutInner::Bytes(b) => b.set_len(len),
619 IoBufMutInner::Aligned(b) => b.set_len(len),
620 IoBufMutInner::Pooled(b) => b.set_len(len),
621 }
622 }
623
624 #[inline]
626 pub fn len(&self) -> usize {
627 self.remaining()
628 }
629
630 #[inline]
632 pub fn is_empty(&self) -> bool {
633 match &self.inner {
634 IoBufMutInner::Bytes(b) => b.is_empty(),
635 IoBufMutInner::Aligned(b) => b.is_empty(),
636 IoBufMutInner::Pooled(b) => b.is_empty(),
637 }
638 }
639
640 #[inline]
642 pub fn freeze(self) -> IoBuf {
643 match self.inner {
644 IoBufMutInner::Bytes(b) => b.freeze().into(),
645 IoBufMutInner::Aligned(b) => b.freeze(),
646 IoBufMutInner::Pooled(b) => b.freeze(),
647 }
648 }
649
650 #[inline]
652 pub fn capacity(&self) -> usize {
653 match &self.inner {
654 IoBufMutInner::Bytes(b) => b.capacity(),
655 IoBufMutInner::Aligned(b) => b.capacity(),
656 IoBufMutInner::Pooled(b) => b.capacity(),
657 }
658 }
659
660 #[inline]
662 pub fn as_mut_ptr(&mut self) -> *mut u8 {
663 match &mut self.inner {
664 IoBufMutInner::Bytes(b) => b.as_mut_ptr(),
665 IoBufMutInner::Aligned(b) => b.as_mut_ptr(),
666 IoBufMutInner::Pooled(b) => b.as_mut_ptr(),
667 }
668 }
669
670 #[inline]
674 pub fn truncate(&mut self, len: usize) {
675 match &mut self.inner {
676 IoBufMutInner::Bytes(b) => b.truncate(len),
677 IoBufMutInner::Aligned(b) => b.truncate(len),
678 IoBufMutInner::Pooled(b) => b.truncate(len),
679 }
680 }
681
682 #[inline]
684 pub fn clear(&mut self) {
685 match &mut self.inner {
686 IoBufMutInner::Bytes(b) => b.clear(),
687 IoBufMutInner::Aligned(b) => b.clear(),
688 IoBufMutInner::Pooled(b) => b.clear(),
689 }
690 }
691}
692
693impl AsRef<[u8]> for IoBufMut {
694 #[inline]
695 fn as_ref(&self) -> &[u8] {
696 match &self.inner {
697 IoBufMutInner::Bytes(b) => b.as_ref(),
698 IoBufMutInner::Aligned(b) => b.as_ref(),
699 IoBufMutInner::Pooled(b) => b.as_ref(),
700 }
701 }
702}
703
704impl AsMut<[u8]> for IoBufMut {
705 #[inline]
706 fn as_mut(&mut self) -> &mut [u8] {
707 match &mut self.inner {
708 IoBufMutInner::Bytes(b) => b.as_mut(),
709 IoBufMutInner::Aligned(b) => b.as_mut(),
710 IoBufMutInner::Pooled(b) => b.as_mut(),
711 }
712 }
713}
714
715impl PartialEq<[u8]> for IoBufMut {
716 #[inline]
717 fn eq(&self, other: &[u8]) -> bool {
718 self.as_ref() == other
719 }
720}
721
722impl PartialEq<&[u8]> for IoBufMut {
723 #[inline]
724 fn eq(&self, other: &&[u8]) -> bool {
725 self.as_ref() == *other
726 }
727}
728
729impl<const N: usize> PartialEq<[u8; N]> for IoBufMut {
730 #[inline]
731 fn eq(&self, other: &[u8; N]) -> bool {
732 self.as_ref() == other
733 }
734}
735
736impl<const N: usize> PartialEq<&[u8; N]> for IoBufMut {
737 #[inline]
738 fn eq(&self, other: &&[u8; N]) -> bool {
739 self.as_ref() == *other
740 }
741}
742
743impl Buf for IoBufMut {
744 #[inline]
745 fn remaining(&self) -> usize {
746 match &self.inner {
747 IoBufMutInner::Bytes(b) => b.remaining(),
748 IoBufMutInner::Aligned(b) => b.remaining(),
749 IoBufMutInner::Pooled(b) => b.remaining(),
750 }
751 }
752
753 #[inline]
754 fn chunk(&self) -> &[u8] {
755 match &self.inner {
756 IoBufMutInner::Bytes(b) => b.chunk(),
757 IoBufMutInner::Aligned(b) => b.chunk(),
758 IoBufMutInner::Pooled(b) => b.chunk(),
759 }
760 }
761
762 #[inline]
763 fn advance(&mut self, cnt: usize) {
764 match &mut self.inner {
765 IoBufMutInner::Bytes(b) => b.advance(cnt),
766 IoBufMutInner::Aligned(b) => b.advance(cnt),
767 IoBufMutInner::Pooled(b) => b.advance(cnt),
768 }
769 }
770
771 #[inline]
772 fn copy_to_bytes(&mut self, len: usize) -> Bytes {
773 match &mut self.inner {
774 IoBufMutInner::Bytes(b) => b.copy_to_bytes(len),
775 IoBufMutInner::Aligned(a) => a.copy_to_bytes(len),
776 IoBufMutInner::Pooled(p) => {
777 if len != 0 && len == p.remaining() {
781 let inner =
782 std::mem::replace(&mut self.inner, IoBufMutInner::Bytes(BytesMut::new()));
783 match inner {
784 IoBufMutInner::Pooled(p) => p.into_bytes(),
785 _ => unreachable!(),
786 }
787 } else {
788 p.copy_to_bytes(len)
789 }
790 }
791 }
792 }
793}
794
795unsafe impl BufMut for IoBufMut {
797 #[inline]
798 fn remaining_mut(&self) -> usize {
799 match &self.inner {
800 IoBufMutInner::Bytes(b) => b.remaining_mut(),
801 IoBufMutInner::Aligned(b) => b.remaining_mut(),
802 IoBufMutInner::Pooled(b) => b.remaining_mut(),
803 }
804 }
805
806 #[inline]
807 unsafe fn advance_mut(&mut self, cnt: usize) {
808 match &mut self.inner {
809 IoBufMutInner::Bytes(b) => b.advance_mut(cnt),
810 IoBufMutInner::Aligned(b) => b.advance_mut(cnt),
811 IoBufMutInner::Pooled(b) => b.advance_mut(cnt),
812 }
813 }
814
815 #[inline]
816 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
817 match &mut self.inner {
818 IoBufMutInner::Bytes(b) => b.chunk_mut(),
819 IoBufMutInner::Aligned(b) => b.chunk_mut(),
820 IoBufMutInner::Pooled(b) => b.chunk_mut(),
821 }
822 }
823}
824
825impl From<Vec<u8>> for IoBufMut {
826 fn from(vec: Vec<u8>) -> Self {
827 Self::from(Bytes::from(vec))
828 }
829}
830
831impl From<&[u8]> for IoBufMut {
832 fn from(slice: &[u8]) -> Self {
833 Self {
834 inner: IoBufMutInner::Bytes(BytesMut::from(slice)),
835 }
836 }
837}
838
839impl<const N: usize> From<[u8; N]> for IoBufMut {
840 fn from(array: [u8; N]) -> Self {
841 Self::from(array.as_ref())
842 }
843}
844
845impl<const N: usize> From<&[u8; N]> for IoBufMut {
846 fn from(array: &[u8; N]) -> Self {
847 Self::from(array.as_ref())
848 }
849}
850
851impl From<BytesMut> for IoBufMut {
852 fn from(bytes: BytesMut) -> Self {
853 Self {
854 inner: IoBufMutInner::Bytes(bytes),
855 }
856 }
857}
858
859impl From<Bytes> for IoBufMut {
860 fn from(bytes: Bytes) -> Self {
864 Self {
865 inner: IoBufMutInner::Bytes(BytesMut::from(bytes)),
866 }
867 }
868}
869
870impl From<IoBuf> for IoBufMut {
871 fn from(buf: IoBuf) -> Self {
873 match buf.try_into_mut() {
874 Ok(buf) => buf,
875 Err(buf) => Self::from(buf.as_ref()),
876 }
877 }
878}
879
880#[derive(Clone, Debug)]
882pub struct IoBufs {
883 inner: IoBufsInner,
884}
885
886#[derive(Clone, Debug)]
893enum IoBufsInner {
894 Single(IoBuf),
896 Pair([IoBuf; 2]),
898 Triple([IoBuf; 3]),
900 Chunked(VecDeque<IoBuf>),
902}
903
904impl Default for IoBufs {
905 fn default() -> Self {
906 Self {
907 inner: IoBufsInner::Single(IoBuf::default()),
908 }
909 }
910}
911
912impl IoBufs {
913 fn from_chunks_iter(chunks: impl IntoIterator<Item = IoBuf>) -> Self {
917 let mut iter = chunks.into_iter().filter(|buf| !buf.is_empty());
918 let first = match iter.next() {
919 Some(first) => first,
920 None => return Self::default(),
921 };
922 let second = match iter.next() {
923 Some(second) => second,
924 None => {
925 return Self {
926 inner: IoBufsInner::Single(first),
927 };
928 }
929 };
930 let third = match iter.next() {
931 Some(third) => third,
932 None => {
933 return Self {
934 inner: IoBufsInner::Pair([first, second]),
935 };
936 }
937 };
938 let fourth = match iter.next() {
939 Some(fourth) => fourth,
940 None => {
941 return Self {
942 inner: IoBufsInner::Triple([first, second, third]),
943 };
944 }
945 };
946
947 let mut bufs = VecDeque::with_capacity(4);
948 bufs.push_back(first);
949 bufs.push_back(second);
950 bufs.push_back(third);
951 bufs.push_back(fourth);
952 bufs.extend(iter);
953
954 Self {
955 inner: IoBufsInner::Chunked(bufs),
956 }
957 }
958
959 fn canonicalize(&mut self) {
961 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
962 self.inner = match inner {
963 IoBufsInner::Single(buf) => {
964 if buf.is_empty() {
965 IoBufsInner::Single(IoBuf::default())
966 } else {
967 IoBufsInner::Single(buf)
968 }
969 }
970 IoBufsInner::Pair([a, b]) => Self::from_chunks_iter([a, b]).inner,
971 IoBufsInner::Triple([a, b, c]) => Self::from_chunks_iter([a, b, c]).inner,
972 IoBufsInner::Chunked(bufs) => Self::from_chunks_iter(bufs).inner,
973 };
974 }
975
976 pub const fn as_single(&self) -> Option<&IoBuf> {
980 match &self.inner {
981 IoBufsInner::Single(buf) => Some(buf),
982 _ => None,
983 }
984 }
985
986 pub fn try_into_single(self) -> Result<IoBuf, Self> {
992 match self.inner {
993 IoBufsInner::Single(buf) => Ok(buf),
994 inner => Err(Self { inner }),
995 }
996 }
997
998 #[inline]
1000 pub fn len(&self) -> usize {
1001 self.remaining()
1002 }
1003
1004 #[inline]
1006 pub fn chunk_count(&self) -> usize {
1007 match &self.inner {
1009 IoBufsInner::Single(buf) => {
1010 if buf.is_empty() {
1011 0
1012 } else {
1013 1
1014 }
1015 }
1016 IoBufsInner::Pair(_) => 2,
1017 IoBufsInner::Triple(_) => 3,
1018 IoBufsInner::Chunked(bufs) => bufs.len(),
1019 }
1020 }
1021
1022 #[inline]
1024 pub fn is_empty(&self) -> bool {
1025 self.remaining() == 0
1026 }
1027
1028 #[inline]
1032 pub const fn is_single(&self) -> bool {
1033 matches!(self.inner, IoBufsInner::Single(_))
1034 }
1035
1036 #[inline]
1038 pub fn for_each_chunk(&self, mut f: impl FnMut(&[u8])) {
1039 match &self.inner {
1040 IoBufsInner::Single(buf) => {
1041 let chunk = buf.as_ref();
1042 if !chunk.is_empty() {
1043 f(chunk);
1044 }
1045 }
1046 IoBufsInner::Pair(pair) => {
1047 for buf in pair {
1048 let chunk = buf.as_ref();
1049 if !chunk.is_empty() {
1050 f(chunk);
1051 }
1052 }
1053 }
1054 IoBufsInner::Triple(triple) => {
1055 for buf in triple {
1056 let chunk = buf.as_ref();
1057 if !chunk.is_empty() {
1058 f(chunk);
1059 }
1060 }
1061 }
1062 IoBufsInner::Chunked(bufs) => {
1063 for buf in bufs {
1064 let chunk = buf.as_ref();
1065 if !chunk.is_empty() {
1066 f(chunk);
1067 }
1068 }
1069 }
1070 }
1071 }
1072
1073 pub fn prepend(&mut self, buf: IoBuf) {
1077 if buf.is_empty() {
1078 return;
1079 }
1080 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
1081 self.inner = match inner {
1082 IoBufsInner::Single(existing) if existing.is_empty() => IoBufsInner::Single(buf),
1083 IoBufsInner::Single(existing) => IoBufsInner::Pair([buf, existing]),
1084 IoBufsInner::Pair([a, b]) => IoBufsInner::Triple([buf, a, b]),
1085 IoBufsInner::Triple([a, b, c]) => {
1086 let mut bufs = VecDeque::with_capacity(4);
1087 bufs.push_back(buf);
1088 bufs.push_back(a);
1089 bufs.push_back(b);
1090 bufs.push_back(c);
1091 IoBufsInner::Chunked(bufs)
1092 }
1093 IoBufsInner::Chunked(mut bufs) => {
1094 bufs.push_front(buf);
1095 IoBufsInner::Chunked(bufs)
1096 }
1097 };
1098 }
1099
1100 pub fn append(&mut self, buf: IoBuf) {
1104 if buf.is_empty() {
1105 return;
1106 }
1107 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
1108 self.inner = match inner {
1109 IoBufsInner::Single(existing) if existing.is_empty() => IoBufsInner::Single(buf),
1110 IoBufsInner::Single(existing) => IoBufsInner::Pair([existing, buf]),
1111 IoBufsInner::Pair([a, b]) => IoBufsInner::Triple([a, b, buf]),
1112 IoBufsInner::Triple([a, b, c]) => {
1113 let mut bufs = VecDeque::with_capacity(4);
1114 bufs.push_back(a);
1115 bufs.push_back(b);
1116 bufs.push_back(c);
1117 bufs.push_back(buf);
1118 IoBufsInner::Chunked(bufs)
1119 }
1120 IoBufsInner::Chunked(mut bufs) => {
1121 bufs.push_back(buf);
1122 IoBufsInner::Chunked(bufs)
1123 }
1124 };
1125 }
1126
1127 pub fn split_to(&mut self, at: usize) -> Self {
1139 if at == 0 {
1140 return Self::default();
1141 }
1142
1143 let remaining = self.remaining();
1144 assert!(
1145 at <= remaining,
1146 "split_to out of bounds: {:?} <= {:?}",
1147 at,
1148 remaining,
1149 );
1150
1151 if at == remaining {
1152 return std::mem::take(self);
1153 }
1154
1155 let inner = std::mem::replace(&mut self.inner, IoBufsInner::Single(IoBuf::default()));
1156 match inner {
1157 IoBufsInner::Single(mut buf) => {
1158 let prefix = buf.split_to(at);
1160 self.inner = IoBufsInner::Single(buf);
1161 Self::from(prefix)
1162 }
1163 IoBufsInner::Pair([mut a, mut b]) => {
1164 let a_len = a.remaining();
1165 if at < a_len {
1166 let prefix = a.split_to(at);
1168 self.inner = IoBufsInner::Pair([a, b]);
1169 return Self::from(prefix);
1170 }
1171 if at == a_len {
1172 self.inner = IoBufsInner::Single(b);
1174 return Self::from(a);
1175 }
1176
1177 let b_prefix_len = at - a_len;
1179 let b_prefix = b.split_to(b_prefix_len);
1180 self.inner = IoBufsInner::Single(b);
1181 Self {
1182 inner: IoBufsInner::Pair([a, b_prefix]),
1183 }
1184 }
1185 IoBufsInner::Triple([mut a, mut b, mut c]) => {
1186 let a_len = a.remaining();
1187 if at < a_len {
1188 let prefix = a.split_to(at);
1190 self.inner = IoBufsInner::Triple([a, b, c]);
1191 return Self::from(prefix);
1192 }
1193 if at == a_len {
1194 self.inner = IoBufsInner::Pair([b, c]);
1196 return Self::from(a);
1197 }
1198
1199 let mut remaining = at - a_len;
1200 let b_len = b.remaining();
1201 if remaining < b_len {
1202 let b_prefix = b.split_to(remaining);
1204 self.inner = IoBufsInner::Pair([b, c]);
1205 return Self {
1206 inner: IoBufsInner::Pair([a, b_prefix]),
1207 };
1208 }
1209 if remaining == b_len {
1210 self.inner = IoBufsInner::Single(c);
1212 return Self {
1213 inner: IoBufsInner::Pair([a, b]),
1214 };
1215 }
1216
1217 remaining -= b_len;
1219 let c_prefix = c.split_to(remaining);
1220 self.inner = IoBufsInner::Single(c);
1221 Self {
1222 inner: IoBufsInner::Triple([a, b, c_prefix]),
1223 }
1224 }
1225 IoBufsInner::Chunked(mut bufs) => {
1226 let mut remaining = at;
1227 let mut out = VecDeque::new();
1228
1229 while remaining > 0 {
1230 let mut front = bufs.pop_front().expect("split_to out of bounds");
1231 let avail = front.remaining();
1232 if avail == 0 {
1233 continue;
1235 }
1236 if remaining < avail {
1237 let prefix = front.split_to(remaining);
1239 out.push_back(prefix);
1240 bufs.push_front(front);
1241 break;
1242 }
1243
1244 out.push_back(front);
1246 remaining -= avail;
1247 }
1248
1249 self.inner = if bufs.len() >= 4 {
1250 IoBufsInner::Chunked(bufs)
1251 } else {
1252 Self::from_chunks_iter(bufs).inner
1253 };
1254
1255 if out.len() >= 4 {
1256 Self {
1257 inner: IoBufsInner::Chunked(out),
1258 }
1259 } else {
1260 Self::from_chunks_iter(out)
1261 }
1262 }
1263 }
1264 }
1265
1266 #[inline]
1270 pub fn coalesce(mut self) -> IoBuf {
1271 match self.inner {
1272 IoBufsInner::Single(buf) => buf,
1273 _ => self.copy_to_bytes(self.remaining()).into(),
1274 }
1275 }
1276
1277 pub fn coalesce_with_pool(self, pool: &BufferPool) -> IoBuf {
1282 match self.inner {
1283 IoBufsInner::Single(buf) => buf,
1284 IoBufsInner::Pair([a, b]) => {
1285 let total_len = a.remaining().saturating_add(b.remaining());
1286 let mut result = pool.alloc(total_len);
1287 result.put_slice(a.as_ref());
1288 result.put_slice(b.as_ref());
1289 result.freeze()
1290 }
1291 IoBufsInner::Triple([a, b, c]) => {
1292 let total_len = a
1293 .remaining()
1294 .saturating_add(b.remaining())
1295 .saturating_add(c.remaining());
1296 let mut result = pool.alloc(total_len);
1297 result.put_slice(a.as_ref());
1298 result.put_slice(b.as_ref());
1299 result.put_slice(c.as_ref());
1300 result.freeze()
1301 }
1302 IoBufsInner::Chunked(bufs) => {
1303 let total_len: usize = bufs
1304 .iter()
1305 .map(|b| b.remaining())
1306 .fold(0, usize::saturating_add);
1307 let mut result = pool.alloc(total_len);
1308 for buf in bufs {
1309 result.put_slice(buf.as_ref());
1310 }
1311 result.freeze()
1312 }
1313 }
1314 }
1315}
1316
1317impl Buf for IoBufs {
1318 fn remaining(&self) -> usize {
1319 match &self.inner {
1320 IoBufsInner::Single(buf) => buf.remaining(),
1321 IoBufsInner::Pair([a, b]) => a.remaining().saturating_add(b.remaining()),
1322 IoBufsInner::Triple([a, b, c]) => a
1323 .remaining()
1324 .saturating_add(b.remaining())
1325 .saturating_add(c.remaining()),
1326 IoBufsInner::Chunked(bufs) => bufs
1327 .iter()
1328 .map(|b| b.remaining())
1329 .fold(0, usize::saturating_add),
1330 }
1331 }
1332
1333 fn chunk(&self) -> &[u8] {
1334 match &self.inner {
1335 IoBufsInner::Single(buf) => buf.chunk(),
1336 IoBufsInner::Pair([a, b]) => {
1337 if a.remaining() > 0 {
1338 a.chunk()
1339 } else if b.remaining() > 0 {
1340 b.chunk()
1341 } else {
1342 &[]
1343 }
1344 }
1345 IoBufsInner::Triple([a, b, c]) => {
1346 if a.remaining() > 0 {
1347 a.chunk()
1348 } else if b.remaining() > 0 {
1349 b.chunk()
1350 } else if c.remaining() > 0 {
1351 c.chunk()
1352 } else {
1353 &[]
1354 }
1355 }
1356 IoBufsInner::Chunked(bufs) => {
1357 for buf in bufs.iter() {
1358 if buf.remaining() > 0 {
1359 return buf.chunk();
1360 }
1361 }
1362 &[]
1363 }
1364 }
1365 }
1366
1367 fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
1368 if dst.is_empty() {
1369 return 0;
1370 }
1371
1372 match &self.inner {
1373 IoBufsInner::Single(buf) => {
1374 let chunk = buf.chunk();
1375 if !chunk.is_empty() {
1376 dst[0] = IoSlice::new(chunk);
1377 return 1;
1378 }
1379 0
1380 }
1381 IoBufsInner::Pair([a, b]) => fill_vectored_from_chunks(dst, [a.chunk(), b.chunk()]),
1382 IoBufsInner::Triple([a, b, c]) => {
1383 fill_vectored_from_chunks(dst, [a.chunk(), b.chunk(), c.chunk()])
1384 }
1385 IoBufsInner::Chunked(bufs) => {
1386 fill_vectored_from_chunks(dst, bufs.iter().map(|buf| buf.chunk()))
1387 }
1388 }
1389 }
1390
1391 fn advance(&mut self, cnt: usize) {
1392 let should_canonicalize = match &mut self.inner {
1393 IoBufsInner::Single(buf) => {
1394 buf.advance(cnt);
1395 false
1396 }
1397 IoBufsInner::Pair(pair) => advance_small_chunks(pair.as_mut_slice(), cnt),
1398 IoBufsInner::Triple(triple) => advance_small_chunks(triple.as_mut_slice(), cnt),
1399 IoBufsInner::Chunked(bufs) => {
1400 advance_chunked_front(bufs, cnt);
1401 bufs.len() <= 3
1402 }
1403 };
1404
1405 if should_canonicalize {
1406 self.canonicalize();
1407 }
1408 }
1409
1410 fn copy_to_bytes(&mut self, len: usize) -> Bytes {
1411 let (result, needs_canonicalize) = match &mut self.inner {
1412 IoBufsInner::Single(buf) => return buf.copy_to_bytes(len),
1413 IoBufsInner::Pair(pair) => {
1414 copy_to_bytes_small_chunks(pair, len, "IoBufs::copy_to_bytes: not enough data")
1415 }
1416 IoBufsInner::Triple(triple) => {
1417 copy_to_bytes_small_chunks(triple, len, "IoBufs::copy_to_bytes: not enough data")
1418 }
1419 IoBufsInner::Chunked(bufs) => {
1420 copy_to_bytes_chunked(bufs, len, "IoBufs::copy_to_bytes: not enough data")
1421 }
1422 };
1423
1424 if needs_canonicalize {
1425 self.canonicalize();
1426 }
1427
1428 result
1429 }
1430}
1431
1432impl From<IoBuf> for IoBufs {
1433 fn from(buf: IoBuf) -> Self {
1434 Self {
1435 inner: IoBufsInner::Single(buf),
1436 }
1437 }
1438}
1439
1440impl From<IoBufMut> for IoBufs {
1441 fn from(buf: IoBufMut) -> Self {
1442 Self {
1443 inner: IoBufsInner::Single(buf.freeze()),
1444 }
1445 }
1446}
1447
1448impl From<Bytes> for IoBufs {
1449 fn from(bytes: Bytes) -> Self {
1450 Self::from(IoBuf::from(bytes))
1451 }
1452}
1453
1454impl From<BytesMut> for IoBufs {
1455 fn from(bytes: BytesMut) -> Self {
1456 Self::from(IoBuf::from(bytes.freeze()))
1457 }
1458}
1459
1460impl From<Vec<u8>> for IoBufs {
1461 fn from(vec: Vec<u8>) -> Self {
1462 Self::from(IoBuf::from(vec))
1463 }
1464}
1465
1466impl From<Vec<IoBuf>> for IoBufs {
1467 fn from(bufs: Vec<IoBuf>) -> Self {
1468 Self::from_chunks_iter(bufs)
1469 }
1470}
1471
1472impl<const N: usize> From<&'static [u8; N]> for IoBufs {
1473 fn from(array: &'static [u8; N]) -> Self {
1474 Self::from(IoBuf::from(array))
1475 }
1476}
1477
1478impl From<&'static [u8]> for IoBufs {
1479 fn from(slice: &'static [u8]) -> Self {
1480 Self::from(IoBuf::from(slice))
1481 }
1482}
1483
1484#[derive(Debug)]
1486pub struct IoBufsMut {
1487 inner: IoBufsMutInner,
1488}
1489
1490#[derive(Debug)]
1497enum IoBufsMutInner {
1498 Single(IoBufMut),
1500 Pair([IoBufMut; 2]),
1502 Triple([IoBufMut; 3]),
1504 Chunked(VecDeque<IoBufMut>),
1506}
1507
1508impl Default for IoBufsMut {
1509 fn default() -> Self {
1510 Self {
1511 inner: IoBufsMutInner::Single(IoBufMut::default()),
1512 }
1513 }
1514}
1515
1516impl IoBufsMut {
1517 fn from_chunks_iter(chunks: impl IntoIterator<Item = IoBufMut>) -> Self {
1524 let mut iter = chunks.into_iter();
1525 let first = match iter.next() {
1526 Some(first) => first,
1527 None => return Self::default(),
1528 };
1529 let second = match iter.next() {
1530 Some(second) => second,
1531 None => {
1532 return Self {
1533 inner: IoBufsMutInner::Single(first),
1534 };
1535 }
1536 };
1537 let third = match iter.next() {
1538 Some(third) => third,
1539 None => {
1540 return Self {
1541 inner: IoBufsMutInner::Pair([first, second]),
1542 };
1543 }
1544 };
1545 let fourth = match iter.next() {
1546 Some(fourth) => fourth,
1547 None => {
1548 return Self {
1549 inner: IoBufsMutInner::Triple([first, second, third]),
1550 };
1551 }
1552 };
1553
1554 let mut bufs = VecDeque::with_capacity(4);
1555 bufs.push_back(first);
1556 bufs.push_back(second);
1557 bufs.push_back(third);
1558 bufs.push_back(fourth);
1559 bufs.extend(iter);
1560 Self {
1561 inner: IoBufsMutInner::Chunked(bufs),
1562 }
1563 }
1564
1565 fn from_writable_chunks_iter(chunks: impl IntoIterator<Item = IoBufMut>) -> Self {
1569 Self::from_chunks_iter(chunks.into_iter().filter(|buf| buf.capacity() > 0))
1571 }
1572
1573 fn from_readable_chunks_iter(chunks: impl IntoIterator<Item = IoBufMut>) -> Self {
1577 Self::from_chunks_iter(chunks.into_iter().filter(|buf| buf.remaining() > 0))
1578 }
1579
1580 fn canonicalize(&mut self) {
1582 let inner = std::mem::replace(&mut self.inner, IoBufsMutInner::Single(IoBufMut::default()));
1583 self.inner = match inner {
1584 IoBufsMutInner::Single(buf) => IoBufsMutInner::Single(buf),
1585 IoBufsMutInner::Pair([a, b]) => Self::from_readable_chunks_iter([a, b]).inner,
1586 IoBufsMutInner::Triple([a, b, c]) => Self::from_readable_chunks_iter([a, b, c]).inner,
1587 IoBufsMutInner::Chunked(bufs) => Self::from_readable_chunks_iter(bufs).inner,
1588 };
1589 }
1590
1591 #[inline]
1592 fn for_each_chunk_mut(&mut self, mut f: impl FnMut(&mut IoBufMut)) {
1593 match &mut self.inner {
1594 IoBufsMutInner::Single(buf) => f(buf),
1595 IoBufsMutInner::Pair(pair) => {
1596 for buf in pair.iter_mut() {
1597 f(buf);
1598 }
1599 }
1600 IoBufsMutInner::Triple(triple) => {
1601 for buf in triple.iter_mut() {
1602 f(buf);
1603 }
1604 }
1605 IoBufsMutInner::Chunked(bufs) => {
1606 for buf in bufs.iter_mut() {
1607 f(buf);
1608 }
1609 }
1610 }
1611 }
1612
1613 pub const fn as_single(&self) -> Option<&IoBufMut> {
1617 match &self.inner {
1618 IoBufsMutInner::Single(buf) => Some(buf),
1619 _ => None,
1620 }
1621 }
1622
1623 pub const fn as_single_mut(&mut self) -> Option<&mut IoBufMut> {
1627 match &mut self.inner {
1628 IoBufsMutInner::Single(buf) => Some(buf),
1629 _ => None,
1630 }
1631 }
1632
1633 #[allow(clippy::result_large_err)]
1638 pub fn try_into_single(self) -> Result<IoBufMut, Self> {
1639 match self.inner {
1640 IoBufsMutInner::Single(buf) => Ok(buf),
1641 inner => Err(Self { inner }),
1642 }
1643 }
1644
1645 #[inline]
1647 pub fn len(&self) -> usize {
1648 self.remaining()
1649 }
1650
1651 #[inline]
1653 pub fn is_empty(&self) -> bool {
1654 self.remaining() == 0
1655 }
1656
1657 #[inline]
1661 pub const fn is_single(&self) -> bool {
1662 matches!(self.inner, IoBufsMutInner::Single(_))
1663 }
1664
1665 pub fn freeze(self) -> IoBufs {
1667 match self.inner {
1668 IoBufsMutInner::Single(buf) => IoBufs::from(buf.freeze()),
1669 IoBufsMutInner::Pair([a, b]) => IoBufs::from_chunks_iter([a.freeze(), b.freeze()]),
1670 IoBufsMutInner::Triple([a, b, c]) => {
1671 IoBufs::from_chunks_iter([a.freeze(), b.freeze(), c.freeze()])
1672 }
1673 IoBufsMutInner::Chunked(bufs) => {
1674 IoBufs::from_chunks_iter(bufs.into_iter().map(IoBufMut::freeze))
1675 }
1676 }
1677 }
1678
1679 fn coalesce_with<F>(self, allocate: F) -> IoBufMut
1680 where
1681 F: FnOnce(usize) -> IoBufMut,
1682 {
1683 match self.inner {
1684 IoBufsMutInner::Single(buf) => buf,
1685 IoBufsMutInner::Pair([a, b]) => {
1686 let total_len = a.len().saturating_add(b.len());
1687 let mut result = allocate(total_len);
1688 result.put_slice(a.as_ref());
1689 result.put_slice(b.as_ref());
1690 result
1691 }
1692 IoBufsMutInner::Triple([a, b, c]) => {
1693 let total_len = a.len().saturating_add(b.len()).saturating_add(c.len());
1694 let mut result = allocate(total_len);
1695 result.put_slice(a.as_ref());
1696 result.put_slice(b.as_ref());
1697 result.put_slice(c.as_ref());
1698 result
1699 }
1700 IoBufsMutInner::Chunked(bufs) => {
1701 let total_len: usize = bufs.iter().map(|b| b.len()).fold(0, usize::saturating_add);
1702 let mut result = allocate(total_len);
1703 for buf in bufs {
1704 result.put_slice(buf.as_ref());
1705 }
1706 result
1707 }
1708 }
1709 }
1710
1711 pub fn coalesce(self) -> IoBufMut {
1715 self.coalesce_with(IoBufMut::with_capacity)
1716 }
1717
1718 pub fn coalesce_with_pool(self, pool: &BufferPool) -> IoBufMut {
1723 self.coalesce_with(|len| pool.alloc(len))
1724 }
1725
1726 pub fn coalesce_with_pool_extra(self, pool: &BufferPool, extra: usize) -> IoBufMut {
1731 match self.inner {
1732 IoBufsMutInner::Single(buf) if buf.capacity() - buf.len() >= extra => buf,
1733 IoBufsMutInner::Single(buf) => {
1734 let mut result = pool.alloc(buf.len() + extra);
1735 result.put_slice(buf.as_ref());
1736 result
1737 }
1738 IoBufsMutInner::Pair([a, b]) => {
1739 let total = a.len().saturating_add(b.len());
1740 let mut result = pool.alloc(total + extra);
1741 result.put_slice(a.as_ref());
1742 result.put_slice(b.as_ref());
1743 result
1744 }
1745 IoBufsMutInner::Triple([a, b, c]) => {
1746 let total = a.len().saturating_add(b.len()).saturating_add(c.len());
1747 let mut result = pool.alloc(total + extra);
1748 result.put_slice(a.as_ref());
1749 result.put_slice(b.as_ref());
1750 result.put_slice(c.as_ref());
1751 result
1752 }
1753 IoBufsMutInner::Chunked(bufs) => {
1754 let total: usize = bufs.iter().map(|b| b.len()).fold(0, usize::saturating_add);
1755 let mut result = pool.alloc(total + extra);
1756 for buf in bufs {
1757 result.put_slice(buf.as_ref());
1758 }
1759 result
1760 }
1761 }
1762 }
1763
1764 pub fn capacity(&self) -> usize {
1766 match &self.inner {
1767 IoBufsMutInner::Single(buf) => buf.capacity(),
1768 IoBufsMutInner::Pair([a, b]) => a.capacity().saturating_add(b.capacity()),
1769 IoBufsMutInner::Triple([a, b, c]) => a
1770 .capacity()
1771 .saturating_add(b.capacity())
1772 .saturating_add(c.capacity()),
1773 IoBufsMutInner::Chunked(bufs) => bufs
1774 .iter()
1775 .map(|b| b.capacity())
1776 .fold(0, usize::saturating_add),
1777 }
1778 }
1779
1780 pub(crate) unsafe fn set_len(&mut self, len: usize) {
1794 let capacity = self.capacity();
1795 assert!(
1796 len <= capacity,
1797 "set_len({len}) exceeds capacity({capacity})"
1798 );
1799 let mut remaining = len;
1800 self.for_each_chunk_mut(|buf| {
1801 let cap = buf.capacity();
1802 let to_set = remaining.min(cap);
1803 buf.set_len(to_set);
1804 remaining -= to_set;
1805 });
1806 }
1807
1808 pub fn copy_from_slice(&mut self, src: &[u8]) {
1812 assert_eq!(
1813 src.len(),
1814 self.len(),
1815 "source slice length must match buffer length"
1816 );
1817 let mut offset = 0;
1818 self.for_each_chunk_mut(|buf| {
1819 let len = buf.len();
1820 buf.as_mut().copy_from_slice(&src[offset..offset + len]);
1821 offset += len;
1822 });
1823 }
1824}
1825
1826impl Buf for IoBufsMut {
1827 fn remaining(&self) -> usize {
1828 match &self.inner {
1829 IoBufsMutInner::Single(buf) => buf.remaining(),
1830 IoBufsMutInner::Pair([a, b]) => a.remaining().saturating_add(b.remaining()),
1831 IoBufsMutInner::Triple([a, b, c]) => a
1832 .remaining()
1833 .saturating_add(b.remaining())
1834 .saturating_add(c.remaining()),
1835 IoBufsMutInner::Chunked(bufs) => bufs
1836 .iter()
1837 .map(|b| b.remaining())
1838 .fold(0, usize::saturating_add),
1839 }
1840 }
1841
1842 fn chunk(&self) -> &[u8] {
1843 match &self.inner {
1844 IoBufsMutInner::Single(buf) => buf.chunk(),
1845 IoBufsMutInner::Pair([a, b]) => {
1846 if a.remaining() > 0 {
1847 a.chunk()
1848 } else if b.remaining() > 0 {
1849 b.chunk()
1850 } else {
1851 &[]
1852 }
1853 }
1854 IoBufsMutInner::Triple([a, b, c]) => {
1855 if a.remaining() > 0 {
1856 a.chunk()
1857 } else if b.remaining() > 0 {
1858 b.chunk()
1859 } else if c.remaining() > 0 {
1860 c.chunk()
1861 } else {
1862 &[]
1863 }
1864 }
1865 IoBufsMutInner::Chunked(bufs) => {
1866 for buf in bufs.iter() {
1867 if buf.remaining() > 0 {
1868 return buf.chunk();
1869 }
1870 }
1871 &[]
1872 }
1873 }
1874 }
1875
1876 fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
1877 if dst.is_empty() {
1878 return 0;
1879 }
1880
1881 match &self.inner {
1882 IoBufsMutInner::Single(buf) => {
1883 let chunk = buf.chunk();
1884 if !chunk.is_empty() {
1885 dst[0] = IoSlice::new(chunk);
1886 return 1;
1887 }
1888 0
1889 }
1890 IoBufsMutInner::Pair([a, b]) => fill_vectored_from_chunks(dst, [a.chunk(), b.chunk()]),
1891 IoBufsMutInner::Triple([a, b, c]) => {
1892 fill_vectored_from_chunks(dst, [a.chunk(), b.chunk(), c.chunk()])
1893 }
1894 IoBufsMutInner::Chunked(bufs) => {
1895 fill_vectored_from_chunks(dst, bufs.iter().map(|buf| buf.chunk()))
1896 }
1897 }
1898 }
1899
1900 fn advance(&mut self, cnt: usize) {
1901 let should_canonicalize = match &mut self.inner {
1902 IoBufsMutInner::Single(buf) => {
1903 buf.advance(cnt);
1904 false
1905 }
1906 IoBufsMutInner::Pair(pair) => advance_small_chunks(pair.as_mut_slice(), cnt),
1907 IoBufsMutInner::Triple(triple) => advance_small_chunks(triple.as_mut_slice(), cnt),
1908 IoBufsMutInner::Chunked(bufs) => {
1909 advance_chunked_front(bufs, cnt);
1910 bufs.len() <= 3
1911 }
1912 };
1913
1914 if should_canonicalize {
1915 self.canonicalize();
1916 }
1917 }
1918
1919 fn copy_to_bytes(&mut self, len: usize) -> Bytes {
1920 let (result, needs_canonicalize) = match &mut self.inner {
1921 IoBufsMutInner::Single(buf) => return buf.copy_to_bytes(len),
1922 IoBufsMutInner::Pair(pair) => {
1923 copy_to_bytes_small_chunks(pair, len, "IoBufsMut::copy_to_bytes: not enough data")
1924 }
1925 IoBufsMutInner::Triple(triple) => {
1926 copy_to_bytes_small_chunks(triple, len, "IoBufsMut::copy_to_bytes: not enough data")
1927 }
1928 IoBufsMutInner::Chunked(bufs) => {
1929 copy_to_bytes_chunked(bufs, len, "IoBufsMut::copy_to_bytes: not enough data")
1930 }
1931 };
1932
1933 if needs_canonicalize {
1934 self.canonicalize();
1935 }
1936
1937 result
1938 }
1939}
1940
1941unsafe impl BufMut for IoBufsMut {
1943 #[inline]
1944 fn remaining_mut(&self) -> usize {
1945 match &self.inner {
1946 IoBufsMutInner::Single(buf) => buf.remaining_mut(),
1947 IoBufsMutInner::Pair([a, b]) => a.remaining_mut().saturating_add(b.remaining_mut()),
1948 IoBufsMutInner::Triple([a, b, c]) => a
1949 .remaining_mut()
1950 .saturating_add(b.remaining_mut())
1951 .saturating_add(c.remaining_mut()),
1952 IoBufsMutInner::Chunked(bufs) => bufs
1953 .iter()
1954 .map(|b| b.remaining_mut())
1955 .fold(0, usize::saturating_add),
1956 }
1957 }
1958
1959 #[inline]
1960 unsafe fn advance_mut(&mut self, cnt: usize) {
1961 match &mut self.inner {
1962 IoBufsMutInner::Single(buf) => buf.advance_mut(cnt),
1963 IoBufsMutInner::Pair(pair) => {
1964 let mut remaining = cnt;
1965 if advance_mut_in_chunks(pair, &mut remaining) {
1966 return;
1967 }
1968 panic!("cannot advance past end of buffer");
1969 }
1970 IoBufsMutInner::Triple(triple) => {
1971 let mut remaining = cnt;
1972 if advance_mut_in_chunks(triple, &mut remaining) {
1973 return;
1974 }
1975 panic!("cannot advance past end of buffer");
1976 }
1977 IoBufsMutInner::Chunked(bufs) => {
1978 let mut remaining = cnt;
1979 let (first, second) = bufs.as_mut_slices();
1980 if advance_mut_in_chunks(first, &mut remaining)
1981 || advance_mut_in_chunks(second, &mut remaining)
1982 {
1983 return;
1984 }
1985 panic!("cannot advance past end of buffer");
1986 }
1987 }
1988 }
1989
1990 #[inline]
1991 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
1992 match &mut self.inner {
1993 IoBufsMutInner::Single(buf) => buf.chunk_mut(),
1994 IoBufsMutInner::Pair(pair) => {
1995 if pair[0].remaining_mut() > 0 {
1996 pair[0].chunk_mut()
1997 } else if pair[1].remaining_mut() > 0 {
1998 pair[1].chunk_mut()
1999 } else {
2000 bytes::buf::UninitSlice::new(&mut [])
2001 }
2002 }
2003 IoBufsMutInner::Triple(triple) => {
2004 if triple[0].remaining_mut() > 0 {
2005 triple[0].chunk_mut()
2006 } else if triple[1].remaining_mut() > 0 {
2007 triple[1].chunk_mut()
2008 } else if triple[2].remaining_mut() > 0 {
2009 triple[2].chunk_mut()
2010 } else {
2011 bytes::buf::UninitSlice::new(&mut [])
2012 }
2013 }
2014 IoBufsMutInner::Chunked(bufs) => {
2015 for buf in bufs.iter_mut() {
2016 if buf.remaining_mut() > 0 {
2017 return buf.chunk_mut();
2018 }
2019 }
2020 bytes::buf::UninitSlice::new(&mut [])
2021 }
2022 }
2023 }
2024}
2025
2026impl From<IoBufMut> for IoBufsMut {
2027 fn from(buf: IoBufMut) -> Self {
2028 Self {
2029 inner: IoBufsMutInner::Single(buf),
2030 }
2031 }
2032}
2033
2034impl From<Vec<u8>> for IoBufsMut {
2035 fn from(vec: Vec<u8>) -> Self {
2036 Self {
2037 inner: IoBufsMutInner::Single(IoBufMut::from(vec)),
2038 }
2039 }
2040}
2041
2042impl From<BytesMut> for IoBufsMut {
2043 fn from(bytes: BytesMut) -> Self {
2044 Self {
2045 inner: IoBufsMutInner::Single(IoBufMut::from(bytes)),
2046 }
2047 }
2048}
2049
2050impl From<Vec<IoBufMut>> for IoBufsMut {
2051 fn from(bufs: Vec<IoBufMut>) -> Self {
2052 Self::from_writable_chunks_iter(bufs)
2053 }
2054}
2055
2056impl<const N: usize> From<[u8; N]> for IoBufsMut {
2057 fn from(array: [u8; N]) -> Self {
2058 Self {
2059 inner: IoBufsMutInner::Single(IoBufMut::from(array)),
2060 }
2061 }
2062}
2063
2064#[inline]
2068fn copy_to_bytes_small_chunks<B: Buf, const N: usize>(
2069 chunks: &mut [B; N],
2070 len: usize,
2071 not_enough_data_msg: &str,
2072) -> (Bytes, bool) {
2073 let total = chunks
2074 .iter()
2075 .map(|buf| buf.remaining())
2076 .fold(0, usize::saturating_add);
2077 assert!(total >= len, "{not_enough_data_msg}");
2078
2079 if chunks[0].remaining() >= len {
2080 let bytes = chunks[0].copy_to_bytes(len);
2081 return (bytes, chunks[0].remaining() == 0);
2082 }
2083
2084 let mut out = BytesMut::with_capacity(len);
2085 let mut remaining = len;
2086 for buf in chunks.iter_mut() {
2087 if remaining == 0 {
2088 break;
2089 }
2090 let to_copy = remaining.min(buf.remaining());
2091 out.extend_from_slice(&buf.chunk()[..to_copy]);
2092 buf.advance(to_copy);
2093 remaining -= to_copy;
2094 }
2095
2096 (out.freeze(), true)
2098}
2099
2100#[inline]
2104fn copy_to_bytes_chunked<B: Buf>(
2105 bufs: &mut VecDeque<B>,
2106 len: usize,
2107 not_enough_data_msg: &str,
2108) -> (Bytes, bool) {
2109 while bufs.front().is_some_and(|buf| buf.remaining() == 0) {
2110 bufs.pop_front();
2111 }
2112
2113 if bufs.front().is_none() {
2114 assert_eq!(len, 0, "{not_enough_data_msg}");
2115 return (Bytes::new(), false);
2116 }
2117
2118 if bufs.front().is_some_and(|front| front.remaining() >= len) {
2119 let front = bufs.front_mut().expect("front checked above");
2120 let bytes = front.copy_to_bytes(len);
2121 if front.remaining() == 0 {
2122 bufs.pop_front();
2123 }
2124 return (bytes, bufs.len() <= 3);
2125 }
2126
2127 let total = bufs
2128 .iter()
2129 .map(|buf| buf.remaining())
2130 .fold(0, usize::saturating_add);
2131 assert!(total >= len, "{not_enough_data_msg}");
2132
2133 let mut out = BytesMut::with_capacity(len);
2134 let mut remaining = len;
2135 while remaining > 0 {
2136 let front = bufs
2137 .front_mut()
2138 .expect("remaining > 0 implies non-empty bufs");
2139 let to_copy = remaining.min(front.remaining());
2140 out.extend_from_slice(&front.chunk()[..to_copy]);
2141 front.advance(to_copy);
2142 if front.remaining() == 0 {
2143 bufs.pop_front();
2144 }
2145 remaining -= to_copy;
2146 }
2147
2148 (out.freeze(), bufs.len() <= 3)
2149}
2150
2151#[inline]
2153fn advance_chunked_front<B: Buf>(bufs: &mut VecDeque<B>, mut cnt: usize) {
2154 while cnt > 0 {
2155 let front = bufs.front_mut().expect("cannot advance past end of buffer");
2156 let avail = front.remaining();
2157 if avail == 0 {
2158 bufs.pop_front();
2159 continue;
2160 }
2161 if cnt < avail {
2162 front.advance(cnt);
2163 break;
2164 }
2165 front.advance(avail);
2166 bufs.pop_front();
2167 cnt -= avail;
2168 }
2169}
2170
2171#[inline]
2176fn advance_small_chunks<B: Buf>(chunks: &mut [B], mut cnt: usize) -> bool {
2177 let mut idx = 0;
2178 let mut needs_canonicalize = false;
2179
2180 while cnt > 0 {
2181 let chunk = chunks
2182 .get_mut(idx)
2183 .expect("cannot advance past end of buffer");
2184 let avail = chunk.remaining();
2185 if avail == 0 {
2186 idx += 1;
2187 needs_canonicalize = true;
2188 continue;
2189 }
2190 if cnt < avail {
2191 chunk.advance(cnt);
2192 return needs_canonicalize;
2193 }
2194 chunk.advance(avail);
2195 cnt -= avail;
2196 idx += 1;
2197 needs_canonicalize = true;
2198 }
2199
2200 needs_canonicalize
2201}
2202
2203#[inline]
2212unsafe fn advance_mut_in_chunks<B: BufMut>(chunks: &mut [B], remaining: &mut usize) -> bool {
2213 if *remaining == 0 {
2214 return true;
2215 }
2216
2217 for buf in chunks.iter_mut() {
2218 let avail = buf.chunk_mut().len();
2219 if avail == 0 {
2220 continue;
2221 }
2222 if *remaining <= avail {
2223 unsafe { buf.advance_mut(*remaining) };
2225 *remaining = 0;
2226 return true;
2227 }
2228 unsafe { buf.advance_mut(avail) };
2230 *remaining -= avail;
2231 }
2232 false
2233}
2234
2235#[inline]
2240fn fill_vectored_from_chunks<'a, I>(dst: &mut [IoSlice<'a>], chunks: I) -> usize
2241where
2242 I: IntoIterator<Item = &'a [u8]>,
2243{
2244 let mut written = 0;
2245 for chunk in chunks
2246 .into_iter()
2247 .filter(|chunk| !chunk.is_empty())
2248 .take(dst.len())
2249 {
2250 dst[written] = IoSlice::new(chunk);
2251 written += 1;
2252 }
2253 written
2254}
2255
2256pub struct Builder {
2279 buf: IoBufMut,
2281 pushes: Vec<(usize, Bytes)>,
2284}
2285
2286impl Builder {
2287 pub fn new(pool: &BufferPool, capacity: NonZeroUsize) -> Self {
2293 Self {
2294 buf: pool.alloc(capacity.get()),
2295 pushes: Vec::new(),
2296 }
2297 }
2298
2299 pub fn finish(self) -> IoBufs {
2302 if self.pushes.is_empty() {
2303 return IoBufs::from(self.buf.freeze());
2304 }
2305
2306 let frozen = self.buf.freeze();
2307 let mut result = IoBufs::default();
2308 let mut pos = 0;
2309
2310 for (offset, pushed) in self.pushes {
2311 if offset > pos {
2312 result.append(frozen.slice(pos..offset));
2313 }
2314 result.append(IoBuf::from(pushed));
2315 pos = offset;
2316 }
2317
2318 if pos < frozen.len() {
2319 result.append(frozen.slice(pos..));
2320 }
2321
2322 result
2323 }
2324}
2325
2326unsafe impl BufMut for Builder {
2331 #[inline]
2332 fn remaining_mut(&self) -> usize {
2333 self.buf.remaining_mut()
2334 }
2335
2336 #[inline]
2337 unsafe fn advance_mut(&mut self, cnt: usize) {
2338 self.buf.advance_mut(cnt);
2339 }
2340
2341 #[inline]
2342 fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
2343 self.buf.chunk_mut()
2344 }
2345}
2346
2347impl BufsMut for Builder {
2348 fn push(&mut self, bytes: impl Into<Bytes>) {
2349 let bytes = bytes.into();
2350 if !bytes.is_empty() {
2351 self.pushes.push((self.buf.len(), bytes));
2352 }
2353 }
2354}
2355
2356pub trait EncodeExt: EncodeSize + Write {
2361 fn encode_with_pool_mut(&self, pool: &BufferPool) -> IoBufMut {
2368 let len = self.encode_size();
2369 let mut buf = pool.alloc(len);
2370 self.write(&mut buf);
2371 assert_eq!(
2372 buf.len(),
2373 len,
2374 "write() did not write expected bytes into pooled buffer"
2375 );
2376 buf
2377 }
2378
2379 fn encode_with_pool(&self, pool: &BufferPool) -> IoBufs {
2389 let len = self.encode_size();
2390 let capacity = NonZeroUsize::new(self.encode_inline_size()).unwrap_or(NonZeroUsize::MIN);
2391 let mut builder = Builder::new(pool, capacity);
2392 self.write_bufs(&mut builder);
2393 let bufs = builder.finish();
2394 assert_eq!(
2395 bufs.remaining(),
2396 len,
2397 "write_bufs() did not write expected bytes"
2398 );
2399 bufs
2400 }
2401}
2402
2403impl<T: EncodeSize + Write> EncodeExt for T {}
2404
2405#[cfg(test)]
2406mod tests {
2407 use super::*;
2408 use bytes::{Bytes, BytesMut};
2409 use commonware_codec::{types::lazy::Lazy, Decode, Encode, RangeCfg};
2410 use core::ops::{Range, RangeFrom, RangeInclusive, RangeToInclusive};
2411 use std::collections::{BTreeMap, HashMap};
2412
2413 fn test_pool() -> BufferPool {
2414 cfg_if::cfg_if! {
2415 if #[cfg(miri)] {
2416 let pool_config = BufferPoolConfig {
2418 pool_min_size: 0,
2419 max_per_class: commonware_utils::NZU32!(32),
2420 ..BufferPoolConfig::for_network()
2421 };
2422 } else {
2423 let pool_config = BufferPoolConfig::for_network().with_pool_min_size(0);
2424 }
2425 }
2426 let mut registry = crate::telemetry::metrics::Registry::default();
2427 BufferPool::new(pool_config, &mut registry)
2428 }
2429
2430 fn assert_encode_with_pool_matches_encode<T: Encode + EncodeExt>(value: &T) {
2431 let pool = test_pool();
2432 let mut pooled = value.encode_with_pool(&pool);
2433 let baseline = value.encode();
2434 let mut pooled_bytes = vec![0u8; pooled.remaining()];
2435 pooled.copy_to_slice(&mut pooled_bytes);
2436 assert_eq!(pooled_bytes, baseline.as_ref());
2437 }
2438
2439 #[test]
2440 fn test_iobuf_core_behaviors() {
2441 let buf1 = IoBuf::from(vec![1u8; 1000]);
2443 let buf2 = buf1.clone();
2444 assert_eq!(buf1.as_ref().as_ptr(), buf2.as_ref().as_ptr());
2445
2446 let data = vec![1u8, 2, 3, 4, 5];
2448 let copied = IoBuf::copy_from_slice(&data);
2449 assert_eq!(copied, [1, 2, 3, 4, 5]);
2450 assert_eq!(copied.len(), 5);
2451 let empty = IoBuf::copy_from_slice(&[]);
2452 assert!(empty.is_empty());
2453
2454 let eq = IoBuf::from(b"hello");
2456 assert_eq!(eq, *b"hello");
2457 assert_eq!(eq, b"hello");
2458 assert_ne!(eq, *b"world");
2459 assert_ne!(eq, b"world");
2460 assert_eq!(IoBuf::from(b"hello"), IoBuf::from(b"hello"));
2461 assert_ne!(IoBuf::from(b"hello"), IoBuf::from(b"world"));
2462 let bytes: Bytes = IoBuf::from(b"bytes").into();
2463 assert_eq!(bytes.as_ref(), b"bytes");
2464
2465 let mut buf = IoBuf::from(b"hello world");
2467 assert_eq!(buf.len(), buf.remaining());
2468 assert_eq!(buf.as_ref(), buf.chunk());
2469 assert_eq!(buf.remaining(), 11);
2470 buf.advance(6);
2471 assert_eq!(buf.chunk(), b"world");
2472 assert_eq!(buf.len(), buf.remaining());
2473
2474 let first = buf.copy_to_bytes(2);
2476 assert_eq!(&first[..], b"wo");
2477 let rest = buf.copy_to_bytes(3);
2478 assert_eq!(&rest[..], b"rld");
2479 assert_eq!(buf.remaining(), 0);
2480
2481 let src = IoBuf::from(b"hello world");
2483 assert_eq!(src.slice(..5), b"hello");
2484 assert_eq!(src.slice(6..), b"world");
2485 assert_eq!(src.slice(3..8), b"lo wo");
2486 assert!(src.slice(5..5).is_empty());
2487 }
2488
2489 #[test]
2490 fn test_iobuf_codec_roundtrip() {
2491 let cfg: RangeCfg<usize> = (0..=1024).into();
2492
2493 let original = IoBuf::from(b"hello world");
2494 let encoded = original.encode();
2495 let decoded = IoBuf::decode_cfg(encoded, &cfg).unwrap();
2496 assert_eq!(original, decoded);
2497
2498 let empty = IoBuf::default();
2499 let encoded = empty.encode();
2500 let decoded = IoBuf::decode_cfg(encoded, &cfg).unwrap();
2501 assert_eq!(empty, decoded);
2502
2503 let large_cfg: RangeCfg<usize> = (0..=20000).into();
2504 let large = IoBuf::from(vec![42u8; 10000]);
2505 let encoded = large.encode();
2506 let decoded = IoBuf::decode_cfg(encoded, &large_cfg).unwrap();
2507 assert_eq!(large, decoded);
2508
2509 let mut truncated = BytesMut::new();
2510 4usize.write(&mut truncated);
2511 truncated.extend_from_slice(b"xy");
2512 let mut truncated = truncated.freeze();
2513 assert!(IoBuf::read_cfg(&mut truncated, &cfg).is_err());
2514
2515 let mut direct = BytesMut::new();
2517 4usize.write(&mut direct);
2518 direct.extend_from_slice(b"wxyz");
2519 let mut direct = direct.freeze();
2520 let decoded = IoBuf::read_cfg(&mut direct, &cfg).unwrap();
2521 assert_eq!(decoded, b"wxyz");
2522 }
2523
2524 #[test]
2525 #[should_panic(expected = "cannot advance")]
2526 fn test_iobuf_advance_past_end() {
2527 let mut buf = IoBuf::from(b"hello");
2528 buf.advance(10);
2529 }
2530
2531 #[test]
2532 fn test_iobuf_split_to_consistent_across_backings() {
2533 let pool = test_pool();
2535 let mut pooled = pool.try_alloc(256).expect("pooled allocation");
2536 pooled.put_slice(b"hello world");
2537 let mut pooled_buf = pooled.freeze();
2538 let mut bytes_buf = IoBuf::from(b"hello world");
2539
2540 assert!(pooled_buf.is_pooled());
2541 assert!(!bytes_buf.is_pooled());
2542
2543 let pooled_empty = pooled_buf.split_to(0);
2544 let bytes_empty = bytes_buf.split_to(0);
2545 assert_eq!(pooled_empty, bytes_empty);
2546 assert_eq!(pooled_buf, bytes_buf);
2547 assert!(!pooled_empty.is_pooled());
2548
2549 let pooled_prefix = pooled_buf.split_to(5);
2550 let bytes_prefix = bytes_buf.split_to(5);
2551 assert_eq!(pooled_prefix, bytes_prefix);
2552 assert_eq!(pooled_buf, bytes_buf);
2553 assert!(pooled_prefix.is_pooled());
2554
2555 let pooled_rest = pooled_buf.split_to(pooled_buf.len());
2556 let bytes_rest = bytes_buf.split_to(bytes_buf.len());
2557 assert_eq!(pooled_rest, bytes_rest);
2558 assert_eq!(pooled_buf, bytes_buf);
2559 assert!(pooled_buf.is_empty());
2560 assert!(bytes_buf.is_empty());
2561 assert!(!pooled_buf.is_pooled());
2562 }
2563
2564 #[test]
2565 #[should_panic(expected = "split_to out of bounds")]
2566 fn test_iobuf_split_to_out_of_bounds() {
2567 let mut buf = IoBuf::from(b"abc");
2568 let _ = buf.split_to(4);
2569 }
2570
2571 #[test]
2572 fn test_iobufmut_core_behaviors() {
2573 let mut buf = IoBufMut::with_capacity(100);
2575 assert!(buf.capacity() >= 100);
2576 assert_eq!(buf.len(), 0);
2577 buf.put_slice(b"hello");
2578 buf.put_slice(b" world");
2579 assert_eq!(buf, b"hello world");
2580 assert_eq!(buf, &b"hello world"[..]);
2581 assert_eq!(buf.freeze(), b"hello world");
2582
2583 let mut zeroed = IoBufMut::zeroed(10);
2585 assert_eq!(zeroed, &[0u8; 10]);
2586 unsafe { zeroed.set_len(5) };
2588 assert_eq!(zeroed, &[0u8; 5]);
2589 zeroed.as_mut()[..5].copy_from_slice(b"hello");
2590 assert_eq!(&zeroed.as_ref()[..5], b"hello");
2591 let frozen = zeroed.freeze();
2592 let vec: Vec<u8> = frozen.into();
2593 assert_eq!(&vec[..5], b"hello");
2594
2595 let pool = test_pool();
2597 let mut pooled = pool.alloc(8);
2598 assert!(pooled.is_empty());
2599 pooled.put_slice(b"x");
2600 assert!(!pooled.is_empty());
2601 }
2602
2603 #[test]
2604 fn test_iobufs_shapes_and_read_paths() {
2605 let empty = IoBufs::from(Vec::<u8>::new());
2607 assert!(empty.is_empty());
2608 assert!(empty.is_single());
2609 assert!(empty.as_single().is_some());
2610
2611 let mut single = IoBufs::from(b"hello world");
2613 assert!(single.is_single());
2614 assert_eq!(single.chunk(), b"hello world");
2615 single.advance(6);
2616 assert_eq!(single.chunk(), b"world");
2617 assert_eq!(single.copy_to_bytes(5).as_ref(), b"world");
2618 assert_eq!(single.remaining(), 0);
2619
2620 let mut pair = IoBufs::from(IoBuf::from(b"a"));
2622 pair.append(IoBuf::from(b"b"));
2623 assert!(matches!(pair.inner, IoBufsInner::Pair(_)));
2624 assert!(pair.as_single().is_none());
2625
2626 let mut triple = IoBufs::from(IoBuf::from(b"a"));
2627 triple.append(IoBuf::from(b"b"));
2628 triple.append(IoBuf::from(b"c"));
2629 assert!(matches!(triple.inner, IoBufsInner::Triple(_)));
2630
2631 let mut chunked = IoBufs::from(IoBuf::from(b"a"));
2632 chunked.append(IoBuf::from(b"b"));
2633 chunked.append(IoBuf::from(b"c"));
2634 chunked.append(IoBuf::from(b"d"));
2635 assert!(matches!(chunked.inner, IoBufsInner::Chunked(_)));
2636
2637 let mut joined = IoBufs::from(b"middle");
2639 joined.prepend(IoBuf::from(b"start "));
2640 joined.append(IoBuf::from(b" end"));
2641 assert_eq!(joined.coalesce(), b"start middle end");
2642
2643 let mut prepend_noop = IoBufs::from(b"x");
2645 prepend_noop.prepend(IoBuf::default());
2646 assert_eq!(prepend_noop.coalesce(), b"x");
2647
2648 let mut prepend_into_empty = IoBufs::default();
2650 prepend_into_empty.prepend(IoBuf::from(b"z"));
2651 assert!(prepend_into_empty.is_single());
2652 assert_eq!(prepend_into_empty.coalesce(), b"z");
2653
2654 let mut prepend_pair = IoBufs::from(vec![IoBuf::from(b"b"), IoBuf::from(b"c")]);
2655 prepend_pair.prepend(IoBuf::from(b"a"));
2656 assert!(matches!(prepend_pair.inner, IoBufsInner::Triple(_)));
2657 assert_eq!(prepend_pair.coalesce(), b"abc");
2658
2659 let mut canonical_single = IoBufs::from(b"q");
2661 canonical_single.canonicalize();
2662 assert!(canonical_single.is_single());
2663 assert_eq!(canonical_single.coalesce(), b"q");
2664 }
2665
2666 #[test]
2667 fn test_iobufs_split_to_cases() {
2668 let mut bufs = IoBufs::from(b"hello");
2670
2671 let empty = bufs.split_to(0);
2672 assert!(empty.is_empty());
2673 assert_eq!(bufs.coalesce(), b"hello");
2674
2675 let mut bufs = IoBufs::from(b"hello");
2676 let all = bufs.split_to(5);
2677 assert_eq!(all.coalesce(), b"hello");
2678 assert!(bufs.is_single());
2679 assert!(bufs.is_empty());
2680
2681 let mut single_mid = IoBufs::from(b"hello");
2683 let single_prefix = single_mid.split_to(2);
2684 assert!(single_prefix.is_single());
2685 assert_eq!(single_prefix.coalesce(), b"he");
2686 assert_eq!(single_mid.coalesce(), b"llo");
2687
2688 let mut pair = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
2690 let pair_prefix = pair.split_to(1);
2691 assert!(pair_prefix.is_single());
2692 assert_eq!(pair_prefix.coalesce(), b"a");
2693 assert!(matches!(pair.inner, IoBufsInner::Pair(_)));
2694 assert_eq!(pair.coalesce(), b"bcd");
2695
2696 let mut pair = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
2697 let pair_prefix = pair.split_to(2);
2698 assert!(pair_prefix.is_single());
2699 assert_eq!(pair_prefix.coalesce(), b"ab");
2700 assert!(pair.is_single());
2701 assert_eq!(pair.coalesce(), b"cd");
2702
2703 let mut pair = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
2704 let pair_prefix = pair.split_to(3);
2705 assert!(matches!(pair_prefix.inner, IoBufsInner::Pair(_)));
2706 assert_eq!(pair_prefix.coalesce(), b"abc");
2707 assert!(pair.is_single());
2708 assert_eq!(pair.coalesce(), b"d");
2709
2710 let mut triple = IoBufs::from(vec![
2713 IoBuf::from(b"ab"),
2714 IoBuf::from(b"cd"),
2715 IoBuf::from(b"ef"),
2716 ]);
2717 let triple_prefix = triple.split_to(1);
2718 assert!(triple_prefix.is_single());
2719 assert_eq!(triple_prefix.coalesce(), b"a");
2720 assert!(matches!(triple.inner, IoBufsInner::Triple(_)));
2721 assert_eq!(triple.coalesce(), b"bcdef");
2722
2723 let mut triple = IoBufs::from(vec![
2724 IoBuf::from(b"ab"),
2725 IoBuf::from(b"cd"),
2726 IoBuf::from(b"ef"),
2727 ]);
2728 let triple_prefix = triple.split_to(2);
2729 assert!(triple_prefix.is_single());
2730 assert_eq!(triple_prefix.coalesce(), b"ab");
2731 assert!(matches!(triple.inner, IoBufsInner::Pair(_)));
2732 assert_eq!(triple.coalesce(), b"cdef");
2733
2734 let mut triple = IoBufs::from(vec![
2735 IoBuf::from(b"ab"),
2736 IoBuf::from(b"cd"),
2737 IoBuf::from(b"ef"),
2738 ]);
2739 let triple_prefix = triple.split_to(3);
2740 assert!(matches!(triple_prefix.inner, IoBufsInner::Pair(_)));
2741 assert_eq!(triple_prefix.coalesce(), b"abc");
2742 assert!(matches!(triple.inner, IoBufsInner::Pair(_)));
2743 assert_eq!(triple.coalesce(), b"def");
2744
2745 let mut triple = IoBufs::from(vec![
2746 IoBuf::from(b"ab"),
2747 IoBuf::from(b"cd"),
2748 IoBuf::from(b"ef"),
2749 ]);
2750 let triple_prefix = triple.split_to(4);
2751 assert!(matches!(triple_prefix.inner, IoBufsInner::Pair(_)));
2752 assert_eq!(triple_prefix.coalesce(), b"abcd");
2753 assert!(triple.is_single());
2754 assert_eq!(triple.coalesce(), b"ef");
2755
2756 let mut triple = IoBufs::from(vec![
2757 IoBuf::from(b"ab"),
2758 IoBuf::from(b"cd"),
2759 IoBuf::from(b"ef"),
2760 ]);
2761 let triple_prefix = triple.split_to(5);
2762 assert!(matches!(triple_prefix.inner, IoBufsInner::Triple(_)));
2763 assert_eq!(triple_prefix.coalesce(), b"abcde");
2764 assert!(triple.is_single());
2765 assert_eq!(triple.coalesce(), b"f");
2766
2767 let mut bufs = IoBufs::from(vec![
2769 IoBuf::from(b"ab"),
2770 IoBuf::from(b"cd"),
2771 IoBuf::from(b"ef"),
2772 IoBuf::from(b"gh"),
2773 ]);
2774 let prefix = bufs.split_to(4);
2775 assert!(matches!(prefix.inner, IoBufsInner::Pair(_)));
2776 assert_eq!(prefix.coalesce(), b"abcd");
2777 assert!(matches!(bufs.inner, IoBufsInner::Pair(_)));
2778 assert_eq!(bufs.coalesce(), b"efgh");
2779
2780 let mut bufs = IoBufs::from(vec![
2782 IoBuf::from(b"ab"),
2783 IoBuf::from(b"cd"),
2784 IoBuf::from(b"ef"),
2785 IoBuf::from(b"gh"),
2786 ]);
2787 let prefix = bufs.split_to(5);
2788 assert!(matches!(prefix.inner, IoBufsInner::Triple(_)));
2789 assert_eq!(prefix.coalesce(), b"abcde");
2790 assert!(matches!(bufs.inner, IoBufsInner::Pair(_)));
2791 assert_eq!(bufs.coalesce(), b"fgh");
2792
2793 let mut bufs = IoBufs::from(vec![
2795 IoBuf::from(b"a"),
2796 IoBuf::from(b"b"),
2797 IoBuf::from(b"c"),
2798 IoBuf::from(b"d"),
2799 IoBuf::from(b"e"),
2800 IoBuf::from(b"f"),
2801 IoBuf::from(b"g"),
2802 IoBuf::from(b"h"),
2803 ]);
2804 let prefix = bufs.split_to(4);
2805 assert!(matches!(prefix.inner, IoBufsInner::Chunked(_)));
2806 assert_eq!(prefix.coalesce(), b"abcd");
2807 assert!(matches!(bufs.inner, IoBufsInner::Chunked(_)));
2808 assert_eq!(bufs.coalesce(), b"efgh");
2809
2810 let mut bufs = IoBufs {
2812 inner: IoBufsInner::Chunked(VecDeque::from([
2813 IoBuf::default(),
2814 IoBuf::from(b"ab"),
2815 IoBuf::from(b"cd"),
2816 IoBuf::from(b"ef"),
2817 IoBuf::from(b"gh"),
2818 ])),
2819 };
2820 let prefix = bufs.split_to(3);
2821 assert_eq!(prefix.coalesce(), b"abc");
2822 assert_eq!(bufs.coalesce(), b"defgh");
2823 }
2824
2825 #[test]
2826 #[should_panic(expected = "split_to out of bounds")]
2827 fn test_iobufs_split_to_out_of_bounds() {
2828 let mut bufs = IoBufs::from(b"abc");
2829 let _ = bufs.split_to(4);
2830 }
2831
2832 #[test]
2833 fn test_iobufs_chunk_count() {
2834 assert_eq!(IoBufs::default().chunk_count(), 0);
2835 assert_eq!(IoBufs::from(IoBuf::from(b"a")).chunk_count(), 1);
2836 assert_eq!(
2837 IoBufs::from(vec![IoBuf::from(b"b"), IoBuf::from(b"c")]).chunk_count(),
2838 2
2839 );
2840 assert_eq!(
2841 IoBufs::from(vec![
2842 IoBuf::from(b"a"),
2843 IoBuf::from(b"b"),
2844 IoBuf::from(b"c")
2845 ])
2846 .chunk_count(),
2847 3
2848 );
2849 assert_eq!(
2850 IoBufs::from(vec![
2851 IoBuf::from(b"a"),
2852 IoBuf::from(b"b"),
2853 IoBuf::from(b"c"),
2854 IoBuf::from(b"d")
2855 ])
2856 .chunk_count(),
2857 4
2858 );
2859 }
2860
2861 #[test]
2862 fn test_iobufs_coalesce_after_advance() {
2863 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
2864 bufs.append(IoBuf::from(b" world"));
2865
2866 assert_eq!(bufs.len(), 11);
2867
2868 bufs.advance(3);
2869 assert_eq!(bufs.len(), 8);
2870
2871 assert_eq!(bufs.coalesce(), b"lo world");
2872 }
2873
2874 #[test]
2875 fn test_iobufs_coalesce_with_pool() {
2876 let pool = test_pool();
2877
2878 let buf = IoBuf::from(vec![1u8, 2, 3, 4, 5]);
2880 let original_ptr = buf.as_ptr();
2881 let bufs = IoBufs::from(buf);
2882 let coalesced = bufs.coalesce_with_pool(&pool);
2883 assert_eq!(coalesced, [1, 2, 3, 4, 5]);
2884 assert_eq!(coalesced.as_ptr(), original_ptr);
2885
2886 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
2888 bufs.append(IoBuf::from(b" world"));
2889 let coalesced = bufs.coalesce_with_pool(&pool);
2890 assert_eq!(coalesced, b"hello world");
2891
2892 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
2894 bufs.append(IoBuf::from(b" world"));
2895 bufs.advance(3);
2896 let coalesced = bufs.coalesce_with_pool(&pool);
2897 assert_eq!(coalesced, b"lo world");
2898
2899 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
2901 bufs.append(IoBuf::default());
2902 bufs.append(IoBuf::from(b" world"));
2903 let coalesced = bufs.coalesce_with_pool(&pool);
2904 assert_eq!(coalesced, b"hello world");
2905
2906 let bufs = IoBufs::default();
2908 let coalesced = bufs.coalesce_with_pool(&pool);
2909 assert!(coalesced.is_empty());
2910
2911 let bufs = IoBufs::from(vec![
2913 IoBuf::from(b"ab"),
2914 IoBuf::from(b"cd"),
2915 IoBuf::from(b"ef"),
2916 IoBuf::from(b"gh"),
2917 ]);
2918 let coalesced = bufs.coalesce_with_pool(&pool);
2919 assert_eq!(coalesced, b"abcdefgh");
2920 assert!(coalesced.is_pooled());
2921 }
2922
2923 #[test]
2924 fn test_iobufs_empty_chunks_and_copy_to_bytes_paths() {
2925 let mut bufs = IoBufs::default();
2927 bufs.append(IoBuf::from(b"hello"));
2928 bufs.append(IoBuf::default());
2929 bufs.append(IoBuf::from(b" "));
2930 bufs.append(IoBuf::default());
2931 bufs.append(IoBuf::from(b"world"));
2932 assert_eq!(bufs.len(), 11);
2933 assert_eq!(bufs.chunk(), b"hello");
2934 bufs.advance(5);
2935 assert_eq!(bufs.chunk(), b" ");
2936 bufs.advance(1);
2937 assert_eq!(bufs.chunk(), b"world");
2938
2939 let mut single = IoBufs::from(b"hello world");
2941 assert_eq!(single.copy_to_bytes(5).as_ref(), b"hello");
2942 assert_eq!(single.remaining(), 6);
2943
2944 let mut multi = IoBufs::from(b"hello");
2946 multi.prepend(IoBuf::from(b"say "));
2947 assert_eq!(multi.copy_to_bytes(7).as_ref(), b"say hel");
2948 assert_eq!(multi.copy_to_bytes(2).as_ref(), b"lo");
2949 }
2950
2951 #[test]
2952 fn test_iobufs_copy_to_bytes_pair_and_triple() {
2953 let mut pair = IoBufs::from(IoBuf::from(b"ab"));
2955 pair.append(IoBuf::from(b"cd"));
2956 let first = pair.copy_to_bytes(3);
2957 assert_eq!(&first[..], b"abc");
2958 assert!(pair.is_single());
2959 assert_eq!(pair.chunk(), b"d");
2960
2961 let mut triple = IoBufs::from(IoBuf::from(b"ab"));
2963 triple.append(IoBuf::from(b"cd"));
2964 triple.append(IoBuf::from(b"ef"));
2965 let first = triple.copy_to_bytes(5);
2966 assert_eq!(&first[..], b"abcde");
2967 assert!(triple.is_single());
2968 assert_eq!(triple.chunk(), b"f");
2969 }
2970
2971 #[test]
2972 fn test_iobufs_copy_to_bytes_chunked_four_plus() {
2973 let mut bufs = IoBufs::from(vec![
2974 IoBuf::from(b"ab"),
2975 IoBuf::from(b"cd"),
2976 IoBuf::from(b"ef"),
2977 IoBuf::from(b"gh"),
2978 ]);
2979
2980 let first = bufs.copy_to_bytes(1);
2982 assert_eq!(&first[..], b"a");
2983
2984 let second = bufs.copy_to_bytes(4);
2986 assert_eq!(&second[..], b"bcde");
2987
2988 let rest = bufs.copy_to_bytes(3);
2989 assert_eq!(&rest[..], b"fgh");
2990 assert_eq!(bufs.remaining(), 0);
2991 }
2992
2993 #[test]
2994 fn test_iobufs_copy_to_bytes_edge_cases() {
2995 let mut iobufs = IoBufs::from(IoBuf::from(b""));
2997 iobufs.append(IoBuf::from(b"hello"));
2998 assert_eq!(iobufs.copy_to_bytes(5).as_ref(), b"hello");
2999
3000 let mut boundary = IoBufs::from(IoBuf::from(b"hello"));
3002 boundary.append(IoBuf::from(b"world"));
3003 assert_eq!(boundary.copy_to_bytes(5).as_ref(), b"hello");
3004 assert_eq!(boundary.copy_to_bytes(5).as_ref(), b"world");
3005 assert_eq!(boundary.remaining(), 0);
3006 }
3007
3008 #[test]
3009 #[should_panic(expected = "cannot advance past end of buffer")]
3010 fn test_iobufs_advance_past_end() {
3011 let mut bufs = IoBufs::from(b"hel");
3012 bufs.append(IoBuf::from(b"lo"));
3013 bufs.advance(10);
3014 }
3015
3016 #[test]
3017 #[should_panic(expected = "not enough data")]
3018 fn test_iobufs_copy_to_bytes_past_end() {
3019 let mut bufs = IoBufs::from(b"hel");
3020 bufs.append(IoBuf::from(b"lo"));
3021 bufs.copy_to_bytes(10);
3022 }
3023
3024 #[test]
3025 fn test_iobufs_matches_bytes_chain() {
3026 let b1 = Bytes::from_static(b"hello");
3027 let b2 = Bytes::from_static(b" ");
3028 let b3 = Bytes::from_static(b"world");
3029
3030 let mut chain = b1.clone().chain(b2.clone()).chain(b3.clone());
3032 let mut iobufs = IoBufs::from(IoBuf::from(b1.clone()));
3033 iobufs.append(IoBuf::from(b2.clone()));
3034 iobufs.append(IoBuf::from(b3.clone()));
3035
3036 assert_eq!(chain.remaining(), iobufs.remaining());
3037 assert_eq!(chain.chunk(), iobufs.chunk());
3038
3039 chain.advance(3);
3040 iobufs.advance(3);
3041 assert_eq!(chain.remaining(), iobufs.remaining());
3042 assert_eq!(chain.chunk(), iobufs.chunk());
3043
3044 chain.advance(3);
3045 iobufs.advance(3);
3046 assert_eq!(chain.remaining(), iobufs.remaining());
3047 assert_eq!(chain.chunk(), iobufs.chunk());
3048
3049 let mut chain = b1.clone().chain(b2.clone()).chain(b3.clone());
3051 let mut iobufs = IoBufs::from(IoBuf::from(b1));
3052 iobufs.append(IoBuf::from(b2));
3053 iobufs.append(IoBuf::from(b3));
3054
3055 assert_eq!(chain.copy_to_bytes(3), iobufs.copy_to_bytes(3));
3056 assert_eq!(chain.copy_to_bytes(4), iobufs.copy_to_bytes(4));
3057 assert_eq!(
3058 chain.copy_to_bytes(chain.remaining()),
3059 iobufs.copy_to_bytes(iobufs.remaining())
3060 );
3061 assert_eq!(chain.remaining(), 0);
3062 assert_eq!(iobufs.remaining(), 0);
3063 }
3064
3065 #[test]
3066 fn test_iobufs_try_into_single() {
3067 let single = IoBufs::from(IoBuf::from(b"hello"));
3068 let single = single.try_into_single().expect("single expected");
3069 assert_eq!(single, b"hello");
3070
3071 let multi = IoBufs::from(vec![IoBuf::from(b"ab"), IoBuf::from(b"cd")]);
3072 let multi = multi.try_into_single().expect_err("multi expected");
3073 assert_eq!(multi.coalesce(), b"abcd");
3074 }
3075
3076 #[test]
3077 fn test_iobufs_chunks_vectored_multiple_slices() {
3078 let single = IoBufs::from(IoBuf::from(b"xy"));
3080 let mut single_dst = [IoSlice::new(&[]); 2];
3081 let count = single.chunks_vectored(&mut single_dst);
3082 assert_eq!(count, 1);
3083 assert_eq!(&single_dst[0][..], b"xy");
3084
3085 let empty_single = IoBufs::default();
3087 let mut empty_single_dst = [IoSlice::new(&[]); 1];
3088 assert_eq!(empty_single.chunks_vectored(&mut empty_single_dst), 0);
3089
3090 let bufs = IoBufs::from(vec![
3091 IoBuf::from(b"ab"),
3092 IoBuf::from(b"cd"),
3093 IoBuf::from(b"ef"),
3094 IoBuf::from(b"gh"),
3095 ]);
3096
3097 let mut small = [IoSlice::new(&[]); 2];
3099 let count = bufs.chunks_vectored(&mut small);
3100 assert_eq!(count, 2);
3101 assert_eq!(&small[0][..], b"ab");
3102 assert_eq!(&small[1][..], b"cd");
3103
3104 let mut large = [IoSlice::new(&[]); 8];
3106 let count = bufs.chunks_vectored(&mut large);
3107 assert_eq!(count, 4);
3108 assert_eq!(&large[0][..], b"ab");
3109 assert_eq!(&large[1][..], b"cd");
3110 assert_eq!(&large[2][..], b"ef");
3111 assert_eq!(&large[3][..], b"gh");
3112
3113 let mut empty_dst: [IoSlice<'_>; 0] = [];
3115 assert_eq!(bufs.chunks_vectored(&mut empty_dst), 0);
3116
3117 let sparse = IoBufs {
3119 inner: IoBufsInner::Pair([IoBuf::default(), IoBuf::from(b"x")]),
3120 };
3121 let mut dst = [IoSlice::new(&[]); 2];
3122 let count = sparse.chunks_vectored(&mut dst);
3123 assert_eq!(count, 1);
3124 assert_eq!(&dst[0][..], b"x");
3125
3126 let sparse_triple = IoBufs {
3128 inner: IoBufsInner::Triple([IoBuf::default(), IoBuf::from(b"y"), IoBuf::from(b"z")]),
3129 };
3130 let mut dst = [IoSlice::new(&[]); 3];
3131 let count = sparse_triple.chunks_vectored(&mut dst);
3132 assert_eq!(count, 2);
3133 assert_eq!(&dst[0][..], b"y");
3134 assert_eq!(&dst[1][..], b"z");
3135
3136 let empty_chunked = IoBufs {
3138 inner: IoBufsInner::Chunked(VecDeque::from([IoBuf::default(), IoBuf::default()])),
3139 };
3140 let mut dst = [IoSlice::new(&[]); 2];
3141 assert_eq!(empty_chunked.chunks_vectored(&mut dst), 0);
3142 }
3143
3144 #[test]
3145 fn test_iobufsmut_freeze_chunked() {
3146 let buf1 = IoBufMut::from(b"hello".as_ref());
3148 let buf2 = IoBufMut::from(b" world".as_ref());
3149 let bufs = IoBufsMut::from(vec![buf1, buf2]);
3150 let mut frozen = bufs.freeze();
3151 assert!(!frozen.is_single());
3152 assert_eq!(frozen.chunk(), b"hello");
3153 frozen.advance(5);
3154 assert_eq!(frozen.chunk(), b" world");
3155 frozen.advance(6);
3156 assert_eq!(frozen.remaining(), 0);
3157
3158 let buf1 = IoBufMut::from(b"hello".as_ref());
3160 let empty = IoBufMut::default();
3161 let buf2 = IoBufMut::from(b" world".as_ref());
3162 let bufs = IoBufsMut::from(vec![buf1, empty, buf2]);
3163 let mut frozen = bufs.freeze();
3164 assert!(!frozen.is_single());
3165 assert_eq!(frozen.chunk(), b"hello");
3166 frozen.advance(5);
3167 assert_eq!(frozen.chunk(), b" world");
3168 frozen.advance(6);
3169 assert_eq!(frozen.remaining(), 0);
3170
3171 let empty1 = IoBufMut::default();
3173 let buf = IoBufMut::from(b"only one".as_ref());
3174 let empty2 = IoBufMut::default();
3175 let bufs = IoBufsMut::from(vec![empty1, buf, empty2]);
3176 let frozen = bufs.freeze();
3177 assert!(frozen.is_single());
3178 assert_eq!(frozen.coalesce(), b"only one");
3179
3180 let empty1 = IoBufMut::default();
3182 let empty2 = IoBufMut::default();
3183 let bufs = IoBufsMut::from(vec![empty1, empty2]);
3184 let frozen = bufs.freeze();
3185 assert!(frozen.is_single());
3186 assert!(frozen.is_empty());
3187 }
3188
3189 #[test]
3190 fn test_iobufsmut_coalesce() {
3191 let buf1 = IoBufMut::from(b"hello");
3192 let buf2 = IoBufMut::from(b" world");
3193 let bufs = IoBufsMut::from(vec![buf1, buf2]);
3194 let coalesced = bufs.coalesce();
3195 assert_eq!(coalesced, b"hello world");
3196 }
3197
3198 #[test]
3199 fn test_iobufsmut_from_vec() {
3200 let bufs = IoBufsMut::from(Vec::<IoBufMut>::new());
3202 assert!(bufs.is_single());
3203 assert!(bufs.is_empty());
3204
3205 let buf = IoBufMut::from(b"test");
3207 let bufs = IoBufsMut::from(vec![buf]);
3208 assert!(bufs.is_single());
3209 assert_eq!(bufs.chunk(), b"test");
3210
3211 let buf1 = IoBufMut::from(b"hello");
3213 let buf2 = IoBufMut::from(b" world");
3214 let bufs = IoBufsMut::from(vec![buf1, buf2]);
3215 assert!(!bufs.is_single());
3216 }
3217
3218 #[test]
3219 fn test_iobufsmut_from_vec_filters_empty_chunks() {
3220 let mut bufs = IoBufsMut::from(vec![
3221 IoBufMut::default(),
3222 IoBufMut::from(b"hello"),
3223 IoBufMut::default(),
3224 IoBufMut::from(b" world"),
3225 IoBufMut::default(),
3226 ]);
3227 assert_eq!(bufs.chunk(), b"hello");
3228 bufs.advance(5);
3229 assert_eq!(bufs.chunk(), b" world");
3230 bufs.advance(6);
3231 assert_eq!(bufs.remaining(), 0);
3232 }
3233
3234 #[test]
3235 fn test_iobufsmut_fast_path_shapes() {
3236 let pair = IoBufsMut::from(vec![IoBufMut::from(b"a"), IoBufMut::from(b"b")]);
3237 assert!(matches!(pair.inner, IoBufsMutInner::Pair(_)));
3238
3239 let triple = IoBufsMut::from(vec![
3240 IoBufMut::from(b"a"),
3241 IoBufMut::from(b"b"),
3242 IoBufMut::from(b"c"),
3243 ]);
3244 assert!(matches!(triple.inner, IoBufsMutInner::Triple(_)));
3245
3246 let chunked = IoBufsMut::from(vec![
3247 IoBufMut::from(b"a"),
3248 IoBufMut::from(b"b"),
3249 IoBufMut::from(b"c"),
3250 IoBufMut::from(b"d"),
3251 ]);
3252 assert!(matches!(chunked.inner, IoBufsMutInner::Chunked(_)));
3253 }
3254
3255 #[test]
3256 fn test_iobufsmut_default() {
3257 let bufs = IoBufsMut::default();
3259 assert!(bufs.is_single());
3260 assert!(bufs.is_empty());
3261 assert_eq!(bufs.len(), 0);
3262 }
3263
3264 #[test]
3265 fn test_iobufsmut_from_array() {
3266 let bufs = IoBufsMut::from([1u8, 2, 3, 4, 5]);
3268 assert!(bufs.is_single());
3269 assert_eq!(bufs.len(), 5);
3270 assert_eq!(bufs.chunk(), &[1, 2, 3, 4, 5]);
3271 }
3272
3273 #[test]
3274 fn test_iobufmut_buf_trait() {
3275 let mut buf = IoBufMut::from(b"hello world");
3277 assert_eq!(buf.remaining(), 11);
3278 assert_eq!(buf.chunk(), b"hello world");
3279
3280 buf.advance(6);
3281 assert_eq!(buf.remaining(), 5);
3282 assert_eq!(buf.chunk(), b"world");
3283
3284 buf.advance(5);
3285 assert_eq!(buf.remaining(), 0);
3286 assert!(buf.chunk().is_empty());
3287 }
3288
3289 #[test]
3290 #[should_panic(expected = "cannot advance")]
3291 fn test_iobufmut_advance_past_end() {
3292 let mut buf = IoBufMut::from(b"hello");
3293 buf.advance(10);
3294 }
3295
3296 #[test]
3297 fn test_iobufsmut_buf_trait_chunked() {
3298 let buf1 = IoBufMut::from(b"hello");
3299 let buf2 = IoBufMut::from(b" ");
3300 let buf3 = IoBufMut::from(b"world");
3301 let mut bufs = IoBufsMut::from(vec![buf1, buf2, buf3]);
3302
3303 assert_eq!(bufs.remaining(), 11);
3304 assert_eq!(bufs.chunk(), b"hello");
3305
3306 bufs.advance(3);
3308 assert_eq!(bufs.remaining(), 8);
3309 assert_eq!(bufs.chunk(), b"lo");
3310
3311 bufs.advance(2);
3313 assert_eq!(bufs.remaining(), 6);
3314 assert_eq!(bufs.chunk(), b" ");
3315
3316 bufs.advance(1);
3318 assert_eq!(bufs.remaining(), 5);
3319 assert_eq!(bufs.chunk(), b"world");
3320
3321 bufs.advance(5);
3323 assert_eq!(bufs.remaining(), 0);
3324 }
3325
3326 #[test]
3327 #[should_panic(expected = "cannot advance past end of buffer")]
3328 fn test_iobufsmut_advance_past_end() {
3329 let buf1 = IoBufMut::from(b"hello");
3330 let buf2 = IoBufMut::from(b" world");
3331 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3332 bufs.advance(20);
3333 }
3334
3335 #[test]
3336 fn test_iobufsmut_bufmut_trait_single() {
3337 let mut bufs = IoBufsMut::from(IoBufMut::with_capacity(20));
3338 assert!(bufs.remaining_mut() > 1000);
3340
3341 bufs.put_slice(b"hello");
3342 assert_eq!(bufs.chunk(), b"hello");
3343 assert_eq!(bufs.len(), 5);
3344
3345 bufs.put_slice(b" world");
3346 assert_eq!(bufs.coalesce(), b"hello world");
3347 }
3348
3349 #[test]
3350 fn test_iobufsmut_zeroed_write() {
3351 let bufs = IoBufsMut::from(IoBufMut::zeroed(20));
3353 assert_eq!(bufs.len(), 20);
3354
3355 let mut coalesced = bufs.coalesce();
3357 coalesced.as_mut()[..5].copy_from_slice(b"hello");
3358 assert_eq!(&coalesced.as_ref()[..5], b"hello");
3359 }
3360
3361 #[test]
3362 fn test_iobufsmut_bufmut_put_slice() {
3363 let buf1 = IoBufMut::with_capacity(5);
3365 let buf2 = IoBufMut::with_capacity(6);
3366 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3367
3368 bufs.put_slice(b"hello");
3370 bufs.put_slice(b" world");
3371 assert_eq!(bufs.coalesce(), b"hello world");
3372 }
3373
3374 #[test]
3375 fn test_iobufs_advance_drains_buffers() {
3376 let mut bufs = IoBufs::from(IoBuf::from(b"hello"));
3377 bufs.append(IoBuf::from(b" "));
3378 bufs.append(IoBuf::from(b"world"));
3379
3380 bufs.advance(5);
3382 assert_eq!(bufs.remaining(), 6);
3383 assert_eq!(bufs.chunk(), b" ");
3384
3385 bufs.advance(4);
3387 assert_eq!(bufs.remaining(), 2);
3388 assert_eq!(bufs.chunk(), b"ld");
3389 }
3390
3391 #[test]
3392 fn test_iobufs_advance_exactly_to_boundary() {
3393 let mut bufs = IoBufs::from(IoBuf::from(b"abc"));
3394 bufs.append(IoBuf::from(b"def"));
3395
3396 bufs.advance(3);
3398 assert_eq!(bufs.remaining(), 3);
3399 assert_eq!(bufs.chunk(), b"def");
3400
3401 bufs.advance(3);
3403 assert_eq!(bufs.remaining(), 0);
3404 }
3405
3406 #[test]
3407 fn test_iobufs_advance_canonicalizes_pair_to_single() {
3408 let mut bufs = IoBufs::from(IoBuf::from(b"ab"));
3409 bufs.append(IoBuf::from(b"cd"));
3410 bufs.advance(2);
3411 assert!(bufs.is_single());
3412 assert_eq!(bufs.chunk(), b"cd");
3413 }
3414
3415 #[test]
3416 fn test_iobufsmut_with_empty_buffers() {
3417 let buf1 = IoBufMut::from(b"hello");
3418 let buf2 = IoBufMut::default();
3419 let buf3 = IoBufMut::from(b" world");
3420 let mut bufs = IoBufsMut::from(vec![buf1, buf2, buf3]);
3421
3422 assert_eq!(bufs.remaining(), 11);
3423 assert_eq!(bufs.chunk(), b"hello");
3424
3425 bufs.advance(5);
3427 assert_eq!(bufs.chunk(), b" world");
3429 assert_eq!(bufs.remaining(), 6);
3430 }
3431
3432 #[test]
3433 fn test_iobufsmut_advance_skips_leading_writable_empty_chunk() {
3434 let empty_writable = IoBufMut::with_capacity(4);
3437 let payload = IoBufMut::from(b"xy");
3438 let mut bufs = IoBufsMut::from(vec![empty_writable, payload]);
3439
3440 bufs.advance(1);
3441 assert_eq!(bufs.chunk(), b"y");
3442 assert_eq!(bufs.remaining(), 1);
3443 }
3444
3445 #[test]
3446 fn test_iobufsmut_coalesce_after_advance() {
3447 let buf1 = IoBufMut::from(b"hello");
3449 let buf2 = IoBufMut::from(b" world");
3450 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3451
3452 bufs.advance(3);
3453 assert_eq!(bufs.coalesce(), b"lo world");
3454
3455 let buf1 = IoBufMut::from(b"hello");
3457 let buf2 = IoBufMut::from(b" world");
3458 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3459
3460 bufs.advance(5);
3461 assert_eq!(bufs.coalesce(), b" world");
3462 }
3463
3464 #[test]
3465 fn test_iobufsmut_copy_to_bytes() {
3466 let buf1 = IoBufMut::from(b"hello");
3467 let buf2 = IoBufMut::from(b" world");
3468 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3469
3470 let first = bufs.copy_to_bytes(7);
3472 assert_eq!(&first[..], b"hello w");
3473 assert_eq!(bufs.remaining(), 4);
3474
3475 let rest = bufs.copy_to_bytes(4);
3477 assert_eq!(&rest[..], b"orld");
3478 assert_eq!(bufs.remaining(), 0);
3479 }
3480
3481 #[test]
3482 fn test_iobufsmut_copy_to_bytes_chunked_four_plus() {
3483 let mut bufs = IoBufsMut::from(vec![
3484 IoBufMut::from(b"ab"),
3485 IoBufMut::from(b"cd"),
3486 IoBufMut::from(b"ef"),
3487 IoBufMut::from(b"gh"),
3488 ]);
3489
3490 bufs.advance(1);
3492 assert_eq!(bufs.chunk(), b"b");
3493 bufs.advance(1);
3494 assert_eq!(bufs.chunk(), b"cd");
3495
3496 let first = bufs.copy_to_bytes(1);
3498 assert_eq!(&first[..], b"c");
3499
3500 let second = bufs.copy_to_bytes(4);
3502 assert_eq!(&second[..], b"defg");
3503
3504 let rest = bufs.copy_to_bytes(1);
3505 assert_eq!(&rest[..], b"h");
3506 assert_eq!(bufs.remaining(), 0);
3507
3508 let mut bufs = IoBufsMut::from(vec![
3510 IoBufMut::from(b"a"),
3511 IoBufMut::from(b"b"),
3512 IoBufMut::from(b"c"),
3513 IoBufMut::from(b"d"),
3514 IoBufMut::from(b"e"),
3515 ]);
3516 assert!(matches!(bufs.inner, IoBufsMutInner::Chunked(_)));
3517 let first = bufs.copy_to_bytes(1);
3518 assert_eq!(&first[..], b"a");
3519 let next = bufs.copy_to_bytes(3);
3521 assert_eq!(&next[..], b"bcd");
3522 assert_eq!(bufs.chunk(), b"e");
3523 assert_eq!(bufs.remaining(), 1);
3524 }
3525
3526 #[test]
3527 fn test_iobufsmut_copy_to_bytes_canonicalizes_pair() {
3528 let mut bufs = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
3529 assert!(matches!(bufs.inner, IoBufsMutInner::Pair(_)));
3530
3531 let first = bufs.copy_to_bytes(2);
3532 assert_eq!(&first[..], b"ab");
3533
3534 assert!(bufs.is_single());
3535 assert_eq!(bufs.chunk(), b"cd");
3536 assert_eq!(bufs.remaining(), 2);
3537 }
3538
3539 #[test]
3540 fn test_iobufsmut_copy_from_slice_single() {
3541 let mut bufs = IoBufsMut::from(IoBufMut::zeroed(11));
3542 bufs.copy_from_slice(b"hello world");
3543 assert_eq!(bufs.coalesce(), b"hello world");
3544 }
3545
3546 #[test]
3547 fn test_iobufsmut_copy_from_slice_chunked() {
3548 let buf1 = IoBufMut::zeroed(5);
3549 let buf2 = IoBufMut::zeroed(6);
3550 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3551
3552 bufs.copy_from_slice(b"hello world");
3553
3554 assert_eq!(bufs.chunk(), b"hello");
3556 bufs.advance(5);
3557 assert_eq!(bufs.chunk(), b" world");
3558 bufs.advance(6);
3559 assert_eq!(bufs.remaining(), 0);
3560 }
3561
3562 #[test]
3563 #[should_panic(expected = "source slice length must match buffer length")]
3564 fn test_iobufsmut_copy_from_slice_wrong_length() {
3565 let mut bufs = IoBufsMut::from(IoBufMut::zeroed(5));
3566 bufs.copy_from_slice(b"hello world"); }
3568
3569 #[test]
3570 fn test_iobufsmut_matches_bytesmut_chain() {
3571 let mut bm1 = BytesMut::with_capacity(5);
3573 let mut bm2 = BytesMut::with_capacity(6);
3574 let mut bm3 = BytesMut::with_capacity(7);
3575
3576 let mut iobufs = IoBufsMut::from(vec![
3578 IoBufMut::with_capacity(5),
3579 IoBufMut::with_capacity(6),
3580 IoBufMut::with_capacity(7),
3581 ]);
3582
3583 let chain_len = (&mut bm1)
3585 .chain_mut(&mut bm2)
3586 .chain_mut(&mut bm3)
3587 .chunk_mut()
3588 .len();
3589 let iobufs_len = iobufs.chunk_mut().len();
3590 assert_eq!(chain_len, iobufs_len);
3591
3592 (&mut bm1)
3594 .chain_mut(&mut bm2)
3595 .chain_mut(&mut bm3)
3596 .put_slice(b"hel");
3597 iobufs.put_slice(b"hel");
3598
3599 let chain_len = (&mut bm1)
3601 .chain_mut(&mut bm2)
3602 .chain_mut(&mut bm3)
3603 .chunk_mut()
3604 .len();
3605 let iobufs_len = iobufs.chunk_mut().len();
3606 assert_eq!(chain_len, iobufs_len);
3607
3608 (&mut bm1)
3610 .chain_mut(&mut bm2)
3611 .chain_mut(&mut bm3)
3612 .put_slice(b"lo world!");
3613 iobufs.put_slice(b"lo world!");
3614
3615 let chain_len = (&mut bm1)
3617 .chain_mut(&mut bm2)
3618 .chain_mut(&mut bm3)
3619 .chunk_mut()
3620 .len();
3621 let iobufs_len = iobufs.chunk_mut().len();
3622 assert_eq!(chain_len, iobufs_len);
3623
3624 let frozen = iobufs.freeze().coalesce();
3626 let mut chain_content = bm1.to_vec();
3627 chain_content.extend_from_slice(&bm2);
3628 chain_content.extend_from_slice(&bm3);
3629 assert_eq!(frozen, chain_content.as_slice());
3630 assert_eq!(frozen, b"hello world!");
3631 }
3632
3633 #[test]
3634 fn test_iobufsmut_buf_matches_bytes_chain() {
3635 let mut b1 = Bytes::from_static(b"hello");
3637 let mut b2 = Bytes::from_static(b" world");
3638 let b3 = Bytes::from_static(b"!");
3639
3640 let mut iobufs = IoBufsMut::from(vec![
3642 IoBufMut::from(b"hello"),
3643 IoBufMut::from(b" world"),
3644 IoBufMut::from(b"!"),
3645 ]);
3646
3647 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
3649 assert_eq!(chain_remaining, iobufs.remaining());
3650
3651 let chain_chunk = b1
3653 .clone()
3654 .chain(b2.clone())
3655 .chain(b3.clone())
3656 .chunk()
3657 .to_vec();
3658 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
3659
3660 b1.advance(3);
3662 iobufs.advance(3);
3663
3664 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
3665 assert_eq!(chain_remaining, iobufs.remaining());
3666
3667 let chain_chunk = b1
3668 .clone()
3669 .chain(b2.clone())
3670 .chain(b3.clone())
3671 .chunk()
3672 .to_vec();
3673 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
3674
3675 b1.advance(2);
3677 iobufs.advance(2);
3678
3679 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
3680 assert_eq!(chain_remaining, iobufs.remaining());
3681
3682 let chain_chunk = b1
3684 .clone()
3685 .chain(b2.clone())
3686 .chain(b3.clone())
3687 .chunk()
3688 .to_vec();
3689 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
3690
3691 b2.advance(6);
3693 iobufs.advance(6);
3694
3695 let chain_remaining = b1.clone().chain(b2.clone()).chain(b3.clone()).remaining();
3696 assert_eq!(chain_remaining, iobufs.remaining());
3697
3698 let chain_chunk = b1.chain(b2).chain(b3).chunk().to_vec();
3700 assert_eq!(chain_chunk, iobufs.chunk().to_vec());
3701
3702 let b1 = Bytes::from_static(b"hello");
3704 let b2 = Bytes::from_static(b" world");
3705 let b3 = Bytes::from_static(b"!");
3706 let mut iobufs = IoBufsMut::from(vec![
3707 IoBufMut::from(b"hello"),
3708 IoBufMut::from(b" world"),
3709 IoBufMut::from(b"!"),
3710 ]);
3711
3712 let chain_bytes = b1.chain(b2).chain(b3).copy_to_bytes(8);
3713 let iobufs_bytes = iobufs.copy_to_bytes(8);
3714 assert_eq!(chain_bytes, iobufs_bytes);
3715 assert_eq!(chain_bytes.as_ref(), b"hello wo");
3716 }
3717
3718 #[test]
3719 fn test_iobufsmut_chunks_vectored_multiple_slices() {
3720 let single = IoBufsMut::from(IoBufMut::from(b"xy"));
3722 let mut single_dst = [IoSlice::new(&[]); 2];
3723 let count = single.chunks_vectored(&mut single_dst);
3724 assert_eq!(count, 1);
3725 assert_eq!(&single_dst[0][..], b"xy");
3726
3727 let empty_single = IoBufsMut::default();
3729 let mut empty_single_dst = [IoSlice::new(&[]); 1];
3730 assert_eq!(empty_single.chunks_vectored(&mut empty_single_dst), 0);
3731
3732 let bufs = IoBufsMut::from(vec![
3733 IoBufMut::from(b"ab"),
3734 IoBufMut::from(b"cd"),
3735 IoBufMut::from(b"ef"),
3736 IoBufMut::from(b"gh"),
3737 ]);
3738
3739 let mut small = [IoSlice::new(&[]); 2];
3741 let count = bufs.chunks_vectored(&mut small);
3742 assert_eq!(count, 2);
3743 assert_eq!(&small[0][..], b"ab");
3744 assert_eq!(&small[1][..], b"cd");
3745
3746 let mut large = [IoSlice::new(&[]); 8];
3748 let count = bufs.chunks_vectored(&mut large);
3749 assert_eq!(count, 4);
3750 assert_eq!(&large[0][..], b"ab");
3751 assert_eq!(&large[1][..], b"cd");
3752 assert_eq!(&large[2][..], b"ef");
3753 assert_eq!(&large[3][..], b"gh");
3754
3755 let mut empty_dst: [IoSlice<'_>; 0] = [];
3757 assert_eq!(bufs.chunks_vectored(&mut empty_dst), 0);
3758
3759 let sparse = IoBufsMut {
3761 inner: IoBufsMutInner::Pair([IoBufMut::default(), IoBufMut::from(b"y")]),
3762 };
3763 let mut dst = [IoSlice::new(&[]); 2];
3764 let count = sparse.chunks_vectored(&mut dst);
3765 assert_eq!(count, 1);
3766 assert_eq!(&dst[0][..], b"y");
3767
3768 let sparse_triple = IoBufsMut {
3770 inner: IoBufsMutInner::Triple([
3771 IoBufMut::default(),
3772 IoBufMut::from(b"z"),
3773 IoBufMut::from(b"w"),
3774 ]),
3775 };
3776 let mut dst = [IoSlice::new(&[]); 3];
3777 let count = sparse_triple.chunks_vectored(&mut dst);
3778 assert_eq!(count, 2);
3779 assert_eq!(&dst[0][..], b"z");
3780 assert_eq!(&dst[1][..], b"w");
3781
3782 let empty_chunked = IoBufsMut {
3784 inner: IoBufsMutInner::Chunked(VecDeque::from([
3785 IoBufMut::default(),
3786 IoBufMut::default(),
3787 ])),
3788 };
3789 let mut dst = [IoSlice::new(&[]); 2];
3790 assert_eq!(empty_chunked.chunks_vectored(&mut dst), 0);
3791 }
3792
3793 #[test]
3794 fn test_iobufsmut_try_into_single() {
3795 let single = IoBufsMut::from(IoBufMut::from(b"hello"));
3796 let single = single.try_into_single().expect("single expected");
3797 assert_eq!(single, b"hello");
3798
3799 let multi = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
3800 let multi = multi.try_into_single().expect_err("multi expected");
3801 assert_eq!(multi.coalesce(), b"abcd");
3802 }
3803
3804 #[test]
3805 fn test_iobufsmut_freeze_after_advance() {
3806 let buf1 = IoBufMut::from(b"hello");
3808 let buf2 = IoBufMut::from(b" world");
3809 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3810
3811 bufs.advance(3);
3812 assert_eq!(bufs.len(), 8);
3813
3814 let frozen = bufs.freeze();
3815 assert_eq!(frozen.len(), 8);
3816 assert_eq!(frozen.coalesce(), b"lo world");
3817
3818 let buf1 = IoBufMut::from(b"hello");
3820 let buf2 = IoBufMut::from(b" world");
3821 let mut bufs = IoBufsMut::from(vec![buf1, buf2]);
3822
3823 bufs.advance(5);
3824 assert_eq!(bufs.len(), 6);
3825
3826 let frozen = bufs.freeze();
3829 assert!(frozen.is_single());
3830 assert_eq!(frozen.coalesce(), b" world");
3831 }
3832
3833 #[test]
3834 fn test_iobufsmut_coalesce_with_pool() {
3835 let pool = test_pool();
3836
3837 let mut buf = IoBufMut::from(b"hello");
3839 let original_ptr = buf.as_mut_ptr();
3840 let bufs = IoBufsMut::from(buf);
3841 let coalesced = bufs.coalesce_with_pool(&pool);
3842 assert_eq!(coalesced, b"hello");
3843 assert_eq!(coalesced.as_ref().as_ptr(), original_ptr);
3844
3845 let bufs = IoBufsMut::from(vec![IoBufMut::from(b"hello"), IoBufMut::from(b" world")]);
3847 let coalesced = bufs.coalesce_with_pool(&pool);
3848 assert_eq!(coalesced, b"hello world");
3849 assert!(coalesced.is_pooled());
3850
3851 let bufs = IoBufsMut::from(vec![
3853 IoBufMut::from(b"a"),
3854 IoBufMut::from(b"b"),
3855 IoBufMut::from(b"c"),
3856 IoBufMut::from(b"d"),
3857 ]);
3858 let coalesced = bufs.coalesce_with_pool(&pool);
3859 assert_eq!(coalesced, b"abcd");
3860 assert!(coalesced.is_pooled());
3861
3862 let mut buf = IoBufMut::with_capacity(100);
3864 buf.put_slice(b"hello");
3865 let original_ptr = buf.as_mut_ptr();
3866 let bufs = IoBufsMut::from(buf);
3867 let coalesced = bufs.coalesce_with_pool_extra(&pool, 10);
3868 assert_eq!(coalesced, b"hello");
3869 assert_eq!(coalesced.as_ref().as_ptr(), original_ptr);
3870
3871 let mut buf = IoBufMut::with_capacity(5);
3873 buf.put_slice(b"hello");
3874 let bufs = IoBufsMut::from(buf);
3875 let coalesced = bufs.coalesce_with_pool_extra(&pool, 100);
3876 assert_eq!(coalesced, b"hello");
3877 assert!(coalesced.capacity() >= 105);
3878 }
3879
3880 #[test]
3881 fn test_iobuf_additional_conversion_and_trait_paths() {
3882 let pool = test_pool();
3883
3884 let mut pooled_mut = pool.alloc(4);
3885 pooled_mut.put_slice(b"data");
3886 let pooled = pooled_mut.freeze();
3887 assert!(!pooled.as_ptr().is_null());
3888
3889 let unique = IoBuf::from(Bytes::from(vec![1u8, 2, 3]));
3890 let unique_mut = unique.try_into_mut().expect("unique bytes should convert");
3891 assert_eq!(unique_mut.as_ref(), &[1u8, 2, 3]);
3892
3893 let shared = IoBuf::from(Bytes::from(vec![4u8, 5, 6]));
3894 let _shared_clone = shared.clone();
3895 assert!(shared.try_into_mut().is_err());
3896
3897 let expected: &[u8] = &[9u8, 8];
3898 let eq_buf = IoBuf::from(vec![9u8, 8]);
3899 assert!(PartialEq::<[u8]>::eq(&eq_buf, expected));
3900
3901 let static_slice: &'static [u8] = b"static";
3902 assert_eq!(IoBuf::from(static_slice), b"static");
3903
3904 let mut pooled_mut = pool.alloc(3);
3905 pooled_mut.put_slice(b"xyz");
3906 let pooled = pooled_mut.freeze();
3907 let vec_out: Vec<u8> = pooled.clone().into();
3908 let bytes_out: Bytes = pooled.into();
3909 assert_eq!(vec_out, b"xyz");
3910 assert_eq!(bytes_out.as_ref(), b"xyz");
3911 }
3912
3913 #[test]
3914 fn test_iobuf_into_mut_with_pool() {
3915 let pool = test_pool();
3916
3917 let mut unique = pool.alloc(4);
3919 unique.put_slice(b"data");
3920 let unique_ptr = unique.as_mut_ptr();
3921 let mut recovered = unique.freeze().into_mut_with_pool(&pool);
3922 assert_eq!(recovered.as_ref(), b"data");
3923 assert_eq!(recovered.as_mut_ptr(), unique_ptr);
3924
3925 let mut shared = pool.alloc(4);
3927 shared.put_slice(b"copy");
3928 let shared = shared.freeze();
3929 let shared_ptr = shared.as_ptr();
3930 let _clone = shared.clone();
3931 let mut copied = shared.into_mut_with_pool(&pool);
3932 assert_eq!(copied.as_ref(), b"copy");
3933 assert_ne!(copied.as_mut_ptr() as *const u8, shared_ptr);
3934 assert!(copied.is_pooled());
3935
3936 let mut mirror = pool.alloc(8);
3939 mirror.put_slice(b"abcdefgh");
3940 let mirror_cap = mirror.capacity();
3941 let mirror_ptr = mirror.as_mut_ptr();
3942 let frozen = mirror.freeze();
3943 let head = frozen.slice(0..3);
3944 let tail = frozen.slice(5..8);
3945 drop(head);
3946 drop(tail);
3947 let mut recovered = frozen.into_mut_with_pool(&pool);
3948 assert_eq!(recovered.as_ref(), b"abcdefgh");
3949 assert_eq!(recovered.as_mut_ptr(), mirror_ptr);
3950 assert_eq!(recovered.capacity(), mirror_cap);
3951 }
3952
3953 #[test]
3954 fn test_iobufmut_additional_conversion_and_trait_paths() {
3955 let mut buf = IoBufMut::from(vec![1u8, 2, 3, 4]);
3957 assert!(!buf.is_empty());
3958 buf.truncate(2);
3959 assert_eq!(buf.as_ref(), &[1u8, 2]);
3960 buf.clear();
3961 assert!(buf.is_empty());
3962 buf.put_slice(b"xyz");
3963
3964 let expected: &[u8] = b"xyz";
3966 assert!(PartialEq::<[u8]>::eq(&buf, expected));
3967 assert!(buf == b"xyz"[..]);
3968 assert!(buf == *b"xyz");
3969 assert!(buf == b"xyz");
3970
3971 let from_vec = IoBufMut::from(vec![7u8, 8]);
3973 assert_eq!(from_vec.as_ref(), &[7u8, 8]);
3974
3975 let from_bytesmut = IoBufMut::from(BytesMut::from(&b"hi"[..]));
3976 assert_eq!(from_bytesmut.as_ref(), b"hi");
3977
3978 let from_bytes = IoBufMut::from(Bytes::from_static(b"ok"));
3979 assert_eq!(from_bytes.as_ref(), b"ok");
3980
3981 let from_iobuf = IoBufMut::from(IoBuf::from(Bytes::from_static(b"io")));
3983 assert_eq!(from_iobuf.as_ref(), b"io");
3984 }
3985
3986 #[test]
3987 fn test_iobuf_aligned_public_paths() {
3988 static ARRAY: &[u8; 4] = b"wxyz";
3992
3993 let alignment = NonZeroUsize::new(64).expect("non-zero alignment");
3994
3995 let mut aligned_mut = IoBufMut::with_alignment(8, alignment);
3997 assert!(!aligned_mut.is_pooled());
3998 assert!(aligned_mut.is_empty());
3999 assert_eq!(aligned_mut.capacity(), 8);
4000 assert!((aligned_mut.as_mut_ptr() as usize).is_multiple_of(64));
4001
4002 aligned_mut.put_slice(b"abcdefgh");
4003 assert_eq!(aligned_mut.as_mut(), b"abcdefgh");
4004 assert_eq!(aligned_mut.chunk(), b"abcdefgh");
4005 aligned_mut.advance(2);
4006 assert_eq!(aligned_mut.chunk(), b"cdefgh");
4007
4008 let partial = aligned_mut.copy_to_bytes(2);
4009 assert_eq!(partial.as_ref(), b"cd");
4010 assert_eq!(aligned_mut.as_ref(), b"efgh");
4011 let empty = aligned_mut.copy_to_bytes(0);
4012 assert!(empty.is_empty());
4013 assert_eq!(aligned_mut.as_ref(), b"efgh");
4014
4015 aligned_mut.clear();
4016 assert!(aligned_mut.is_empty());
4017 aligned_mut.put_slice(ARRAY);
4018 assert!(aligned_mut == ARRAY);
4019
4020 let mut fully_drained = IoBufMut::with_alignment(4, alignment);
4022 fully_drained.put_slice(b"lmno");
4023 let empty = fully_drained.copy_to_bytes(0);
4024 assert!(empty.is_empty());
4025 assert_eq!(fully_drained.as_ref(), b"lmno");
4026 let drained = fully_drained.copy_to_bytes(4);
4027 assert_eq!(drained.as_ref(), b"lmno");
4028 assert!(fully_drained.is_empty());
4029
4030 let aligned = aligned_mut.freeze();
4032 assert!(!aligned.is_pooled());
4033 assert_eq!(aligned.as_ref(), &ARRAY[..]);
4034 assert!(aligned == ARRAY);
4035 assert!(!aligned.as_ptr().is_null());
4036 assert_eq!(aligned.slice(..2), b"wx");
4037 assert_eq!(aligned.slice(1..), b"xyz");
4038 assert_eq!(aligned.slice(1..=2), b"xy");
4039 assert_eq!(aligned.chunk(), b"wxyz");
4040
4041 let mut split = aligned.clone();
4042 let prefix = split.split_to(2);
4043 assert_eq!(prefix, b"wx");
4044 assert_eq!(split, b"yz");
4045
4046 let mut advanced = aligned.clone();
4047 advanced.advance(2);
4048 assert_eq!(advanced.chunk(), b"yz");
4049
4050 let mut drained = aligned.clone();
4052 let empty = drained.copy_to_bytes(0);
4053 assert!(empty.is_empty());
4054 assert_eq!(drained.as_ref(), &ARRAY[..]);
4055 let first = drained.copy_to_bytes(1);
4056 assert_eq!(first.as_ref(), b"w");
4057 let rest = drained.copy_to_bytes(3);
4058 assert_eq!(rest.as_ref(), b"xyz");
4059 assert_eq!(drained.remaining(), 0);
4060
4061 let mut unique_source = IoBufMut::zeroed_with_alignment(4, alignment);
4063 unique_source.as_mut().copy_from_slice(b"pqrs");
4064 let unique = unique_source.freeze();
4065 let recovered = unique
4066 .try_into_mut()
4067 .expect("unique aligned iobuf should recover mutability");
4068 assert_eq!(recovered.as_ref(), b"pqrs");
4069
4070 let mut shared_source = IoBufMut::zeroed_with_alignment(4, alignment);
4072 shared_source.as_mut().copy_from_slice(b"tuvw");
4073 let shared = shared_source.freeze();
4074 let _shared_clone = shared.clone();
4075 assert!(shared.try_into_mut().is_err());
4076
4077 let vec_out: Vec<u8> = aligned.clone().into();
4079 let bytes_out: Bytes = aligned.into();
4080 assert_eq!(vec_out, ARRAY.to_vec());
4081 assert_eq!(bytes_out.as_ref(), &ARRAY[..]);
4082
4083 let from_array = IoBuf::from(ARRAY);
4084 assert_eq!(from_array, b"wxyz");
4085
4086 let iobufs = IoBufs::from(ARRAY);
4087 assert_eq!(iobufs.chunk(), b"wxyz");
4088 }
4089
4090 #[test]
4091 fn test_iobufmut_aligned_zero_length_constructors() {
4092 let alignment = NonZeroUsize::new(64).expect("non-zero alignment");
4093
4094 let with_alignment = IoBufMut::with_alignment(0, alignment);
4095 assert!(with_alignment.is_empty());
4096 assert_eq!(with_alignment.len(), 0);
4097 assert_eq!(with_alignment.capacity(), 0);
4098
4099 let zeroed = IoBufMut::zeroed_with_alignment(0, alignment);
4100 assert!(zeroed.is_empty());
4101 assert_eq!(zeroed.len(), 0);
4102 assert_eq!(zeroed.capacity(), 0);
4103 }
4104
4105 #[test]
4106 fn test_iobufs_additional_shape_and_conversion_paths() {
4107 let pool = test_pool();
4108
4109 let from_mut = IoBufs::from(IoBufMut::from(b"m"));
4111 assert_eq!(from_mut.chunk(), b"m");
4112 let from_bytes = IoBufs::from(Bytes::from_static(b"b"));
4113 assert_eq!(from_bytes.chunk(), b"b");
4114 let from_bytesmut = IoBufs::from(BytesMut::from(&b"bm"[..]));
4115 assert_eq!(from_bytesmut.chunk(), b"bm");
4116 let from_vec = IoBufs::from(vec![1u8, 2u8]);
4117 assert_eq!(from_vec.chunk(), &[1u8, 2]);
4118 let static_slice: &'static [u8] = b"slice";
4119 let from_static = IoBufs::from(static_slice);
4120 assert_eq!(from_static.chunk(), b"slice");
4121
4122 let mut single_empty = IoBufs::default();
4124 single_empty.canonicalize();
4125 assert!(single_empty.is_single());
4126
4127 let mut triple = IoBufs::from(vec![
4129 IoBuf::from(b"a".to_vec()),
4130 IoBuf::from(b"b".to_vec()),
4131 IoBuf::from(b"c".to_vec()),
4132 ]);
4133 assert!(triple.as_single().is_none());
4134 triple.prepend(IoBuf::from(vec![b'0']));
4135 triple.prepend(IoBuf::from(vec![b'1']));
4136 triple.append(IoBuf::from(vec![b'2']));
4137 assert_eq!(triple.copy_to_bytes(triple.remaining()).as_ref(), b"10abc2");
4138
4139 let mut triple_append = IoBufs::from(vec![
4141 IoBuf::from(b"x".to_vec()),
4142 IoBuf::from(b"y".to_vec()),
4143 IoBuf::from(b"z".to_vec()),
4144 ]);
4145 triple_append.append(IoBuf::from(vec![b'w']));
4146 assert_eq!(triple_append.coalesce(), b"xyzw");
4147
4148 let triple_pool = IoBufs::from(vec![
4150 IoBuf::from(b"a".to_vec()),
4151 IoBuf::from(b"b".to_vec()),
4152 IoBuf::from(b"c".to_vec()),
4153 ]);
4154 assert_eq!(triple_pool.coalesce_with_pool(&pool), b"abc");
4155
4156 let mut chunked_pool = IoBufs::from(vec![
4158 IoBuf::from(b"a".to_vec()),
4159 IoBuf::from(b"b".to_vec()),
4160 IoBuf::from(b"c".to_vec()),
4161 IoBuf::from(b"d".to_vec()),
4162 ]);
4163 assert_eq!(chunked_pool.remaining(), 4);
4164 chunked_pool.advance(1);
4165 assert_eq!(chunked_pool.coalesce_with_pool(&pool), b"bcd");
4166
4167 let pair_second = IoBufs {
4169 inner: IoBufsInner::Pair([IoBuf::default(), IoBuf::from(vec![1u8])]),
4170 };
4171 assert_eq!(pair_second.chunk(), &[1u8]);
4172 let pair_empty = IoBufs {
4173 inner: IoBufsInner::Pair([IoBuf::default(), IoBuf::default()]),
4174 };
4175 assert_eq!(pair_empty.chunk(), b"");
4176
4177 let triple_third = IoBufs {
4178 inner: IoBufsInner::Triple([
4179 IoBuf::default(),
4180 IoBuf::default(),
4181 IoBuf::from(vec![3u8]),
4182 ]),
4183 };
4184 assert_eq!(triple_third.chunk(), &[3u8]);
4185 let triple_second = IoBufs {
4186 inner: IoBufsInner::Triple([
4187 IoBuf::default(),
4188 IoBuf::from(vec![2u8]),
4189 IoBuf::default(),
4190 ]),
4191 };
4192 assert_eq!(triple_second.chunk(), &[2u8]);
4193 let triple_empty = IoBufs {
4194 inner: IoBufsInner::Triple([IoBuf::default(), IoBuf::default(), IoBuf::default()]),
4195 };
4196 assert_eq!(triple_empty.chunk(), b"");
4197
4198 let chunked_second = IoBufs {
4199 inner: IoBufsInner::Chunked(VecDeque::from([IoBuf::default(), IoBuf::from(vec![9u8])])),
4200 };
4201 assert_eq!(chunked_second.chunk(), &[9u8]);
4202 let chunked_empty = IoBufs {
4203 inner: IoBufsInner::Chunked(VecDeque::from([IoBuf::default()])),
4204 };
4205 assert_eq!(chunked_empty.chunk(), b"");
4206 }
4207
4208 #[test]
4209 fn test_iobufsmut_additional_shape_and_conversion_paths() {
4210 let mut single = IoBufsMut::from(IoBufMut::from(b"x"));
4212 assert!(single.as_single().is_some());
4213 assert!(single.as_single_mut().is_some());
4214 single.canonicalize();
4215 assert!(single.is_single());
4216
4217 let mut pair = IoBufsMut::from(vec![IoBufMut::from(b"a"), IoBufMut::from(b"b")]);
4218 assert!(pair.as_single().is_none());
4219 assert!(pair.as_single_mut().is_none());
4220
4221 let from_vec = IoBufsMut::from(vec![1u8, 2u8]);
4223 assert_eq!(from_vec.chunk(), &[1u8, 2]);
4224 let from_bytesmut = IoBufsMut::from(BytesMut::from(&b"cd"[..]));
4225 assert_eq!(from_bytesmut.chunk(), b"cd");
4226
4227 let mut chunked = IoBufsMut::from(vec![
4229 IoBufMut::with_capacity(1),
4230 IoBufMut::with_capacity(1),
4231 IoBufMut::with_capacity(1),
4232 IoBufMut::with_capacity(1),
4233 ]);
4234 unsafe { chunked.set_len(4) };
4236 chunked.copy_from_slice(b"wxyz");
4237 assert_eq!(chunked.capacity(), 4);
4238 assert_eq!(chunked.remaining(), 4);
4239 let frozen = chunked.freeze();
4240 assert_eq!(frozen.coalesce(), b"wxyz");
4241 }
4242
4243 #[test]
4244 fn test_iobufsmut_coalesce_multi_shape_paths() {
4245 let pool = test_pool();
4246
4247 let pair = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
4249 assert_eq!(pair.coalesce(), b"abcd");
4250 let pair = IoBufsMut::from(vec![IoBufMut::from(b"ab"), IoBufMut::from(b"cd")]);
4251 let pair_extra = pair.coalesce_with_pool_extra(&pool, 3);
4252 assert_eq!(pair_extra, b"abcd");
4253 assert!(pair_extra.capacity() >= 7);
4254
4255 let triple = IoBufsMut::from(vec![
4257 IoBufMut::from(b"a"),
4258 IoBufMut::from(b"b"),
4259 IoBufMut::from(b"c"),
4260 ]);
4261 assert_eq!(triple.coalesce(), b"abc");
4262 let triple = IoBufsMut::from(vec![
4263 IoBufMut::from(b"a"),
4264 IoBufMut::from(b"b"),
4265 IoBufMut::from(b"c"),
4266 ]);
4267 let triple_extra = triple.coalesce_with_pool_extra(&pool, 2);
4268 assert_eq!(triple_extra, b"abc");
4269 assert!(triple_extra.capacity() >= 5);
4270
4271 let chunked = IoBufsMut::from(vec![
4273 IoBufMut::from(b"1"),
4274 IoBufMut::from(b"2"),
4275 IoBufMut::from(b"3"),
4276 IoBufMut::from(b"4"),
4277 ]);
4278 assert_eq!(chunked.coalesce(), b"1234");
4279 let chunked = IoBufsMut::from(vec![
4280 IoBufMut::from(b"1"),
4281 IoBufMut::from(b"2"),
4282 IoBufMut::from(b"3"),
4283 IoBufMut::from(b"4"),
4284 ]);
4285 let chunked_extra = chunked.coalesce_with_pool_extra(&pool, 5);
4286 assert_eq!(chunked_extra, b"1234");
4287 assert!(chunked_extra.capacity() >= 9);
4288 }
4289
4290 #[test]
4291 fn test_iobufsmut_noncanonical_chunk_and_chunk_mut_paths() {
4292 fn no_spare_capacity_buf(pool: &BufferPool) -> IoBufMut {
4293 let mut buf = pool.alloc(1);
4294 let cap = buf.capacity();
4295 unsafe { buf.set_len(cap) };
4297 buf
4298 }
4299 let pool = test_pool();
4300
4301 let pair_second = IoBufsMut {
4303 inner: IoBufsMutInner::Pair([IoBufMut::default(), IoBufMut::from(b"b")]),
4304 };
4305 assert_eq!(pair_second.chunk(), b"b");
4306 let pair_empty = IoBufsMut {
4307 inner: IoBufsMutInner::Pair([IoBufMut::default(), IoBufMut::default()]),
4308 };
4309 assert_eq!(pair_empty.chunk(), b"");
4310
4311 let triple_third = IoBufsMut {
4312 inner: IoBufsMutInner::Triple([
4313 IoBufMut::default(),
4314 IoBufMut::default(),
4315 IoBufMut::from(b"c"),
4316 ]),
4317 };
4318 assert_eq!(triple_third.chunk(), b"c");
4319 let triple_second = IoBufsMut {
4320 inner: IoBufsMutInner::Triple([
4321 IoBufMut::default(),
4322 IoBufMut::from(b"b"),
4323 IoBufMut::default(),
4324 ]),
4325 };
4326 assert_eq!(triple_second.chunk(), b"b");
4327 let triple_empty = IoBufsMut {
4328 inner: IoBufsMutInner::Triple([
4329 IoBufMut::default(),
4330 IoBufMut::default(),
4331 IoBufMut::default(),
4332 ]),
4333 };
4334 assert_eq!(triple_empty.chunk(), b"");
4335
4336 let chunked_second = IoBufsMut {
4337 inner: IoBufsMutInner::Chunked(VecDeque::from([
4338 IoBufMut::default(),
4339 IoBufMut::from(b"d"),
4340 ])),
4341 };
4342 assert_eq!(chunked_second.chunk(), b"d");
4343 let chunked_empty = IoBufsMut {
4344 inner: IoBufsMutInner::Chunked(VecDeque::from([IoBufMut::default()])),
4345 };
4346 assert_eq!(chunked_empty.chunk(), b"");
4347
4348 let mut pair_chunk_mut = IoBufsMut {
4350 inner: IoBufsMutInner::Pair([no_spare_capacity_buf(&pool), IoBufMut::with_capacity(2)]),
4351 };
4352 assert!(pair_chunk_mut.chunk_mut().len() >= 2);
4353
4354 let mut pair_chunk_mut_empty = IoBufsMut {
4355 inner: IoBufsMutInner::Pair([
4356 no_spare_capacity_buf(&pool),
4357 no_spare_capacity_buf(&pool),
4358 ]),
4359 };
4360 assert_eq!(pair_chunk_mut_empty.chunk_mut().len(), 0);
4361
4362 let mut triple_chunk_mut = IoBufsMut {
4363 inner: IoBufsMutInner::Triple([
4364 no_spare_capacity_buf(&pool),
4365 no_spare_capacity_buf(&pool),
4366 IoBufMut::with_capacity(3),
4367 ]),
4368 };
4369 assert!(triple_chunk_mut.chunk_mut().len() >= 3);
4370 let mut triple_chunk_mut_second = IoBufsMut {
4371 inner: IoBufsMutInner::Triple([
4372 no_spare_capacity_buf(&pool),
4373 IoBufMut::with_capacity(2),
4374 no_spare_capacity_buf(&pool),
4375 ]),
4376 };
4377 assert!(triple_chunk_mut_second.chunk_mut().len() >= 2);
4378
4379 let mut triple_chunk_mut_empty = IoBufsMut {
4380 inner: IoBufsMutInner::Triple([
4381 no_spare_capacity_buf(&pool),
4382 no_spare_capacity_buf(&pool),
4383 no_spare_capacity_buf(&pool),
4384 ]),
4385 };
4386 assert_eq!(triple_chunk_mut_empty.chunk_mut().len(), 0);
4387
4388 let mut chunked_chunk_mut = IoBufsMut {
4389 inner: IoBufsMutInner::Chunked(VecDeque::from([
4390 IoBufMut::default(),
4391 IoBufMut::with_capacity(4),
4392 ])),
4393 };
4394 assert!(chunked_chunk_mut.chunk_mut().len() >= 4);
4395
4396 let mut chunked_chunk_mut_empty = IoBufsMut {
4397 inner: IoBufsMutInner::Chunked(VecDeque::from([no_spare_capacity_buf(&pool)])),
4398 };
4399 assert_eq!(chunked_chunk_mut_empty.chunk_mut().len(), 0);
4400 }
4401
4402 #[test]
4403 fn test_iobuf_internal_chunk_helpers() {
4404 let mut empty_with_leading = VecDeque::from([IoBuf::default()]);
4406 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut empty_with_leading, 0, "x");
4407 assert!(bytes.is_empty());
4408 assert!(!needs_canonicalize);
4409 assert!(empty_with_leading.is_empty());
4410
4411 let mut fast = VecDeque::from([
4413 IoBuf::from(b"ab".to_vec()),
4414 IoBuf::from(b"cd".to_vec()),
4415 IoBuf::from(b"ef".to_vec()),
4416 IoBuf::from(b"gh".to_vec()),
4417 ]);
4418 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut fast, 2, "x");
4419 assert_eq!(bytes.as_ref(), b"ab");
4420 assert!(needs_canonicalize);
4421 assert_eq!(fast.front().expect("front exists").as_ref(), b"cd");
4422
4423 let mut slow = VecDeque::from([
4425 IoBuf::from(b"a".to_vec()),
4426 IoBuf::from(b"bc".to_vec()),
4427 IoBuf::from(b"d".to_vec()),
4428 IoBuf::from(b"e".to_vec()),
4429 ]);
4430 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut slow, 3, "x");
4431 assert_eq!(bytes.as_ref(), b"abc");
4432 assert!(needs_canonicalize);
4433
4434 let mut empty_with_leading_mut = VecDeque::from([IoBufMut::default()]);
4435 let (bytes, needs_canonicalize) =
4436 copy_to_bytes_chunked(&mut empty_with_leading_mut, 0, "x");
4437 assert!(bytes.is_empty());
4438 assert!(!needs_canonicalize);
4439 assert!(empty_with_leading_mut.is_empty());
4440
4441 let mut fast_mut = VecDeque::from([
4443 IoBufMut::from(b"ab"),
4444 IoBufMut::from(b"cd"),
4445 IoBufMut::from(b"ef"),
4446 IoBufMut::from(b"gh"),
4447 ]);
4448 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut fast_mut, 2, "x");
4449 assert_eq!(bytes.as_ref(), b"ab");
4450 assert!(needs_canonicalize);
4451 assert_eq!(fast_mut.front().expect("front exists").as_ref(), b"cd");
4452
4453 let mut slow_mut = VecDeque::from([
4454 IoBufMut::from(b"a"),
4455 IoBufMut::from(b"bc"),
4456 IoBufMut::from(b"de"),
4457 IoBufMut::from(b"f"),
4458 ]);
4459 let (bytes, needs_canonicalize) = copy_to_bytes_chunked(&mut slow_mut, 4, "x");
4460 assert_eq!(bytes.as_ref(), b"abcd");
4461 assert!(needs_canonicalize);
4462 assert_eq!(slow_mut.front().expect("front exists").as_ref(), b"e");
4463
4464 let mut advance_chunked = VecDeque::from([
4466 IoBuf::default(),
4467 IoBuf::from(b"abc".to_vec()),
4468 IoBuf::from(b"d".to_vec()),
4469 ]);
4470 advance_chunked_front(&mut advance_chunked, 2);
4471 assert_eq!(
4472 advance_chunked.front().expect("front exists").as_ref(),
4473 b"c"
4474 );
4475 advance_chunked_front(&mut advance_chunked, 2);
4476 assert!(advance_chunked.is_empty());
4477
4478 let mut advance_chunked_mut = VecDeque::from([
4480 IoBufMut::default(),
4481 IoBufMut::from(b"abc"),
4482 IoBufMut::from(b"d"),
4483 ]);
4484 advance_chunked_front(&mut advance_chunked_mut, 2);
4485 assert_eq!(
4486 advance_chunked_mut.front().expect("front exists").as_ref(),
4487 b"c"
4488 );
4489 advance_chunked_front(&mut advance_chunked_mut, 2);
4490 assert!(advance_chunked_mut.is_empty());
4491
4492 let mut small = [IoBuf::default(), IoBuf::from(b"abc".to_vec())];
4494 let needs_canonicalize = advance_small_chunks(&mut small, 2);
4495 assert!(needs_canonicalize);
4496 assert_eq!(small[1].as_ref(), b"c");
4497
4498 let mut small_exact = [
4499 IoBuf::from(b"a".to_vec()),
4500 IoBuf::from(b"b".to_vec()),
4501 IoBuf::from(b"c".to_vec()),
4502 ];
4503 let needs_canonicalize = advance_small_chunks(&mut small_exact, 3);
4504 assert!(needs_canonicalize);
4505 assert_eq!(small_exact[0].remaining(), 0);
4506 assert_eq!(small_exact[1].remaining(), 0);
4507 assert_eq!(small_exact[2].remaining(), 0);
4508
4509 let mut small_mut = [
4511 IoBufMut::from(b"a"),
4512 IoBufMut::from(b"bc"),
4513 IoBufMut::from(b"d"),
4514 ];
4515 let (bytes, needs_canonicalize) = copy_to_bytes_small_chunks(&mut small_mut, 3, "x");
4516 assert_eq!(bytes.as_ref(), b"abc");
4517 assert!(needs_canonicalize);
4518 assert_eq!(small_mut[2].as_ref(), b"d");
4519
4520 let mut writable = [IoBufMut::with_capacity(2), IoBufMut::with_capacity(1)];
4522 let mut remaining = 3usize;
4523 let all_advanced = unsafe { advance_mut_in_chunks(&mut writable, &mut remaining) };
4525 assert!(all_advanced);
4526 assert_eq!(remaining, 0);
4527
4528 let pool = test_pool();
4530 let mut full = pool.alloc(1);
4531 unsafe { full.set_len(full.capacity()) };
4533 let mut writable_after_full = [full, IoBufMut::with_capacity(2)];
4534 let mut remaining = 2usize;
4535 let all_advanced =
4537 unsafe { advance_mut_in_chunks(&mut writable_after_full, &mut remaining) };
4538 assert!(all_advanced);
4539 assert_eq!(remaining, 0);
4540
4541 let mut writable_short = [IoBufMut::with_capacity(1), IoBufMut::with_capacity(1)];
4542 let mut remaining = 3usize;
4543 let all_advanced = unsafe { advance_mut_in_chunks(&mut writable_short, &mut remaining) };
4545 assert!(!all_advanced);
4546 assert_eq!(remaining, 1);
4547 }
4548
4549 #[test]
4550 fn test_iobufsmut_advance_mut_success_paths() {
4551 let mut pair = IoBufsMut {
4553 inner: IoBufsMutInner::Pair([IoBufMut::with_capacity(2), IoBufMut::with_capacity(2)]),
4554 };
4555 unsafe { pair.advance_mut(3) };
4557 assert_eq!(pair.remaining(), 3);
4558
4559 let mut triple = IoBufsMut {
4561 inner: IoBufsMutInner::Triple([
4562 IoBufMut::with_capacity(1),
4563 IoBufMut::with_capacity(1),
4564 IoBufMut::with_capacity(1),
4565 ]),
4566 };
4567 unsafe { triple.advance_mut(2) };
4569 assert_eq!(triple.remaining(), 2);
4570
4571 let mut wrapped = VecDeque::with_capacity(5);
4573 wrapped.push_back(IoBufMut::with_capacity(1));
4574 wrapped.push_back(IoBufMut::with_capacity(1));
4575 wrapped.push_back(IoBufMut::with_capacity(1));
4576 wrapped.push_back(IoBufMut::with_capacity(1));
4577 wrapped.push_back(IoBufMut::with_capacity(1));
4578 let _ = wrapped.pop_front();
4579 wrapped.push_back(IoBufMut::with_capacity(1));
4580 let (first, second) = wrapped.as_slices();
4581 assert!(!first.is_empty());
4582 assert!(!second.is_empty());
4583
4584 let to_advance = first.len() + 1;
4586 let mut chunked = IoBufsMut {
4587 inner: IoBufsMutInner::Chunked(wrapped),
4588 };
4589 unsafe { chunked.advance_mut(to_advance) };
4591 assert_eq!(chunked.remaining(), to_advance);
4592 assert!(chunked.remaining_mut() > 0);
4593 }
4594
4595 #[test]
4596 fn test_iobufsmut_advance_mut_zero_noop_when_full() {
4597 fn full_chunk(pool: &BufferPool) -> IoBufMut {
4598 let mut buf = pool.alloc(1);
4601 let cap = buf.capacity();
4602 unsafe { buf.set_len(cap) };
4604 buf
4605 }
4606
4607 let pool = test_pool();
4608
4609 let mut pair = IoBufsMut::from(vec![full_chunk(&pool), full_chunk(&pool)]);
4611 assert!(matches!(pair.inner, IoBufsMutInner::Pair(_)));
4612 assert_eq!(pair.remaining_mut(), 0);
4613 let before = pair.remaining();
4614 unsafe { pair.advance_mut(0) };
4616 assert_eq!(pair.remaining(), before);
4617
4618 let mut triple = IoBufsMut::from(vec![
4620 full_chunk(&pool),
4621 full_chunk(&pool),
4622 full_chunk(&pool),
4623 ]);
4624 assert!(matches!(triple.inner, IoBufsMutInner::Triple(_)));
4625 assert_eq!(triple.remaining_mut(), 0);
4626 let before = triple.remaining();
4627 unsafe { triple.advance_mut(0) };
4629 assert_eq!(triple.remaining(), before);
4630
4631 let mut chunked = IoBufsMut::from(vec![
4633 full_chunk(&pool),
4634 full_chunk(&pool),
4635 full_chunk(&pool),
4636 full_chunk(&pool),
4637 ]);
4638 assert!(matches!(chunked.inner, IoBufsMutInner::Chunked(_)));
4639 assert_eq!(chunked.remaining_mut(), 0);
4640 let before = chunked.remaining();
4641 unsafe { chunked.advance_mut(0) };
4643 assert_eq!(chunked.remaining(), before);
4644 }
4645
4646 #[test]
4647 #[should_panic(expected = "cannot advance past end of buffer")]
4648 fn test_iobufsmut_advance_mut_past_end_pair() {
4649 let mut pair = IoBufsMut {
4650 inner: IoBufsMutInner::Pair([IoBufMut::with_capacity(1), IoBufMut::with_capacity(1)]),
4651 };
4652 unsafe { pair.advance_mut(3) };
4654 }
4655
4656 #[test]
4657 #[should_panic(expected = "cannot advance past end of buffer")]
4658 fn test_iobufsmut_advance_mut_past_end_triple() {
4659 let mut triple = IoBufsMut {
4660 inner: IoBufsMutInner::Triple([
4661 IoBufMut::with_capacity(1),
4662 IoBufMut::with_capacity(1),
4663 IoBufMut::with_capacity(1),
4664 ]),
4665 };
4666 unsafe { triple.advance_mut(4) };
4668 }
4669
4670 #[test]
4671 #[should_panic(expected = "cannot advance past end of buffer")]
4672 fn test_iobufsmut_advance_mut_past_end_chunked() {
4673 let mut chunked = IoBufsMut {
4674 inner: IoBufsMutInner::Chunked(VecDeque::from([
4675 IoBufMut::with_capacity(1),
4676 IoBufMut::with_capacity(1),
4677 IoBufMut::with_capacity(1),
4678 IoBufMut::with_capacity(1),
4679 ])),
4680 };
4681 unsafe { chunked.advance_mut(5) };
4683 }
4684
4685 #[test]
4686 fn test_iobufsmut_set_len() {
4687 unsafe {
4689 let mut bufs = IoBufsMut::from(IoBufMut::with_capacity(16));
4691 bufs.set_len(10);
4692 assert_eq!(bufs.len(), 10);
4693
4694 let mut bufs = IoBufsMut::from(vec![
4696 IoBufMut::with_capacity(5),
4697 IoBufMut::with_capacity(10),
4698 ]);
4699 bufs.set_len(12);
4700 assert_eq!(bufs.len(), 12);
4701 assert_eq!(bufs.chunk().len(), 5);
4702 bufs.advance(5);
4703 assert_eq!(bufs.chunk().len(), 7);
4704 bufs.advance(7);
4705 assert_eq!(bufs.remaining(), 0);
4706
4707 let mut bufs = IoBufsMut::from(vec![
4709 IoBufMut::with_capacity(3),
4710 IoBufMut::with_capacity(20),
4711 IoBufMut::with_capacity(2),
4712 ]);
4713 bufs.set_len(18);
4714 assert_eq!(bufs.chunk().len(), 3);
4715 bufs.advance(3);
4716 assert_eq!(bufs.chunk().len(), 15);
4717 bufs.advance(15);
4718 assert_eq!(bufs.remaining(), 0);
4719
4720 let mut bufs =
4722 IoBufsMut::from(vec![IoBufMut::with_capacity(4), IoBufMut::with_capacity(4)]);
4723 bufs.set_len(8);
4724 assert_eq!(bufs.chunk().len(), 4);
4725 bufs.advance(4);
4726 assert_eq!(bufs.chunk().len(), 4);
4727 bufs.advance(4);
4728 assert_eq!(bufs.remaining(), 0);
4729
4730 let mut bufs =
4732 IoBufsMut::from(vec![IoBufMut::with_capacity(4), IoBufMut::with_capacity(4)]);
4733 bufs.set_len(0);
4734 assert_eq!(bufs.len(), 0);
4735 assert_eq!(bufs.chunk(), b"");
4736 }
4737 }
4738
4739 #[test]
4740 #[should_panic(expected = "set_len(9) exceeds capacity(8)")]
4741 fn test_iobufsmut_set_len_overflow() {
4742 let mut bufs =
4743 IoBufsMut::from(vec![IoBufMut::with_capacity(4), IoBufMut::with_capacity(4)]);
4744 unsafe { bufs.set_len(9) };
4746 }
4747
4748 #[test]
4749 #[should_panic(expected = "set_len(9) exceeds capacity(8)")]
4750 fn test_iobufmut_set_len_overflow() {
4751 let mut buf = IoBufMut::with_capacity(8);
4752 unsafe { buf.set_len(9) };
4754 }
4755
4756 #[test]
4757 fn test_encode_with_pool_matches_encode() {
4758 let value = vec![1u8, 2, 3, 4, 5, 6];
4759 assert_encode_with_pool_matches_encode(&value);
4760 }
4761
4762 #[test]
4763 fn test_encode_with_pool_mut_len_matches_encode_size() {
4764 let pool = test_pool();
4765 let value = vec![9u8, 8, 7, 6];
4766
4767 let buf = value.encode_with_pool_mut(&pool);
4768 assert_eq!(buf.len(), value.encode_size());
4769 }
4770
4771 #[test]
4772 fn test_iobuf_encode_with_pool_matches_encode() {
4773 let value = IoBuf::from(vec![0xAB; 512]);
4774 assert_encode_with_pool_matches_encode(&value);
4775 }
4776
4777 #[test]
4778 fn test_nested_container_encode_with_pool_matches_encode() {
4779 let value = (
4780 Some(Bytes::from(vec![0xAA; 256])),
4781 vec![Bytes::from(vec![0xBB; 128]), Bytes::from(vec![0xCC; 64])],
4782 );
4783 assert_encode_with_pool_matches_encode(&value);
4784 }
4785
4786 #[test]
4787 fn test_map_encode_with_pool_matches_encode() {
4788 let mut btree = BTreeMap::new();
4789 btree.insert(2u8, Bytes::from(vec![0xDD; 96]));
4790 btree.insert(1u8, Bytes::from(vec![0xEE; 48]));
4791 assert_encode_with_pool_matches_encode(&btree);
4792
4793 let mut hash = HashMap::new();
4794 hash.insert(2u8, Bytes::from(vec![0x11; 96]));
4795 hash.insert(1u8, Bytes::from(vec![0x22; 48]));
4796 assert_encode_with_pool_matches_encode(&hash);
4797 }
4798
4799 #[test]
4800 fn test_lazy_encode_with_pool_matches_encode() {
4801 let value = Lazy::new(Bytes::from(vec![0x44; 200]));
4802 assert_encode_with_pool_matches_encode(&value);
4803 }
4804
4805 #[test]
4806 fn test_range_encode_with_pool_matches_encode() {
4807 let range: Range<Bytes> = Bytes::from(vec![0x10; 32])..Bytes::from(vec![0x20; 48]);
4808 assert_encode_with_pool_matches_encode(&range);
4809
4810 let inclusive: RangeInclusive<Bytes> =
4811 Bytes::from(vec![0x30; 16])..=Bytes::from(vec![0x40; 24]);
4812 assert_encode_with_pool_matches_encode(&inclusive);
4813
4814 let from: RangeFrom<IoBuf> = IoBuf::from(vec![0x50; 40])..;
4815 assert_encode_with_pool_matches_encode(&from);
4816
4817 let to_inclusive: RangeToInclusive<IoBuf> = ..=IoBuf::from(vec![0x60; 56]);
4818 assert_encode_with_pool_matches_encode(&to_inclusive);
4819 }
4820
4821 #[cfg(feature = "arbitrary")]
4822 mod conformance {
4823 use super::IoBuf;
4824 use commonware_codec::conformance::CodecConformance;
4825
4826 commonware_conformance::conformance_tests! {
4827 CodecConformance<IoBuf>
4828 }
4829 }
4830
4831 mod builder_tests {
4832 use super::*;
4833 use commonware_codec::{BufsMut, Encode, Write};
4834
4835 fn builder(capacity: usize) -> Builder {
4836 Builder::new(&test_pool(), NonZeroUsize::new(capacity).unwrap())
4837 }
4838
4839 #[test]
4841 fn test_inline_only() {
4842 let mut b = builder(64);
4843 b.put_u32(42);
4844 b.put_u8(7);
4845 let mut r = b.finish();
4846 assert_eq!(r.remaining(), 5);
4847 assert_eq!(r.get_u32(), 42);
4848 assert_eq!(r.get_u8(), 7);
4849 }
4850
4851 #[test]
4853 fn test_push_only() {
4854 let mut b = builder(64);
4855 let data = Bytes::from(vec![0xAA; 1024]);
4856 b.push(data.clone());
4857 let mut r = b.finish();
4858 assert_eq!(r.remaining(), 1024);
4859 assert_eq!(r.copy_to_bytes(1024), data);
4860 }
4861
4862 #[test]
4864 fn test_inline_push_inline() {
4865 let mut b = builder(64);
4866 b.put_u16(99);
4867 let payload = Bytes::from(vec![0xBB; 512]);
4868 b.push(payload.clone());
4869 b.put_u8(1);
4870 let mut r = b.finish();
4871 assert_eq!(r.remaining(), 2 + 512 + 1);
4872 assert_eq!(r.get_u16(), 99);
4873 assert_eq!(r.copy_to_bytes(512), payload);
4874 assert_eq!(r.get_u8(), 1);
4875 }
4876
4877 #[test]
4879 fn test_write_bufs_matches_write() {
4880 let data = Bytes::from(vec![0xCC; 256]);
4881 let mut b = builder(64);
4882 data.write_bufs(&mut b);
4883 let mut bufs = b.finish();
4884
4885 let mut out = vec![0u8; bufs.remaining()];
4886 bufs.copy_to_slice(&mut out);
4887 assert_eq!(out, data.encode().as_ref());
4888 }
4889
4890 #[test]
4892 fn test_empty() {
4893 let bufs = builder(64).finish();
4894 assert_eq!(bufs.remaining(), 0);
4895 }
4896
4897 #[test]
4899 #[should_panic]
4900 fn test_inline_overflow_panics() {
4901 let mut b = builder(1);
4902 let cap = b.remaining_mut();
4903 b.put_slice(&vec![0xFF; cap]);
4904 b.put_u8(1); }
4906
4907 #[test]
4909 fn test_empty_push_ignored() {
4910 let mut b = builder(64);
4911 b.push(Bytes::new());
4912 b.put_u8(1);
4913 let bufs = b.finish();
4914 assert_eq!(bufs.remaining(), 1);
4915 }
4916
4917 #[test]
4919 fn test_multiple_pushes() {
4920 let mut b = builder(64);
4921 let a = Bytes::from(vec![0xAA; 100]);
4922 let c = Bytes::from(vec![0xCC; 200]);
4923 b.push(a.clone());
4924 b.push(c.clone());
4925 let mut r = b.finish();
4926 assert_eq!(r.remaining(), 300);
4927 assert_eq!(r.copy_to_bytes(100), a);
4928 assert_eq!(r.copy_to_bytes(200), c);
4929 }
4930
4931 #[test]
4933 #[should_panic]
4934 fn test_put_exceeding_capacity_panics() {
4935 let mut b = builder(1);
4936 let cap = b.remaining_mut();
4937 let src = Bytes::from(vec![0xAB; cap + 1]);
4938 b.put(src);
4939 }
4940
4941 #[test]
4943 #[should_panic]
4944 fn test_put_slice_exceeding_capacity_panics() {
4945 let mut b = builder(1);
4946 let cap = b.remaining_mut();
4947 b.put_slice(&vec![0xFE; cap + 1]);
4948 }
4949
4950 #[test]
4953 fn test_multi_field_struct_equivalence() {
4954 let header: u16 = 0xCAFE;
4955 let payload = Bytes::from(vec![0xDD; 1024]);
4956 let trailer: u32 = 0xDEADBEEF;
4957
4958 let size = header.encode_size() + payload.encode_size() + trailer.encode_size();
4960 let mut flat = BytesMut::with_capacity(size);
4961 header.write(&mut flat);
4962 payload.write(&mut flat);
4963 trailer.write(&mut flat);
4964
4965 let mut b = builder(64);
4967 header.write(&mut b);
4968 payload.write_bufs(&mut b);
4969 trailer.write(&mut b);
4970 let mut bufs = b.finish();
4971
4972 let mut out = vec![0u8; bufs.remaining()];
4973 bufs.copy_to_slice(&mut out);
4974 assert_eq!(out, flat.as_ref());
4975 }
4976
4977 #[test]
4979 fn test_encode_with_pool_matches_encode() {
4980 let pool = test_pool();
4981 let data = Bytes::from(vec![0xEE; 500]);
4982 let mut pooled = data.encode_with_pool(&pool);
4983 let baseline = data.encode();
4984 let mut out = vec![0u8; pooled.remaining()];
4985 pooled.copy_to_slice(&mut out);
4986 assert_eq!(out, baseline.as_ref());
4987 }
4988
4989 #[test]
4991 fn test_chunk_mut_and_advance_mut() {
4992 let mut b = builder(64);
4993 let initial = b.remaining_mut();
4994 assert!(initial >= 64);
4995 let chunk = b.chunk_mut();
4996 chunk[0..1].copy_from_slice(&[0xAB]);
4997 unsafe { b.advance_mut(1) };
4999 assert_eq!(b.remaining_mut(), initial - 1);
5000 let mut r = b.finish();
5001 assert_eq!(r.remaining(), 1);
5002 assert_eq!(r.get_u8(), 0xAB);
5003 }
5004
5005 #[test]
5007 #[should_panic]
5008 fn test_write_past_full_panics() {
5009 let mut b = builder(1);
5010 let cap = b.remaining_mut();
5011 b.put_slice(&vec![0xFF; cap]); assert_eq!(b.remaining_mut(), 0);
5013 b.put_u8(0x42); }
5015
5016 #[test]
5019 fn test_push_at_start_with_trailer() {
5020 let mut b = builder(64);
5021 let payload = Bytes::from(vec![0xCC; 32]);
5022 b.push(payload.clone());
5023 b.put_u8(0x01);
5024 let mut r = b.finish();
5025 assert_eq!(r.remaining(), 33);
5026 assert_eq!(r.copy_to_bytes(32), payload);
5027 assert_eq!(r.get_u8(), 0x01);
5028 }
5029 }
5030}