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);
480
481 self.advance_to(init + len);
483 }
484
485 Ok(())
486 }
487
488 fn copy_within<R>(&mut self, src: R, dest: usize)
499 where
500 R: RangeBounds<usize>,
501 {
502 self.as_uninit().copy_within(src, dest);
503 }
504
505 fn uninit(self) -> Uninit<Self>
526 where
527 Self: Sized,
528 {
529 Uninit::new(self)
530 }
531
532 fn into_writer(self) -> Writer<Self>
535 where
536 Self: Sized,
537 {
538 Writer::new(self)
539 }
540
541 fn as_writer(&mut self) -> WriterRef<'_, Self> {
544 WriterRef::new(self)
545 }
546
547 fn is_filled(&mut self) -> bool {
549 let len = (*self).as_init().len();
550 let cap = (*self).buf_capacity();
551 len == cap
552 }
553}
554
555impl<B: IoBufMut + ?Sized> IoBufMutExt for B {}
556
557impl<B: IoBufMut + ?Sized> IoBufMut for &'static mut B {
558 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
559 (**self).as_uninit()
560 }
561
562 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
563 (**self).reserve(len)
564 }
565
566 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
567 (**self).reserve_exact(len)
568 }
569}
570
571impl<B: IoBufMut + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBufMut
572 for t_alloc!(Box, B, A)
573{
574 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
575 (**self).as_uninit()
576 }
577
578 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
579 (**self).reserve(len)
580 }
581
582 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
583 (**self).reserve_exact(len)
584 }
585}
586
587impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> IoBufMut for t_alloc!(Vec, u8, A) {
588 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
589 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
590 let cap = self.capacity();
591 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
593 }
594
595 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
596 if let Err(e) = Vec::try_reserve(self, len) {
597 return Err(ReserveError::ReserveFailed(Box::new(e)));
598 }
599
600 Ok(())
601 }
602
603 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
604 if self.capacity() - self.len() >= len {
605 return Ok(());
606 }
607
608 if let Err(e) = Vec::try_reserve_exact(self, len) {
609 return Err(ReserveExactError::ReserveFailed(Box::new(e)));
610 }
611
612 if self.capacity() - self.len() != len {
613 return Err(ReserveExactError::ExactSizeMismatch {
614 reserved: self.capacity() - self.len(),
615 expected: len,
616 });
617 }
618 Ok(())
619 }
620}
621
622impl IoBufMut for [u8] {
623 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
624 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
625 let len = self.len();
626 unsafe { std::slice::from_raw_parts_mut(ptr, len) }
629 }
630}
631
632impl<const N: usize> IoBufMut for [u8; N] {
633 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
634 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
635 unsafe { std::slice::from_raw_parts_mut(ptr, N) }
638 }
639}
640
641#[cfg(feature = "bytes")]
642impl IoBufMut for bytes::BytesMut {
643 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
644 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
645 let cap = self.capacity();
646 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
649 }
650
651 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
652 bytes::BytesMut::reserve(self, len);
653 Ok(())
654 }
655
656 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
657 if self.capacity() - self.len() >= len {
658 return Ok(());
659 }
660
661 bytes::BytesMut::reserve(self, len);
662
663 if self.capacity() - self.len() != len {
664 Err(ReserveExactError::ExactSizeMismatch {
665 reserved: self.capacity() - self.len(),
666 expected: len,
667 })
668 } else {
669 Ok(())
670 }
671 }
672}
673
674#[cfg(feature = "read_buf")]
675impl IoBufMut for std::io::BorrowedBuf<'static, u8> {
676 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
677 let total_cap = self.capacity();
678
679 unsafe {
683 let filled_ptr = self.filled().as_ptr() as *mut MaybeUninit<u8>;
684 std::slice::from_raw_parts_mut(filled_ptr, total_cap)
685 }
686 }
687}
688
689#[cfg(feature = "arrayvec")]
690impl<const N: usize> IoBufMut for arrayvec::ArrayVec<u8, N> {
691 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
692 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
693 unsafe { std::slice::from_raw_parts_mut(ptr, N) }
695 }
696}
697
698#[cfg(feature = "smallvec")]
699impl<const N: usize> IoBufMut for smallvec::SmallVec<[u8; N]>
700where
701 [u8; N]: smallvec::Array<Item = u8>,
702{
703 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
704 let ptr = self.as_mut_ptr() as *mut MaybeUninit<u8>;
705 let cap = self.capacity();
706 unsafe { std::slice::from_raw_parts_mut(ptr, cap) }
709 }
710
711 fn reserve(&mut self, len: usize) -> Result<(), ReserveError> {
712 if let Err(e) = smallvec::SmallVec::try_reserve(self, len) {
713 return Err(ReserveError::ReserveFailed(Box::new(
714 smallvec_err::SmallVecErr(e),
715 )));
716 }
717 Ok(())
718 }
719
720 fn reserve_exact(&mut self, len: usize) -> Result<(), ReserveExactError> {
721 if self.capacity() - self.len() >= len {
722 return Ok(());
723 }
724
725 if let Err(e) = smallvec::SmallVec::try_reserve_exact(self, len) {
726 return Err(ReserveExactError::ReserveFailed(Box::new(
727 smallvec_err::SmallVecErr(e),
728 )));
729 }
730
731 if self.capacity() - self.len() != len {
732 return Err(ReserveExactError::ExactSizeMismatch {
733 reserved: self.capacity() - self.len(),
734 expected: len,
735 });
736 }
737 Ok(())
738 }
739}
740
741#[cfg(feature = "memmap2")]
742impl IoBufMut for memmap2::MmapMut {
743 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
744 unsafe { std::mem::transmute(self.as_mut()) }
746 }
747}
748
749pub trait SetLen {
751 unsafe fn set_len(&mut self, len: usize);
758}
759
760const _: [&dyn SetLen; 0] = [];
762
763pub trait SetLenExt: SetLen {
765 unsafe fn advance(&mut self, len: usize)
772 where
773 Self: IoBuf,
774 {
775 let current_len = (*self).buf_len();
776 let new_len = current_len.checked_add(len).expect("length overflow");
777 unsafe { self.set_len(new_len) };
778 }
779
780 unsafe fn advance_to(&mut self, len: usize)
788 where
789 Self: IoBuf,
790 {
791 let current_len = (*self).buf_len();
792 if len > current_len {
793 unsafe { self.set_len(len) };
794 }
795 }
796
797 unsafe fn advance_vec_to(&mut self, len: usize)
805 where
806 Self: IoVectoredBuf,
807 {
808 let current_len = (*self).total_len();
809 if len > current_len {
810 unsafe { self.set_len(len) };
811 }
812 }
813
814 fn clear(&mut self)
817 where
818 Self: IoBuf,
819 {
820 unsafe { self.set_len(0) };
822 }
823}
824
825impl<B: SetLen + ?Sized> SetLenExt for B {}
826
827impl<B: SetLen + ?Sized> SetLen for &'static mut B {
828 unsafe fn set_len(&mut self, len: usize) {
829 unsafe { (**self).set_len(len) }
830 }
831}
832
833impl<B: SetLen + ?Sized, #[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen
834 for t_alloc!(Box, B, A)
835{
836 unsafe fn set_len(&mut self, len: usize) {
837 unsafe { (**self).set_len(len) }
838 }
839}
840
841impl<#[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen for t_alloc!(Vec, u8, A) {
842 unsafe fn set_len(&mut self, len: usize) {
843 unsafe { self.set_len(len) };
844 }
845}
846
847impl SetLen for [u8] {
848 unsafe fn set_len(&mut self, len: usize) {
849 debug_assert!(len <= self.len());
850 }
851}
852
853impl<const N: usize> SetLen for [u8; N] {
854 unsafe fn set_len(&mut self, len: usize) {
855 debug_assert!(len <= N);
856 }
857}
858
859#[cfg(feature = "bytes")]
860impl SetLen for bytes::BytesMut {
861 unsafe fn set_len(&mut self, len: usize) {
862 unsafe { self.set_len(len) };
863 }
864}
865
866#[cfg(feature = "read_buf")]
867impl SetLen for std::io::BorrowedBuf<'static, u8> {
868 unsafe fn set_len(&mut self, len: usize) {
869 debug_assert!(self.capacity() >= len);
870
871 #[allow(unused_unsafe)]
874 unsafe {
875 self.clear().unfilled().advance(len)
876 };
877 }
878}
879
880#[cfg(feature = "arrayvec")]
881impl<const N: usize> SetLen for arrayvec::ArrayVec<u8, N> {
882 unsafe fn set_len(&mut self, len: usize) {
883 if (**self).buf_len() < len {
884 unsafe { self.set_len(len) };
885 }
886 }
887}
888
889#[cfg(feature = "smallvec")]
890impl<const N: usize> SetLen for smallvec::SmallVec<[u8; N]>
891where
892 [u8; N]: smallvec::Array<Item = u8>,
893{
894 unsafe fn set_len(&mut self, len: usize) {
895 if (**self).buf_len() < len {
896 unsafe { self.set_len(len) };
897 }
898 }
899}
900
901#[cfg(feature = "memmap2")]
902impl SetLen for memmap2::MmapMut {
903 unsafe fn set_len(&mut self, len: usize) {
904 debug_assert!(len <= self.len())
905 }
906}
907
908impl<T: IoBufMut> SetLen for [T] {
909 unsafe fn set_len(&mut self, len: usize) {
910 unsafe { default_set_len(self.iter_mut(), len) }
911 }
912}
913
914impl<T: IoBufMut, const N: usize> SetLen for [T; N] {
915 unsafe fn set_len(&mut self, len: usize) {
916 unsafe { default_set_len(self.iter_mut(), len) }
917 }
918}
919
920impl<T: IoBufMut, #[cfg(feature = "allocator_api")] A: Allocator + 'static> SetLen
921 for t_alloc!(Vec, T, A)
922{
923 unsafe fn set_len(&mut self, len: usize) {
924 unsafe { default_set_len(self.iter_mut(), len) }
925 }
926}
927
928#[cfg(feature = "arrayvec")]
929impl<T: IoBufMut, const N: usize> SetLen for arrayvec::ArrayVec<T, N> {
930 unsafe fn set_len(&mut self, len: usize) {
931 unsafe { default_set_len(self.iter_mut(), len) }
932 }
933}
934
935#[cfg(feature = "smallvec")]
936impl<T: IoBufMut, const N: usize> SetLen for smallvec::SmallVec<[T; N]>
937where
938 [T; N]: smallvec::Array<Item = T>,
939{
940 unsafe fn set_len(&mut self, len: usize) {
941 unsafe { default_set_len(self.iter_mut(), len) }
942 }
943}
944
945unsafe fn default_set_len<'a, B: IoBufMut>(
951 iter: impl IntoIterator<Item = &'a mut B>,
952 mut len: usize,
953) {
954 let mut iter = iter.into_iter();
955 while len > 0 {
956 let Some(curr) = iter.next() else { return };
957 let sub = (*curr).buf_capacity().min(len);
958 unsafe { curr.set_len(sub) };
959 len -= sub;
960 }
961}
962
963#[cfg(test)]
964mod test {
965 use crate::{IoBufMut, IoBufMutExt};
966
967 #[test]
968 fn test_vec_reserve() {
969 let mut buf = Vec::new();
970 IoBufMut::reserve(&mut buf, 10).unwrap();
971 assert!(buf.capacity() >= 10);
972
973 let mut buf = Vec::new();
974 IoBufMut::reserve_exact(&mut buf, 10).unwrap();
975 assert!(buf.capacity() == 10);
976
977 let mut buf = Box::new(Vec::new());
978 IoBufMut::reserve_exact(&mut buf, 10).unwrap();
979 assert!(buf.capacity() == 10);
980 }
981
982 #[test]
983 #[cfg(feature = "bytes")]
984 fn test_bytes_reserve() {
985 let mut buf = bytes::BytesMut::new();
986 IoBufMut::reserve(&mut buf, 10).unwrap();
987 assert!(buf.capacity() >= 10);
988 }
989
990 #[test]
991 #[cfg(feature = "smallvec")]
992 fn test_smallvec_reserve() {
993 let mut buf = smallvec::SmallVec::<[u8; 8]>::new();
994 IoBufMut::reserve(&mut buf, 10).unwrap();
995 assert!(buf.capacity() >= 10);
996 }
997
998 #[test]
999 #[cfg(feature = "memmap2")]
1000 fn tests_memmap2() {
1001 use std::{
1002 fs::{OpenOptions, remove_file},
1003 io::{Seek, SeekFrom, Write},
1004 };
1005
1006 use memmap2::MmapOptions;
1007
1008 use super::*;
1009
1010 let path = std::env::temp_dir().join("compio_buf_mmap_mut_test");
1011
1012 let mut file = OpenOptions::new()
1013 .read(true)
1014 .write(true)
1015 .create(true)
1016 .truncate(true)
1017 .open(&path)
1018 .unwrap();
1019 let data = b"hello memmap2";
1020 file.write_all(data).unwrap();
1021 file.flush().unwrap();
1022 file.seek(SeekFrom::Start(0)).unwrap();
1023 {
1024 let mmap = unsafe { MmapOptions::new().map(&file).unwrap() };
1025
1026 let init_slice = mmap.as_init();
1027 assert_eq!(init_slice, data);
1028 }
1029
1030 {
1031 let mut mmap = unsafe { MmapOptions::new().map_mut(&file).unwrap() };
1032
1033 let init_slice = mmap.as_mut_slice();
1034 assert_eq!(init_slice, data);
1035 }
1036
1037 remove_file(path).unwrap();
1038 }
1039
1040 #[test]
1041 fn test_other_reserve() {
1042 let mut buf = [1, 1, 4, 5, 1, 4];
1043 let res = IoBufMut::reserve(&mut buf, 10);
1044 assert!(res.is_err_and(|x| x.is_not_supported()));
1045 assert!(buf.buf_capacity() == 6);
1046 }
1047
1048 #[test]
1049 fn test_extend() {
1050 let mut buf = Vec::from(b"hello");
1051 IoBufMutExt::extend_from_slice(&mut buf, b" world").unwrap();
1052 assert_eq!(buf.as_slice(), b"hello world");
1053
1054 let mut buf = [];
1055 let res = IoBufMutExt::extend_from_slice(&mut buf, b" ");
1056 assert!(res.is_err_and(|x| x.is_not_supported()));
1057 }
1058}