1#[cfg(feature = "allocator_api")]
2use std::alloc::Allocator;
3use std::{error::Error, fmt::Display, mem::MaybeUninit, ops::RangeBounds, rc::Rc, sync::Arc};
4
5use crate::*;
6
7pub trait IoBuf: 'static {
13 fn as_init(&self) -> &[u8];
15}
16
17const _: [&dyn IoBuf; 0] = [];
19
20pub trait IoBufExt: IoBuf {
22 fn buf_len(&self) -> usize {
24 self.as_init().len()
25 }
26
27 fn buf_ptr(&self) -> *const u8 {
29 self.as_init().as_ptr()
30 }
31
32 fn is_empty(&self) -> bool {
34 self.buf_len() == 0
35 }
36
37 fn slice(self, range: impl std::ops::RangeBounds<usize>) -> Slice<Self>
56 where
57 Self: Sized,
58 {
59 use std::ops::Bound;
60
61 let begin = match range.start_bound() {
62 Bound::Included(&n) => n,
63 Bound::Excluded(&n) => n + 1,
64 Bound::Unbounded => 0,
65 };
66
67 let end = match range.end_bound() {
68 Bound::Included(&n) => Some(n.checked_add(1).expect("out of range")),
69 Bound::Excluded(&n) => Some(n),
70 Bound::Unbounded => None,
71 };
72
73 assert!(begin <= self.buf_len());
74
75 if let Some(end) = end {
76 assert!(begin <= end);
77 }
78
79 unsafe { Slice::new(self, begin, end) }
81 }
82
83 fn into_reader(self) -> Reader<Self>
86 where
87 Self: Sized,
88 {
89 Reader::new(self)
90 }
91
92 fn as_reader(&self) -> ReaderRef<'_, Self> {
95 ReaderRef::new(self)
96 }
97}
98
99impl<B: IoBuf + ?Sized> IoBufExt for B {}
100
101impl<B: IoBuf + ?Sized> IoBuf for &'static B {
102 fn as_init(&self) -> &[u8] {
103 (**self).as_init()
104 }
105}
106
107impl<B: IoBuf + ?Sized> IoBuf for &'static mut B {
108 fn as_init(&self) -> &[u8] {
109 (**self).as_init()
110 }
111}
112
113impl<B: IoBuf + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBuf
114 for t_alloc!(Box, B, A)
115{
116 fn as_init(&self) -> &[u8] {
117 (**self).as_init()
118 }
119}
120
121impl<B: IoBuf + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBuf
122 for t_alloc!(Rc, B, A)
123{
124 fn as_init(&self) -> &[u8] {
125 (**self).as_init()
126 }
127}
128
129impl IoBuf for [u8] {
130 fn as_init(&self) -> &[u8] {
131 self
132 }
133}
134
135impl<const N: usize> IoBuf for [u8; N] {
136 fn as_init(&self) -> &[u8] {
137 self
138 }
139}
140
141impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBuf for t_alloc!(Vec, u8, A) {
142 fn as_init(&self) -> &[u8] {
143 self
144 }
145}
146
147impl IoBuf for str {
148 fn as_init(&self) -> &[u8] {
149 self.as_bytes()
150 }
151}
152
153impl IoBuf for String {
154 fn as_init(&self) -> &[u8] {
155 self.as_bytes()
156 }
157}
158
159impl<B: IoBuf + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBuf
160 for t_alloc!(Arc, B, A)
161{
162 fn as_init(&self) -> &[u8] {
163 (**self).as_init()
164 }
165}
166
167#[cfg(feature = "bytes")]
168impl IoBuf for bytes::Bytes {
169 fn as_init(&self) -> &[u8] {
170 self
171 }
172}
173
174#[cfg(feature = "bytes")]
175impl IoBuf for bytes::BytesMut {
176 fn as_init(&self) -> &[u8] {
177 self
178 }
179}
180
181#[cfg(feature = "read_buf")]
182impl IoBuf for std::io::BorrowedBuf<'static, u8> {
183 fn as_init(&self) -> &[u8] {
184 self.filled()
185 }
186}
187
188#[cfg(feature = "arrayvec")]
189impl<const N: usize> IoBuf for arrayvec::ArrayVec<u8, N> {
190 fn as_init(&self) -> &[u8] {
191 self
192 }
193}
194
195#[cfg(feature = "smallvec")]
196impl<const N: usize> IoBuf for smallvec::SmallVec<[u8; N]>
197where
198 [u8; N]: smallvec::Array<Item = u8>,
199{
200 fn as_init(&self) -> &[u8] {
201 self
202 }
203}
204
205#[cfg(feature = "memmap2")]
206impl IoBuf for memmap2::Mmap {
207 fn as_init(&self) -> &[u8] {
208 self
209 }
210}
211
212#[cfg(feature = "memmap2")]
213impl IoBuf for memmap2::MmapMut {
214 fn as_init(&self) -> &[u8] {
215 self
216 }
217}
218
219#[must_use]
221#[derive(Debug)]
222pub enum ReserveError {
223 NotSupported,
225
226 ReserveFailed(Box<dyn Error + Send + Sync>),
230}
231
232impl ReserveError {
233 pub fn is_not_supported(&self) -> bool {
237 matches!(self, ReserveError::NotSupported)
238 }
239}
240
241impl Display for ReserveError {
242 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243 match self {
244 ReserveError::NotSupported => write!(f, "reservation is not supported"),
245 ReserveError::ReserveFailed(src) => write!(f, "reservation failed: {src}"),
246 }
247 }
248}
249
250impl Error for ReserveError {
251 fn source(&self) -> Option<&(dyn Error + 'static)> {
252 match self {
253 ReserveError::ReserveFailed(src) => Some(src.as_ref()),
254 _ => None,
255 }
256 }
257}
258
259impl From<ReserveError> for std::io::Error {
260 fn from(value: ReserveError) -> Self {
261 match value {
262 ReserveError::NotSupported => {
263 std::io::Error::new(std::io::ErrorKind::Unsupported, "reservation not supported")
264 }
265 ReserveError::ReserveFailed(src) => {
266 std::io::Error::new(std::io::ErrorKind::OutOfMemory, src)
267 }
268 }
269 }
270}
271
272#[must_use]
274#[derive(Debug)]
275pub enum ReserveExactError {
276 NotSupported,
278
279 ReserveFailed(Box<dyn Error + Send + Sync>),
283
284 ExactSizeMismatch {
286 expected: usize,
288
289 reserved: usize,
291 },
292}
293
294impl ReserveExactError {
295 pub fn is_not_supported(&self) -> bool {
299 matches!(self, ReserveExactError::NotSupported)
300 }
301}
302
303impl Display for ReserveExactError {
304 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305 match self {
306 ReserveExactError::NotSupported => write!(f, "reservation is not supported"),
307 ReserveExactError::ReserveFailed(src) => write!(f, "reservation failed: {src}"),
308 ReserveExactError::ExactSizeMismatch { reserved, expected } => {
309 write!(
310 f,
311 "reserved size mismatch: expected {}, reserved {}",
312 expected, reserved
313 )
314 }
315 }
316 }
317}
318
319impl From<ReserveError> for ReserveExactError {
320 fn from(err: ReserveError) -> Self {
321 match err {
322 ReserveError::NotSupported => ReserveExactError::NotSupported,
323 ReserveError::ReserveFailed(src) => ReserveExactError::ReserveFailed(src),
324 }
325 }
326}
327
328impl Error for ReserveExactError {
329 fn source(&self) -> Option<&(dyn Error + 'static)> {
330 match self {
331 ReserveExactError::ReserveFailed(src) => Some(src.as_ref()),
332 _ => None,
333 }
334 }
335}
336
337impl From<ReserveExactError> for std::io::Error {
338 fn from(value: ReserveExactError) -> Self {
339 match value {
340 ReserveExactError::NotSupported => {
341 std::io::Error::new(std::io::ErrorKind::Unsupported, "reservation not supported")
342 }
343 ReserveExactError::ReserveFailed(src) => {
344 std::io::Error::new(std::io::ErrorKind::OutOfMemory, src)
345 }
346 ReserveExactError::ExactSizeMismatch { expected, reserved } => std::io::Error::other(
347 format!("reserved size mismatch: expected {expected}, reserved {reserved}",),
348 ),
349 }
350 }
351}
352
353#[cfg(feature = "smallvec")]
354mod smallvec_err {
355 use std::{error::Error, fmt::Display};
356
357 use smallvec::CollectionAllocErr;
358
359 #[derive(Debug)]
360 pub(super) struct SmallVecErr(pub CollectionAllocErr);
361
362 impl Display for SmallVecErr {
363 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
364 write!(f, "SmallVec allocation error: {}", self.0)
365 }
366 }
367
368 impl Error for SmallVecErr {}
369}
370
371pub trait IoBufMut: IoBuf + SetLen {
378 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>];
381
382 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
396 let init = (*self).buf_len();
397 if len <= self.buf_capacity() - init {
398 return Ok(());
399 }
400 Err(ReserveError::NotSupported)
401 }
402
403 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
413 self.reserve(len)?;
414 Ok(())
415 }
416}
417
418const _: [&dyn IoBufMut; 0] = [];
420
421pub trait IoBufMutExt: IoBufMut {
423 fn ensure_init(&mut self) -> &mut [u8] {
429 let len = (*self).buf_len();
430 let slice = self.as_uninit();
431 slice[len..].fill(MaybeUninit::new(0));
432 unsafe { slice.assume_init_mut() }
433 }
434
435 fn buf_capacity(&mut self) -> usize {
438 self.as_uninit().len()
439 }
440
441 fn buf_mut_ptr(&mut self) -> *mut MaybeUninit<u8> {
443 self.as_uninit().as_mut_ptr()
444 }
445
446 fn as_mut_slice(&mut self) -> &mut [u8] {
449 let len = (*self).buf_len();
450 let ptr = (*self).buf_mut_ptr();
451 unsafe { std::slice::from_raw_parts_mut(ptr as *mut u8, len) }
456 }
457
458 fn extend_from_slice(&mut self, src: &[u8]) -> Result<(), ReserveError> {
467 let len = src.len();
468 let init = (*self).buf_len();
469 self.reserve(len)?;
470 let ptr = self.buf_mut_ptr().wrapping_add(init);
471
472 unsafe {
473 std::ptr::copy_nonoverlapping(src.as_ptr() as _, ptr, len);
479
480 self.advance_to(init + len);
482 }
483
484 Ok(())
485 }
486
487 fn copy_within<R>(&mut self, src: R, dest: usize)
498 where
499 R: RangeBounds<usize>,
500 {
501 self.as_uninit().copy_within(src, dest);
502 }
503
504 fn uninit(self) -> Uninit<Self>
525 where
526 Self: Sized,
527 {
528 Uninit::new(self)
529 }
530
531 fn into_writer(self) -> Writer<Self>
534 where
535 Self: Sized,
536 {
537 Writer::new(self)
538 }
539
540 fn as_writer(&mut self) -> WriterRef<'_, Self> {
543 WriterRef::new(self)
544 }
545
546 fn is_filled(&mut self) -> bool {
548 let len = (*self).as_init().len();
549 let cap = (*self).buf_capacity();
550 len == cap
551 }
552}
553
554impl<B: IoBufMut + ?Sized> IoBufMutExt for B {}
555
556impl<B: IoBufMut + ?Sized> IoBufMut for &'static mut B {
557 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
558 (**self).as_uninit()
559 }
560
561 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
562 (**self).reserve(len)
563 }
564
565 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
566 (**self).reserve_exact(len)
567 }
568}
569
570impl<B: IoBufMut + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBufMut
571 for t_alloc!(Box, B, A)
572{
573 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
574 (**self).as_uninit()
575 }
576
577 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
578 (**self).reserve(len)
579 }
580
581 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
582 (**self).reserve_exact(len)
583 }
584}
585
586impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBufMut for t_alloc!(Vec, u8, A) {
587 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
588 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
589 let cap = self.capacity();
590 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
592 }
593
594 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
595 if let Err(e) = Vec::try_reserve(self, len) {
596 return Err(ReserveError::ReserveFailed(Box::new(e)));
597 }
598
599 Ok(())
600 }
601
602 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
603 if self.capacity() - self.len() >= len {
604 return Ok(());
605 }
606
607 if let Err(e) = Vec::try_reserve_exact(self, len) {
608 return Err(ReserveExactError::ReserveFailed(Box::new(e)));
609 }
610
611 if self.capacity() - self.len() != len {
612 return Err(ReserveExactError::ExactSizeMismatch {
613 reserved: self.capacity() - self.len(),
614 expected: len,
615 });
616 }
617 Ok(())
618 }
619}
620
621impl IoBufMut for [u8] {
622 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
623 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
624 let len = self.len();
625 unsafe { std::slice::from_raw_parts_mut(ptr, len) }
627 }
628}
629
630impl<const N: usize> IoBufMut for [u8; N] {
631 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
632 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
633 unsafe { std::slice::from_raw_parts_mut(ptr, N) }
635 }
636}
637
638#[cfg(feature = "bytes")]
639impl IoBufMut for bytes::BytesMut {
640 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
641 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
642 let cap = self.capacity();
643 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
645 }
646
647 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
648 bytes::BytesMut::reserve(self, len);
649 Ok(())
650 }
651
652 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
653 if self.capacity() - self.len() >= len {
654 return Ok(());
655 }
656
657 bytes::BytesMut::reserve(self, len);
658
659 if self.capacity() - self.len() != len {
660 Err(ReserveExactError::ExactSizeMismatch {
661 reserved: self.capacity() - self.len(),
662 expected: len,
663 })
664 } else {
665 Ok(())
666 }
667 }
668}
669
670#[cfg(feature = "read_buf")]
671impl IoBufMut for std::io::BorrowedBuf<'static, u8> {
672 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
673 let total_cap = self.capacity();
674
675 unsafe {
678 let filled_ptr = self.filled().as_ptr() as *mut MaybeUninit<u8>;
679 std::slice::from_raw_parts_mut(filled_ptr, total_cap)
680 }
681 }
682}
683
684#[cfg(feature = "arrayvec")]
685impl<const N: usize> IoBufMut for arrayvec::ArrayVec<u8, N> {
686 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
687 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
688 unsafe { std::slice::from_raw_parts_mut(ptr, N) }
690 }
691}
692
693#[cfg(feature = "smallvec")]
694impl<const N: usize> IoBufMut for smallvec::SmallVec<[u8; N]>
695where
696 [u8; N]: smallvec::Array<Item = u8>,
697{
698 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
699 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
700 let cap = self.capacity();
701 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
703 }
704
705 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
706 if let Err(e) = smallvec::SmallVec::try_reserve(self, len) {
707 return Err(ReserveError::ReserveFailed(Box::new(
708 smallvec_err::SmallVecErr(e),
709 )));
710 }
711 Ok(())
712 }
713
714 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
715 if self.capacity() - self.len() >= len {
716 return Ok(());
717 }
718
719 if let Err(e) = smallvec::SmallVec::try_reserve_exact(self, len) {
720 return Err(ReserveExactError::ReserveFailed(Box::new(
721 smallvec_err::SmallVecErr(e),
722 )));
723 }
724
725 if self.capacity() - self.len() != len {
726 return Err(ReserveExactError::ExactSizeMismatch {
727 reserved: self.capacity() - self.len(),
728 expected: len,
729 });
730 }
731 Ok(())
732 }
733}
734
735#[cfg(feature = "memmap2")]
736impl IoBufMut for memmap2::MmapMut {
737 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
738 unsafe { std::mem::transmute(self.as_mut_slice()) }
740 }
741}
742
743pub trait SetLen {
745 unsafe fn set_len(&mut self, len: usize);
752}
753
754const _: [&dyn SetLen; 0] = [];
756
757pub trait SetLenExt: SetLen {
759 unsafe fn advance(&mut self, len: usize)
766 where
767 Self: IoBuf,
768 {
769 let current_len = (*self).buf_len();
770 let new_len = current_len.checked_add(len).expect("length overflow");
771 unsafe { self.set_len(new_len) };
772 }
773
774 unsafe fn advance_to(&mut self, len: usize)
782 where
783 Self: IoBuf,
784 {
785 let current_len = (*self).buf_len();
786 if len > current_len {
787 unsafe { self.set_len(len) };
788 }
789 }
790
791 unsafe fn advance_vec_to(&mut self, len: usize)
799 where
800 Self: IoVectoredBuf,
801 {
802 let current_len = (*self).total_len();
803 if len > current_len {
804 unsafe { self.set_len(len) };
805 }
806 }
807
808 fn clear(&mut self)
811 where
812 Self: IoBuf,
813 {
814 unsafe { self.set_len(0) };
816 }
817}
818
819impl<B: SetLen + ?Sized> SetLenExt for B {}
820
821impl<B: SetLen + ?Sized> SetLen for &'static mut B {
822 unsafe fn set_len(&mut self, len: usize) {
823 unsafe { (**self).set_len(len) }
824 }
825}
826
827impl<B: SetLen + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen
828 for t_alloc!(Box, B, A)
829{
830 unsafe fn set_len(&mut self, len: usize) {
831 unsafe { (**self).set_len(len) }
832 }
833}
834
835impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen for t_alloc!(Vec, u8, A) {
836 unsafe fn set_len(&mut self, len: usize) {
837 unsafe { self.set_len(len) };
838 }
839}
840
841impl SetLen for [u8] {
842 unsafe fn set_len(&mut self, len: usize) {
843 debug_assert!(len <= self.len());
844 }
845}
846
847impl<const N: usize> SetLen for [u8; N] {
848 unsafe fn set_len(&mut self, len: usize) {
849 debug_assert!(len <= N);
850 }
851}
852
853#[cfg(feature = "bytes")]
854impl SetLen for bytes::BytesMut {
855 unsafe fn set_len(&mut self, len: usize) {
856 unsafe { self.set_len(len) };
857 }
858}
859
860#[cfg(feature = "read_buf")]
861impl SetLen for std::io::BorrowedBuf<'static, u8> {
862 unsafe fn set_len(&mut self, len: usize) {
863 debug_assert!(self.capacity() >= len);
864
865 #[allow(unused_unsafe)]
867 unsafe {
868 self.clear().unfilled().advance(len)
869 };
870 }
871}
872
873#[cfg(feature = "arrayvec")]
874impl<const N: usize> SetLen for arrayvec::ArrayVec<u8, N> {
875 unsafe fn set_len(&mut self, len: usize) {
876 if (**self).buf_len() < len {
877 unsafe { self.set_len(len) };
878 }
879 }
880}
881
882#[cfg(feature = "smallvec")]
883impl<const N: usize> SetLen for smallvec::SmallVec<[u8; N]>
884where
885 [u8; N]: smallvec::Array<Item = u8>,
886{
887 unsafe fn set_len(&mut self, len: usize) {
888 if (**self).buf_len() < len {
889 unsafe { self.set_len(len) };
890 }
891 }
892}
893
894#[cfg(feature = "memmap2")]
895impl SetLen for memmap2::MmapMut {
896 unsafe fn set_len(&mut self, len: usize) {
897 debug_assert!(len <= self.len())
898 }
899}
900
901impl<T: IoBufMut> SetLen for [T] {
902 unsafe fn set_len(&mut self, len: usize) {
903 unsafe { default_set_len(self.iter_mut(), len) }
904 }
905}
906
907impl<T: IoBufMut, const N: usize> SetLen for [T; N] {
908 unsafe fn set_len(&mut self, len: usize) {
909 unsafe { default_set_len(self.iter_mut(), len) }
910 }
911}
912
913impl<T: IoBufMut, #[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen
914 for t_alloc!(Vec, T, A)
915{
916 unsafe fn set_len(&mut self, len: usize) {
917 unsafe { default_set_len(self.iter_mut(), len) }
918 }
919}
920
921#[cfg(feature = "arrayvec")]
922impl<T: IoBufMut, const N: usize> SetLen for arrayvec::ArrayVec<T, N> {
923 unsafe fn set_len(&mut self, len: usize) {
924 unsafe { default_set_len(self.iter_mut(), len) }
925 }
926}
927
928#[cfg(feature = "smallvec")]
929impl<T: IoBufMut, const N: usize> SetLen for smallvec::SmallVec<[T; N]>
930where
931 [T; N]: smallvec::Array<Item = T>,
932{
933 unsafe fn set_len(&mut self, len: usize) {
934 unsafe { default_set_len(self.iter_mut(), len) }
935 }
936}
937
938unsafe fn default_set_len<'a, B: IoBufMut>(
944 iter: impl IntoIterator<Item = &'a mut B>,
945 mut len: usize,
946) {
947 let mut iter = iter.into_iter();
948 while len > 0 {
949 let Some(curr) = iter.next() else { return };
950 let sub = (*curr).buf_capacity().min(len);
951 unsafe { curr.set_len(sub) };
952 len -= sub;
953 }
954}
955
956#[cfg(test)]
957mod test {
958 use crate::{IoBufMut, IoBufMutExt};
959
960 #[test]
961 fn test_vec_reserve() {
962 let mut buf = Vec::new();
963 IoBufMut::reserve(&mut buf, 10).unwrap();
964 assert!(buf.capacity() >= 10);
965
966 let mut buf = Vec::new();
967 IoBufMut::reserve_exact(&mut buf, 10).unwrap();
968 assert!(buf.capacity() == 10);
969
970 let mut buf = Box::new(Vec::new());
971 IoBufMut::reserve_exact(&mut buf, 10).unwrap();
972 assert!(buf.capacity() == 10);
973 }
974
975 #[test]
976 #[cfg(feature = "bytes")]
977 fn test_bytes_reserve() {
978 let mut buf = bytes::BytesMut::new();
979 IoBufMut::reserve(&mut buf, 10).unwrap();
980 assert!(buf.capacity() >= 10);
981 }
982
983 #[test]
984 #[cfg(feature = "smallvec")]
985 fn test_smallvec_reserve() {
986 let mut buf = smallvec::SmallVec::<[u8; 8]>::new();
987 IoBufMut::reserve(&mut buf, 10).unwrap();
988 assert!(buf.capacity() >= 10);
989 }
990
991 #[test]
992 #[cfg(feature = "memmap2")]
993 fn tests_memmap2() {
994 use std::{
995 fs::{OpenOptions, remove_file},
996 io::{Seek, SeekFrom, Write},
997 };
998
999 use memmap2::MmapOptions;
1000
1001 use super::*;
1002
1003 let path = std::env::temp_dir().join("compio_buf_mmap_mut_test");
1004
1005 let mut file = OpenOptions::new()
1006 .read(true)
1007 .write(true)
1008 .create(true)
1009 .truncate(true)
1010 .open(&path)
1011 .unwrap();
1012 let data = b"hello memmap2";
1013 file.write_all(data).unwrap();
1014 file.flush().unwrap();
1015 file.seek(SeekFrom::Start(0)).unwrap();
1016 let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
1017
1018 let uninit_slice = mmap.as_init();
1019 assert_eq!(uninit_slice, data);
1020
1021 remove_file(path).unwrap();
1022 }
1023
1024 #[test]
1025 fn test_other_reserve() {
1026 let mut buf = [1, 1, 4, 5, 1, 4];
1027 let res = IoBufMut::reserve(&mut buf, 10);
1028 assert!(res.is_err_and(|x| x.is_not_supported()));
1029 assert!(buf.buf_capacity() == 6);
1030 }
1031
1032 #[test]
1033 fn test_extend() {
1034 let mut buf = Vec::from(b"hello");
1035 IoBufMutExt::extend_from_slice(&mut buf, b" world").unwrap();
1036 assert_eq!(buf.as_slice(), b"hello world");
1037
1038 let mut buf = [];
1039 let res = IoBufMutExt::extend_from_slice(&mut buf, b" ");
1040 assert!(res.is_err_and(|x| x.is_not_supported()));
1041 }
1042}