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 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>];
387
388 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
402 let init = (*self).buf_len();
403 if len <= self.buf_capacity() - init {
404 return Ok(());
405 }
406 Err(ReserveError::NotSupported)
407 }
408
409 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
419 self.reserve(len)?;
420 Ok(())
421 }
422}
423
424const _: [&dyn IoBufMut; 0] = [];
426
427pub trait IoBufMutExt: IoBufMut {
429 fn ensure_init(&mut self) -> &mut [u8] {
435 let len = (*self).buf_len();
436 let slice = unsafe { self.as_uninit() };
439 slice[len..].fill(MaybeUninit::new(0));
440 unsafe { slice.assume_init_mut() }
443 }
444
445 fn buf_capacity(&mut self) -> usize {
448 unsafe { self.as_uninit() }.len()
449 }
450
451 fn buf_mut_ptr(&mut self) -> *mut MaybeUninit<u8> {
453 unsafe { self.as_uninit() }.as_mut_ptr()
454 }
455
456 fn as_mut_slice(&mut self) -> &mut [u8] {
459 let len = (*self).buf_len();
460 let ptr = (*self).buf_mut_ptr();
461 unsafe { std::slice::from_raw_parts_mut(ptr as *mut u8, len) }
466 }
467
468 fn extend_from_slice(&mut self, src: &[u8]) -> Result<(), ReserveError> {
476 let len = src.len();
477 let init = (*self).buf_len();
478 self.reserve(len)?;
479 (unsafe { self.as_uninit() })[init..init + len].write_copy_of_slice(src);
483
484 unsafe { self.advance_to(init + len) };
486
487 Ok(())
488 }
489
490 unsafe fn copy_within<R>(&mut self, src: R, dest: usize)
507 where
508 R: RangeBounds<usize>,
509 {
510 unsafe { self.as_uninit() }.copy_within(src, dest);
511 }
512
513 fn uninit(self) -> Uninit<Self>
534 where
535 Self: Sized,
536 {
537 Uninit::new(self)
538 }
539
540 fn into_writer(self) -> Writer<Self>
543 where
544 Self: Sized,
545 {
546 Writer::new(self)
547 }
548
549 fn as_writer(&mut self) -> WriterRef<'_, Self> {
552 WriterRef::new(self)
553 }
554
555 fn is_filled(&mut self) -> bool {
557 let len = (*self).as_init().len();
558 let cap = (*self).buf_capacity();
559 len == cap
560 }
561}
562
563impl<B: IoBufMut + ?Sized> IoBufMutExt for B {}
564
565impl<B: IoBufMut + ?Sized> IoBufMut for &'static mut B {
566 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
567 unsafe { (**self).as_uninit() }
568 }
569
570 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
571 (**self).reserve(len)
572 }
573
574 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
575 (**self).reserve_exact(len)
576 }
577}
578
579impl<B: IoBufMut + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBufMut
580 for t_alloc!(Box, B, A)
581{
582 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
583 unsafe { (**self).as_uninit() }
584 }
585
586 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
587 (**self).reserve(len)
588 }
589
590 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
591 (**self).reserve_exact(len)
592 }
593}
594
595impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBufMut for t_alloc!(Vec, u8, A) {
596 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
597 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
598 let cap = self.capacity();
599 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
601 }
602
603 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
604 if let Err(e) = Vec::try_reserve(self, len) {
605 return Err(ReserveError::ReserveFailed(Box::new(e)));
606 }
607
608 Ok(())
609 }
610
611 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
612 if self.capacity() - self.len() >= len {
613 return Ok(());
614 }
615
616 if let Err(e) = Vec::try_reserve_exact(self, len) {
617 return Err(ReserveExactError::ReserveFailed(Box::new(e)));
618 }
619
620 if self.capacity() - self.len() != len {
621 return Err(ReserveExactError::ExactSizeMismatch {
622 reserved: self.capacity() - self.len(),
623 expected: len,
624 });
625 }
626 Ok(())
627 }
628}
629
630impl IoBufMut for [u8] {
631 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
632 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
633 let len = self.len();
634 unsafe { std::slice::from_raw_parts_mut(ptr, len) }
637 }
638}
639
640impl<const N: usize> IoBufMut for [u8; N] {
641 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
642 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
643 unsafe { std::slice::from_raw_parts_mut(ptr, N) }
646 }
647}
648
649#[cfg(feature = "bytes")]
650impl IoBufMut for bytes::BytesMut {
651 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
652 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
653 let cap = self.capacity();
654 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
657 }
658
659 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
660 bytes::BytesMut::reserve(self, len);
661 Ok(())
662 }
663
664 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
665 if self.capacity() - self.len() >= len {
666 return Ok(());
667 }
668
669 bytes::BytesMut::reserve(self, len);
670
671 if self.capacity() - self.len() != len {
672 Err(ReserveExactError::ExactSizeMismatch {
673 reserved: self.capacity() - self.len(),
674 expected: len,
675 })
676 } else {
677 Ok(())
678 }
679 }
680}
681
682#[cfg(feature = "read_buf")]
683impl IoBufMut for std::io::BorrowedBuf<'static, u8> {
684 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
685 let total_cap = self.capacity();
686
687 unsafe {
691 let filled_ptr = self.filled().as_ptr() as *mut MaybeUninit<u8>;
692 std::slice::from_raw_parts_mut(filled_ptr, total_cap)
693 }
694 }
695}
696
697#[cfg(feature = "arrayvec")]
698impl<const N: usize> IoBufMut for arrayvec::ArrayVec<u8, N> {
699 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
700 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
701 unsafe { std::slice::from_raw_parts_mut(ptr, N) }
703 }
704}
705
706#[cfg(feature = "smallvec")]
707impl<const N: usize> IoBufMut for smallvec::SmallVec<[u8; N]>
708where
709 [u8; N]: smallvec::Array<Item = u8>,
710{
711 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
712 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
713 let cap = self.capacity();
714 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
717 }
718
719 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
720 if let Err(e) = smallvec::SmallVec::try_reserve(self, len) {
721 return Err(ReserveError::ReserveFailed(Box::new(
722 smallvec_err::SmallVecErr(e),
723 )));
724 }
725 Ok(())
726 }
727
728 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
729 if self.capacity() - self.len() >= len {
730 return Ok(());
731 }
732
733 if let Err(e) = smallvec::SmallVec::try_reserve_exact(self, len) {
734 return Err(ReserveExactError::ReserveFailed(Box::new(
735 smallvec_err::SmallVecErr(e),
736 )));
737 }
738
739 if self.capacity() - self.len() != len {
740 return Err(ReserveExactError::ExactSizeMismatch {
741 reserved: self.capacity() - self.len(),
742 expected: len,
743 });
744 }
745 Ok(())
746 }
747}
748
749#[cfg(feature = "memmap2")]
750impl IoBufMut for memmap2::MmapMut {
751 unsafe fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
752 unsafe { std::mem::transmute(self.as_mut()) }
754 }
755}
756
757pub trait SetLen {
759 unsafe fn set_len(&mut self, len: usize);
767}
768
769const _: [&dyn SetLen; 0] = [];
771
772pub trait SetLenExt: SetLen {
774 unsafe fn advance(&mut self, len: usize)
781 where
782 Self: IoBuf,
783 {
784 let current_len = (*self).buf_len();
785 let new_len = current_len.checked_add(len).expect("length overflow");
786 unsafe { self.set_len(new_len) };
787 }
788
789 unsafe fn advance_to(&mut self, len: usize)
798 where
799 Self: IoBuf,
800 {
801 let current_len = (*self).buf_len();
802 if len > current_len {
803 unsafe { self.set_len(len) };
804 }
805 }
806
807 unsafe fn advance_vec_to(&mut self, len: usize)
815 where
816 Self: IoVectoredBuf,
817 {
818 let current_len = (*self).total_len();
819 if len > current_len {
820 unsafe { self.set_len(len) };
821 }
822 }
823
824 fn clear(&mut self)
827 where
828 Self: IoBuf,
829 {
830 unsafe { self.set_len(0) };
832 }
833}
834
835impl<B: SetLen + ?Sized> SetLenExt for B {}
836
837impl<B: SetLen + ?Sized> SetLen for &'static mut B {
838 unsafe fn set_len(&mut self, len: usize) {
839 unsafe { (**self).set_len(len) }
840 }
841}
842
843impl<B: SetLen + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen
844 for t_alloc!(Box, B, A)
845{
846 unsafe fn set_len(&mut self, len: usize) {
847 unsafe { (**self).set_len(len) }
848 }
849}
850
851impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen for t_alloc!(Vec, u8, A) {
852 unsafe fn set_len(&mut self, len: usize) {
853 unsafe { self.set_len(len) };
854 }
855}
856
857impl SetLen for [u8] {
858 unsafe fn set_len(&mut self, len: usize) {
859 debug_assert!(len <= self.len());
860 }
861}
862
863impl<const N: usize> SetLen for [u8; N] {
864 unsafe fn set_len(&mut self, len: usize) {
865 debug_assert!(len <= N);
866 }
867}
868
869#[cfg(feature = "bytes")]
870impl SetLen for bytes::BytesMut {
871 unsafe fn set_len(&mut self, len: usize) {
872 unsafe { self.set_len(len) };
873 }
874}
875
876#[cfg(feature = "read_buf")]
877impl SetLen for std::io::BorrowedBuf<'static, u8> {
878 unsafe fn set_len(&mut self, len: usize) {
879 debug_assert!(self.capacity() >= len);
880
881 #[allow(unused_unsafe)]
884 unsafe {
885 self.clear().unfilled().advance(len)
886 };
887 }
888}
889
890#[cfg(feature = "arrayvec")]
891impl<const N: usize> SetLen for arrayvec::ArrayVec<u8, N> {
892 unsafe fn set_len(&mut self, len: usize) {
893 if (**self).buf_len() < len {
894 unsafe { self.set_len(len) };
895 }
896 }
897}
898
899#[cfg(feature = "smallvec")]
900impl<const N: usize> SetLen for smallvec::SmallVec<[u8; N]>
901where
902 [u8; N]: smallvec::Array<Item = u8>,
903{
904 unsafe fn set_len(&mut self, len: usize) {
905 if (**self).buf_len() < len {
906 unsafe { self.set_len(len) };
907 }
908 }
909}
910
911#[cfg(feature = "memmap2")]
912impl SetLen for memmap2::MmapMut {
913 unsafe fn set_len(&mut self, len: usize) {
914 debug_assert!(len <= self.len())
915 }
916}
917
918impl<T: IoBufMut> SetLen for [T] {
919 unsafe fn set_len(&mut self, len: usize) {
920 unsafe { default_set_len(self.iter_mut(), len) }
921 }
922}
923
924impl<T: IoBufMut, const N: usize> SetLen for [T; N] {
925 unsafe fn set_len(&mut self, len: usize) {
926 unsafe { default_set_len(self.iter_mut(), len) }
927 }
928}
929
930impl<T: IoBufMut, #[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen
931 for t_alloc!(Vec, T, A)
932{
933 unsafe fn set_len(&mut self, len: usize) {
934 unsafe { default_set_len(self.iter_mut(), len) }
935 }
936}
937
938#[cfg(feature = "arrayvec")]
939impl<T: IoBufMut, const N: usize> SetLen for arrayvec::ArrayVec<T, N> {
940 unsafe fn set_len(&mut self, len: usize) {
941 unsafe { default_set_len(self.iter_mut(), len) }
942 }
943}
944
945#[cfg(feature = "smallvec")]
946impl<T: IoBufMut, const N: usize> SetLen for smallvec::SmallVec<[T; N]>
947where
948 [T; N]: smallvec::Array<Item = T>,
949{
950 unsafe fn set_len(&mut self, len: usize) {
951 unsafe { default_set_len(self.iter_mut(), len) }
952 }
953}
954
955unsafe fn default_set_len<'a, B: IoBufMut>(
961 iter: impl IntoIterator<Item = &'a mut B>,
962 mut len: usize,
963) {
964 let mut iter = iter.into_iter();
965 while len > 0 {
966 let Some(curr) = iter.next() else { return };
967 let sub = (*curr).buf_capacity().min(len);
968 unsafe { curr.set_len(sub) };
969 len -= sub;
970 }
971}
972
973#[cfg(test)]
974mod test {
975 use crate::{IoBufMut, IoBufMutExt};
976
977 #[test]
978 fn test_vec_reserve() {
979 let mut buf = Vec::new();
980 IoBufMut::reserve(&mut buf, 10).unwrap();
981 assert!(buf.capacity() >= 10);
982
983 let mut buf = Vec::new();
984 IoBufMut::reserve_exact(&mut buf, 10).unwrap();
985 assert!(buf.capacity() == 10);
986
987 let mut buf = Box::new(Vec::new());
988 IoBufMut::reserve_exact(&mut buf, 10).unwrap();
989 assert!(buf.capacity() == 10);
990 }
991
992 #[test]
993 #[cfg(feature = "bytes")]
994 fn test_bytes_reserve() {
995 let mut buf = bytes::BytesMut::new();
996 IoBufMut::reserve(&mut buf, 10).unwrap();
997 assert!(buf.capacity() >= 10);
998 }
999
1000 #[test]
1001 #[cfg(feature = "smallvec")]
1002 fn test_smallvec_reserve() {
1003 let mut buf = smallvec::SmallVec::<[u8; 8]>::new();
1004 IoBufMut::reserve(&mut buf, 10).unwrap();
1005 assert!(buf.capacity() >= 10);
1006 }
1007
1008 #[test]
1009 #[cfg(feature = "memmap2")]
1010 #[cfg_attr(miri, ignore = "Miri does not support mmap")]
1011 fn tests_memmap2() {
1012 use std::{
1013 fs::{OpenOptions, remove_file},
1014 io::{Seek, SeekFrom, Write},
1015 };
1016
1017 use memmap2::MmapOptions;
1018
1019 use super::*;
1020
1021 let path = std::env::temp_dir().join("compio_buf_mmap_mut_test");
1022
1023 let mut file = OpenOptions::new()
1024 .read(true)
1025 .write(true)
1026 .create(true)
1027 .truncate(true)
1028 .open(&path)
1029 .unwrap();
1030 let data = b"hello memmap2";
1031 file.write_all(data).unwrap();
1032 file.flush().unwrap();
1033 file.seek(SeekFrom::Start(0)).unwrap();
1034 {
1035 let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
1036
1037 let init_slice = mmap.as_init();
1038 assert_eq!(init_slice, data);
1039 }
1040
1041 {
1042 let mut mmap = unsafe { MmapOptions::new().map_mut(&file).unwrap() };
1043
1044 let init_slice = mmap.as_mut_slice();
1045 assert_eq!(init_slice, data);
1046 }
1047
1048 remove_file(path).unwrap();
1049 }
1050
1051 #[test]
1052 fn test_other_reserve() {
1053 let mut buf = [1, 1, 4, 5, 1, 4];
1054 let res = IoBufMut::reserve(&mut buf, 10);
1055 assert!(res.is_err_and(|x| x.is_not_supported()));
1056 assert!(buf.buf_capacity() == 6);
1057 }
1058
1059 #[test]
1060 fn test_extend() {
1061 let mut buf = Vec::from(b"hello");
1062 IoBufMutExt::extend_from_slice(&mut buf, b" world").unwrap();
1063 assert_eq!(buf.as_slice(), b"hello world");
1064
1065 let mut buf = [];
1066 let res = IoBufMutExt::extend_from_slice(&mut buf, b" ");
1067 assert!(res.is_err_and(|x| x.is_not_supported()));
1068 }
1069}