1use core::borrow::{Borrow, BorrowMut};
2use core::fmt;
3use core::marker::PhantomData;
4use core::mem::MaybeUninit;
5use core::ops::{Deref, DerefMut};
6
7#[cfg(feature = "redox_syscall")]
8use syscall::data::IoVec;
9#[cfg(all(windows, feature = "winapi"))]
10use winapi::shared::{
11 ntdef::{CHAR, ULONG},
12 ws2def::WSABUF,
13};
14
15pub mod init_marker {
16 use super::*;
17
18 mod private {
19 pub trait Sealed: Sized + 'static + Send + Sync + Unpin {}
20 }
21 pub unsafe trait InitMarker: private::Sealed {
22 const IS_INITIALIZED: bool;
23 type DerefTargetItem: fmt::Debug;
24 }
25
26 pub enum Init {}
27 pub enum Uninit {}
28
29 impl private::Sealed for Init {}
30 impl private::Sealed for Uninit {}
31
32 unsafe impl InitMarker for Init {
33 const IS_INITIALIZED: bool = true;
34 type DerefTargetItem = u8;
35 }
36 unsafe impl InitMarker for Uninit {
37 const IS_INITIALIZED: bool = false;
38 type DerefTargetItem = MaybeUninit<u8>;
39 }
40} use self::init_marker::*;
42
43#[repr(transparent)]
54#[derive(Clone, Copy)]
55pub struct IoSlice<'a, I: InitMarker = Init> {
56 #[cfg(all(unix, feature = "libc", not(all(feature = "redox_syscall"))))]
57 inner: (libc::iovec, PhantomData<&'a [I::DerefTargetItem]>),
58
59 #[cfg(feature = "redox_syscall")]
60 inner: (IoVec, PhantomData<&'a [I::DerefTargetItem]>),
61
62 #[cfg(all(windows, feature = "winapi"))]
63 inner: (WSABUF, PhantomData<&'a [I::DerefTargetItem]>),
64
65 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
66 inner: &'a [I::DerefTargetItem],
67
68 _marker: PhantomData<I>,
69}
70
71unsafe impl<'a, I: InitMarker> Send for IoSlice<'a, I> {}
74unsafe impl<'a, I: InitMarker> Sync for IoSlice<'a, I> {}
76impl<'a, I: InitMarker> Unpin for IoSlice<'a, I> {}
77
78#[cfg(feature = "std")]
79impl<'a, I: InitMarker> std::panic::UnwindSafe for IoSlice<'a, I> {}
80#[cfg(feature = "std")]
81impl<'a, I: InitMarker> std::panic::RefUnwindSafe for IoSlice<'a, I> {}
82
83impl<'a, I: InitMarker> IoSlice<'a, I> {
84 #[inline]
91 pub fn new(slice: &'a [u8]) -> Self {
92 unsafe { Self::__construct(slice.as_ptr(), slice.len()) }
93 }
94
95 #[inline]
98 pub fn as_uninit(&self) -> &IoSlice<'a, Uninit> {
99 unsafe { &*(self as *const Self as *const IoSlice<'a, Uninit>) }
100 }
101 #[inline]
102 pub fn as_uninit_mut(&mut self) -> &mut IoSlice<'a, Uninit> {
103 unsafe { &mut *(self as *mut Self as *mut IoSlice<'a, Uninit>) }
104 }
105
106 #[inline]
108 pub fn cast_to_uninit_slices(selves: &[Self]) -> &[IoSlice<'a, Uninit>] {
109 unsafe { crate::cast_slice_same_layout(selves) }
110 }
111 #[inline]
113 pub fn cast_to_uninit_slices_mut(selves: &mut [Self]) -> &mut [IoSlice<'a, Uninit>] {
114 unsafe { crate::cast_slice_same_layout_mut(selves) }
115 }
116
117 #[inline]
120 pub fn into_uninit(self) -> IoSlice<'a, Uninit> {
121 unsafe { IoSlice::__construct(self.__ptr(), self.__len()) }
122 }
123
124 #[inline]
131 pub unsafe fn assume_init(self) -> IoSlice<'a, Init> {
132 IoSlice::__construct(self.__ptr(), self.__len())
133 }
134
135 #[cfg(all(unix, feature = "libc"))]
147 #[inline]
148 pub unsafe fn from_raw_iovec(slice: libc::iovec) -> Self {
149 Self {
150 #[cfg(not(feature = "redox_syscall"))]
151 inner: (slice, PhantomData),
152
153 #[cfg(feature = "redox_syscall")]
154 inner: (
155 IoVec {
156 addr: slice.iov_base as usize,
157 len: slice.iov_len,
158 },
159 PhantomData,
160 ),
161 _marker: PhantomData,
162 }
163 }
164 #[cfg(all(windows, feature = "winapi"))]
174 #[inline]
175 pub unsafe fn from_raw_wsabuf(slice: WSABUF) -> Self {
176 Self {
177 inner: (slice, PhantomData),
178 _marker: PhantomData,
179 }
180 }
181 #[cfg(all(unix, feature = "libc"))]
188 #[inline]
189 pub fn as_raw_iovec(&self) -> libc::iovec {
190 #[cfg(not(feature = "redox_syscall"))]
191 return self.inner.0;
192
193 #[cfg(feature = "redox_syscall")]
194 return libc::iovec {
195 iov_base: self.inner.0.addr as *mut libc::c_void,
196 iov_len: self.inner.0.len,
197 };
198 }
199
200 #[cfg(all(windows, feature = "winapi"))]
207 #[inline]
208 pub fn as_raw_wsabuf(&self) -> WSABUF {
209 self.inner.0
210 }
211
212 #[cfg(all(unix, feature = "libc"))]
217 #[inline]
218 pub fn cast_to_raw_iovecs(slices: &'a [Self]) -> &'a [libc::iovec] {
219 unsafe { crate::cast_slice_same_layout(slices) }
220 }
221
222 #[cfg(all(windows, feature = "winapi"))]
228 #[inline]
229 pub fn cast_to_raw_wsabufs(slices: &'a [Self]) -> &'a [WSABUF] {
230 unsafe { crate::cast_slice_same_layout(slices) }
231 }
232 #[cfg(all(unix, feature = "libc"))]
243 #[inline]
244 pub unsafe fn cast_to_raw_iovecs_mut(slices: &'a mut [Self]) -> &'a mut [libc::iovec] {
245 crate::cast_slice_same_layout_mut(slices)
246 }
247 #[cfg(all(windows, feature = "winapi"))]
259 #[inline]
260 pub unsafe fn cast_to_raw_wsabufs_mut(slices: &'a mut [Self]) -> &'a mut [WSABUF] {
261 cast_slice_same_layout_mut(slices)
262 }
263
264 #[inline]
274 pub fn advance(&mut self, count: usize) {
275 unsafe {
276 self.__set_len(
277 self.__len()
278 .checked_sub(count)
279 .expect("IoSlice::advance causes length to overflow"),
280 );
281 self.__set_ptr(self.__ptr().add(count));
282 }
283 }
284 #[must_use]
294 pub fn advance_within(mut slices: &mut [Self], mut n: usize) -> Option<&mut [Self]> {
295 while let Some(buffer) = slices.first_mut() {
296 if n == 0 {
297 return Some(slices);
298 };
299
300 let buffer_len = buffer.len();
301
302 if buffer_len > n {
303 buffer.advance(n);
304 } else {
305 slices = &mut slices[1..];
306 }
307 n -= core::cmp::min(buffer_len, n);
308 }
309 if n > 0 {
310 return None;
311 }
312 Some(slices)
313 }
314 #[inline]
322 pub fn inner_data(&self) -> &'a [I::DerefTargetItem] {
323 unsafe {
324 core::slice::from_raw_parts(self.__ptr() as *const I::DerefTargetItem, self.__len())
325 }
326 }
327 #[inline]
329 pub fn from_inner_data(inner_data: &'a [I::DerefTargetItem]) -> Self {
330 unsafe { Self::__construct(inner_data.as_ptr() as *const u8, inner_data.len()) }
331 }
332 #[inline]
334 pub fn as_maybe_uninit_slice(&self) -> &'a [MaybeUninit<u8>] {
335 self.as_uninit().inner_data()
336 }
337 fn __ptr(&self) -> *const u8 {
338 #[cfg(all(unix, feature = "libc", not(feature = "redox_syscall")))]
339 return self.inner.0.iov_base as *const u8;
340
341 #[cfg(feature = "redox_syscall")]
342 return self.inner.0.addr as *const u8;
343
344 #[cfg(all(windows, feature = "winapi"))]
345 return self.inner.0.buf as *const u8;
346
347 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
348 return self.inner.as_ptr() as *const u8;
349 }
350 fn __len(&self) -> usize {
351 #[cfg(all(unix, feature = "libc", not(feature = "redox_syscall")))]
352 return self.inner.0.iov_len as usize;
353
354 #[cfg(feature = "redox_syscall")]
355 return self.inner.0.len;
356
357 #[cfg(all(windows, feature = "winapi"))]
358 return self.inner.0.len as usize;
359
360 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
361 return self.inner.len();
362 }
363 #[inline]
364 unsafe fn __set_ptr(&mut self, ptr: *const u8) {
365 #[cfg(all(unix, feature = "libc", not(feature = "redox_syscall")))]
366 {
367 self.inner.0.iov_base = ptr as *mut libc::c_void;
368 }
369 #[cfg(feature = "redox_syscall")]
370 {
371 self.inner.0.addr = ptr as usize;
372 }
373
374 #[cfg(all(windows, feature = "winapi"))]
375 {
376 self.inner.0.buf = ptr as *mut CHAR;
377 }
378
379 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
380 {
381 self.inner =
382 core::slice::from_raw_parts(ptr as *const I::DerefTargetItem, self.__len());
383 }
384 }
385 #[inline]
386 unsafe fn __set_len(&mut self, len: usize) {
387 #[cfg(all(unix, feature = "libc", not(feature = "redox_syscall")))]
388 {
389 self.inner.0.iov_len = len as usize;
390 }
391 #[cfg(feature = "redox_syscall")]
392 {
393 self.inner.0.len = len;
394 }
395
396 #[cfg(all(windows, feature = "libc"))]
397 {
398 use core::convert::TryInto;
399
400 self.inner.0.len = len
401 .try_into()
402 .expect("length exceeding 2^32 bytes, which is the limit of WSABUF");
403 }
404
405 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
406 {
407 self.inner =
408 core::slice::from_raw_parts(self.__ptr() as *const I::DerefTargetItem, len);
409 }
410 }
411 unsafe fn __construct(ptr: *const u8, len: usize) -> Self {
412 #[cfg(all(windows, feature = "winapi"))]
413 use core::convert::TryInto;
414
415 Self {
416 #[cfg(all(unix, feature = "libc", not(feature = "redox_syscall")))]
417 inner: (
418 libc::iovec {
419 iov_base: ptr as *mut libc::c_void,
420 iov_len: len as usize,
421 },
422 PhantomData,
423 ),
424 #[cfg(feature = "redox_syscall")]
425 inner: (
426 IoVec {
427 addr: ptr as usize,
428 len,
429 },
430 PhantomData,
431 ),
432 #[cfg(all(windows, feature = "winapi"))]
433 inner: (
434 WSABUF {
435 len: len.try_into().expect(
436 "Constructing an IoSlice that is larger than the 2^32 limit of WSABUF",
437 ),
438 buf: ptr as *mut CHAR,
439 },
440 PhantomData,
441 ),
442 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
443 inner: { core::slice::from_raw_parts(ptr as *const I::DerefTargetItem, len) },
444
445 _marker: PhantomData,
446 }
447 }
448
449 #[inline]
450 pub fn split_at(self, mid: usize) -> (Self, Self) {
451 let (a, b) = self.inner_data().split_at(mid);
452 (Self::from_inner_data(a), Self::from_inner_data(b))
453 }
454}
455impl<'a> IoSlice<'a, Init> {
456 #[inline]
458 pub fn as_slice(&self) -> &'a [u8] {
459 self.inner_data()
460 }
461 #[cfg(feature = "std")]
465 #[inline]
466 pub fn into_std_ioslice(self) -> std::io::IoSlice<'a> {
467 std::io::IoSlice::new(self.as_slice())
468 }
469 #[cfg(feature = "std")]
474 #[inline]
475 pub fn cast_to_std_ioslices<'b>(slices: &'b [Self]) -> &'b [std::io::IoSlice<'a>] {
476 unsafe { crate::cast_slice_same_layout(slices) }
477 }
478 #[cfg(feature = "std")]
484 #[inline]
485 pub fn cast_to_std_ioslices_mut(slices: &'a mut [Self]) -> &'a mut [std::io::IoSlice<'a>] {
486 unsafe { crate::cast_slice_same_layout_mut(slices) }
487 }
488}
489impl<'a, I: InitMarker> fmt::Debug for IoSlice<'a, I> {
490 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
491 if I::IS_INITIALIZED {
492 write!(f, "{:?}", self.inner_data())
493 } else {
494 write!(
495 f,
496 "[possibly uninitialized immutable I/O slice at {:p}, len {} bytes]",
497 self.as_maybe_uninit_slice().as_ptr(),
498 self.as_maybe_uninit_slice().len()
499 )
500 }
501 }
502}
503impl<'a, I: InitMarker> AsRef<[MaybeUninit<u8>]> for IoSlice<'a, I> {
504 #[inline]
505 fn as_ref(&self) -> &[MaybeUninit<u8>] {
506 self.as_maybe_uninit_slice()
507 }
508}
509impl<'a> AsRef<[u8]> for IoSlice<'a, Init> {
510 #[inline]
511 fn as_ref(&self) -> &[u8] {
512 self.as_slice()
513 }
514}
515impl<'a, I: InitMarker> Borrow<[I::DerefTargetItem]> for IoSlice<'a, I> {
516 #[inline]
517 fn borrow(&self) -> &[I::DerefTargetItem] {
518 self.inner_data()
519 }
520}
521impl<'a> Borrow<[MaybeUninit<u8>]> for IoSlice<'a, Init> {
522 #[inline]
523 fn borrow(&self) -> &[MaybeUninit<u8>] {
524 self.as_maybe_uninit_slice()
525 }
526}
527impl<'a, I: InitMarker> Deref for IoSlice<'a, I> {
528 type Target = [I::DerefTargetItem];
529
530 #[inline]
531 fn deref(&self) -> &Self::Target {
532 self.inner_data()
533 }
534}
535impl<'a, I: InitMarker> From<&'a [I::DerefTargetItem]> for IoSlice<'a, I> {
536 #[inline]
537 fn from(slice: &'a [I::DerefTargetItem]) -> Self {
538 Self::from_inner_data(slice)
539 }
540}
541impl<'a, I: InitMarker> From<&'a mut [I::DerefTargetItem]> for IoSlice<'a, I> {
542 #[inline]
543 fn from(slice: &'a mut [I::DerefTargetItem]) -> Self {
544 Self::from_inner_data(&*slice)
545 }
546}
547impl<'a> From<&'a [u8]> for IoSlice<'a, Uninit> {
548 fn from(maybe_uninit_slice: &'a [u8]) -> Self {
549 Self::new(maybe_uninit_slice)
550 }
551}
552impl<'a> From<&'a mut [u8]> for IoSlice<'a, Uninit> {
553 fn from(maybe_uninit_slice: &'a mut [u8]) -> Self {
554 Self::new(&*maybe_uninit_slice)
555 }
556}
557
558#[cfg(feature = "nightly")]
559impl<'a, I: InitMarker, const N: usize> From<&'a [I::DerefTargetItem; N]> for IoSlice<'a, I> {
560 #[inline]
561 fn from(array_ref: &'a [I::DerefTargetItem; N]) -> Self {
562 Self::from_inner_data(&array_ref[..])
563 }
564}
565#[cfg(feature = "nightly")]
566impl<'a, I: InitMarker, const N: usize> From<&'a mut [I::DerefTargetItem; N]> for IoSlice<'a, I> {
567 #[inline]
568 fn from(array_ref: &'a mut [I::DerefTargetItem; N]) -> Self {
569 Self::from_inner_data(&array_ref[..])
570 }
571}
572#[cfg(feature = "nightly")]
573impl<'a, const N: usize> From<&'a [u8; N]> for IoSlice<'a, Uninit> {
574 #[inline]
575 fn from(array_ref: &'a [u8; N]) -> Self {
576 Self::new(&array_ref[..])
577 }
578}
579#[cfg(feature = "nightly")]
580impl<'a, const N: usize> From<&'a mut [u8; N]> for IoSlice<'a, Uninit> {
581 #[inline]
582 fn from(array_ref: &'a mut [u8; N]) -> Self {
583 Self::new(&array_ref[..])
584 }
585}
586impl<'a> PartialEq for IoSlice<'a, Init> {
587 #[inline]
588 fn eq(&self, other: &Self) -> bool {
589 self == other.as_slice()
590 }
591}
592impl<'a> PartialEq<[u8]> for IoSlice<'a, Init> {
593 #[inline]
594 fn eq(&self, other: &[u8]) -> bool {
595 self.as_slice() == other
596 }
597}
598#[cfg(feature = "nightly")]
599impl<'a, const N: usize> PartialEq<[u8; N]> for IoSlice<'a, Init> {
600 #[inline]
601 fn eq(&self, other: &[u8; N]) -> bool {
602 self == &other[..]
603 }
604}
605impl<'a, 'b> PartialEq<IoSliceMut<'b, Init>> for IoSlice<'a, Init> {
606 #[inline]
607 fn eq(&self, other: &IoSliceMut<'b>) -> bool {
608 self == other.as_slice()
609 }
610}
611
612impl<'a> Eq for IoSlice<'a, Init> {}
613
614impl<'a> PartialOrd<[u8]> for IoSlice<'a, Init> {
615 #[inline]
616 fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
617 PartialOrd::partial_cmp(self.as_slice(), other)
618 }
619}
620impl<'a, 'b> PartialOrd<IoSliceMut<'b, Init>> for IoSlice<'a, Init> {
621 #[inline]
622 fn partial_cmp(&self, other: &IoSliceMut<'b>) -> Option<core::cmp::Ordering> {
623 PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
624 }
625}
626#[cfg(feature = "nightly")]
627impl<'a, const N: usize> PartialOrd<[u8; N]> for IoSlice<'a, Init> {
628 #[inline]
629 fn partial_cmp(&self, other: &[u8; N]) -> Option<core::cmp::Ordering> {
630 PartialOrd::partial_cmp(self.as_slice(), other)
631 }
632}
633
634impl<'a> PartialOrd for IoSlice<'a, Init> {
635 #[inline]
636 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
637 Some(Ord::cmp(self, other))
638 }
639}
640impl<'a> Ord for IoSlice<'a, Init> {
641 #[inline]
642 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
643 Ord::cmp(self.as_slice(), other.as_slice())
644 }
645}
646impl<'a, I: InitMarker> Default for IoSlice<'a, I> {
647 #[inline]
648 fn default() -> Self {
649 Self::new(&[])
650 }
651}
652impl<'a> core::hash::Hash for IoSlice<'a, Init> {
653 #[inline]
654 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
655 state.write(self.as_slice())
656 }
657}
658
659#[cfg(feature = "std")]
660impl<'a, I: InitMarker> From<std::io::IoSlice<'a>> for IoSlice<'a, I> {
661 #[inline]
662 fn from(slice: std::io::IoSlice<'a>) -> Self {
663 unsafe { Self::__construct(slice.as_ptr(), slice.len()) }
664 }
665}
666#[cfg(feature = "std")]
667impl<'a, I: InitMarker> From<std::io::IoSliceMut<'a>> for IoSlice<'a, I> {
668 #[inline]
669 fn from(mut slice: std::io::IoSliceMut<'a>) -> Self {
670 unsafe { Self::__construct(slice.as_mut_ptr(), slice.len()) }
671 }
672}
673#[cfg(all(unix, feature = "libc"))]
674impl<'a, I: InitMarker> From<IoSlice<'a, I>> for libc::iovec {
675 #[inline]
676 fn from(slice: IoSlice<'a, I>) -> Self {
677 slice.as_raw_iovec()
678 }
679}
680#[cfg(feature = "stable_deref_trait")]
681unsafe impl<'a, I: InitMarker> stable_deref_trait::StableDeref for IoSlice<'a, I> {}
682
683#[repr(transparent)]
694pub struct IoSliceMut<'a, I: InitMarker = Init> {
695 #[cfg(all(unix, feature = "libc"))]
696 inner: (libc::iovec, PhantomData<&'a mut [I::DerefTargetItem]>),
697
698 #[cfg(all(windows, feature = "winapi"))]
699 inner: (WSABUF, PhantomData<&'a mut [I::DerefTargetItem]>),
700
701 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
702 inner: &'a mut [I::DerefTargetItem],
703
704 _marker: PhantomData<I>,
705}
706unsafe impl<'a, I: InitMarker> Send for IoSliceMut<'a, I> {}
708unsafe impl<'a, I: InitMarker> Sync for IoSliceMut<'a, I> {}
710impl<'a, I: InitMarker> Unpin for IoSliceMut<'a, I> {}
711
712#[cfg(feature = "std")]
713impl<'a, I: InitMarker> std::panic::UnwindSafe for IoSliceMut<'a, I> {}
714#[cfg(feature = "std")]
715impl<'a, I: InitMarker> std::panic::RefUnwindSafe for IoSliceMut<'a, I> {}
716
717impl<'a, I: InitMarker> IoSliceMut<'a, I> {
718 #[inline]
722 pub fn new(slice: &'a mut [u8]) -> Self {
723 unsafe { Self::__construct(slice.as_mut_ptr(), slice.len()) }
724 }
725 #[inline]
734 pub unsafe fn assume_init(self) -> IoSliceMut<'a, Init> {
735 IoSliceMut::__construct(self.__ptr(), self.__len())
736 }
737
738 #[inline]
744 pub unsafe fn assume_init_ref(&self) -> &IoSliceMut<'a, Init> {
745 &*(self as *const Self as *const IoSliceMut<'a, Init>)
746 }
747 #[inline]
753 pub unsafe fn assume_init_mut(&mut self) -> &mut IoSliceMut<'a, Init> {
754 &mut *(self as *mut Self as *mut IoSliceMut<'a, Init>)
755 }
756
757 #[inline]
759 pub fn into_uninit(self) -> IoSliceMut<'a, Uninit> {
760 unsafe { IoSliceMut::__construct(self.__ptr(), self.__len()) }
761 }
762 #[inline]
765 pub fn as_uninit(&self) -> &IoSliceMut<'a, Uninit> {
766 unsafe { &*(self as *const Self as *const IoSliceMut<'a, Uninit>) }
767 }
768 #[inline]
771 pub fn as_uninit_mut(&mut self) -> &mut IoSliceMut<'a, Uninit> {
772 unsafe { &mut *(self as *mut Self as *mut IoSliceMut<'a, Uninit>) }
773 }
774
775 #[inline]
777 pub fn cast_to_uninit_slices(selves: &[Self]) -> &[IoSliceMut<'a, Uninit>] {
778 unsafe { crate::cast_slice_same_layout(selves) }
779 }
780 #[inline]
786 pub unsafe fn cast_to_uninit_slices_mut(selves: &mut [Self]) -> &mut [IoSliceMut<'a, Uninit>] {
787 crate::cast_slice_same_layout_mut(selves)
788 }
789
790 #[inline]
796 pub unsafe fn cast_to_init_slices(selves: &[Self]) -> &[IoSliceMut<'a, Init>] {
797 crate::cast_slice_same_layout(selves)
798 }
799 #[inline]
805 pub unsafe fn cast_to_init_slices_mut(selves: &mut [Self]) -> &mut [IoSliceMut<'a, Init>] {
806 crate::cast_slice_same_layout_mut(selves)
807 }
808
809 #[cfg(all(unix, feature = "libc"))]
823 #[inline]
824 pub unsafe fn from_raw_iovec(slice: libc::iovec) -> Self {
825 Self {
826 inner: (slice, PhantomData),
827 _marker: PhantomData,
828 }
829 }
830 #[cfg(all(windows, feature = "winapi"))]
834 #[inline]
835 pub unsafe fn from_raw_wsabuf(slice: WSABUF) -> Self {
836 Self {
837 inner: (slice, PhantomData),
838 _marker: PhantomData,
839 }
840 }
841 #[cfg(all(unix, feature = "libc"))]
849 #[inline]
850 pub fn as_raw_iovec(&self) -> libc::iovec {
851 self.inner.0
852 }
853 #[cfg(all(unix, feature = "libc"))]
856 #[inline]
857 pub fn as_raw_iovec_mut(&mut self) -> libc::iovec {
858 self.inner.0
859 }
860
861 #[cfg(all(windows, feature = "winapi"))]
862 #[inline]
863 pub fn as_raw_wsabuf(&self) -> WSABUF {
864 self.inner.0
865 }
866 #[cfg(all(windows, feature = "winapi"))]
867 #[inline]
868 pub fn as_raw_wsabuf_mut(&mut self) -> WSABUF {
869 self.inner.0
870 }
871
872 #[cfg(all(unix, feature = "libc"))]
874 #[inline]
875 pub fn cast_to_raw_iovecs(slices: &[Self]) -> &[libc::iovec] {
876 unsafe { crate::cast_slice_same_layout(slices) }
877 }
878 #[cfg(all(windows, feature = "winapi"))]
880 #[inline]
881 pub fn cast_to_raw_wsabufs(slices: &[Self]) -> &[WSABUF] {
882 unsafe { crate::cast_slice_same_layout(slices) }
883 }
884 #[cfg(all(unix, feature = "libc"))]
892 #[inline]
893 pub unsafe fn cast_to_raw_iovecs_mut(slices: &mut [Self]) -> &mut [libc::iovec] {
894 crate::cast_slice_same_layout_mut(slices)
895 }
896 #[cfg(all(windows, feature = "winapi"))]
904 #[inline]
905 pub unsafe fn cast_to_raw_wsabufs_mut(slices: &mut [Self]) -> &mut [WSABUF] {
906 cast_slice_same_layout_mut(slices)
907 }
908
909 #[cfg(all(unix, feature = "libc"))]
917 #[inline]
918 pub unsafe fn from_raw_iovecs(slice: &[libc::iovec]) -> &[Self] {
919 crate::cast_slice_same_layout(slice)
920 }
921 #[cfg(all(unix, feature = "libc"))]
929 #[inline]
930 pub unsafe fn from_raw_iovecs_mut(slice: &mut [libc::iovec]) -> &mut [Self] {
931 crate::cast_slice_same_layout_mut(slice)
932 }
933 #[cfg(all(windows, feature = "winapi"))]
941 #[inline]
942 pub unsafe fn from_raw_wsabufs(slice: &[WSABUF]) -> &[Self] {
943 cast_slice_same_layout(slice)
944 }
945 #[cfg(all(windows, feature = "winapi"))]
953 #[inline]
954 pub unsafe fn from_raw_wsabufs_mut(slice: &mut [WSABUF]) -> &mut [Self] {
955 cast_slice_same_layout_mut(slice)
956 }
957 #[inline]
963 pub fn advance(&mut self, count: usize) {
964 unsafe {
965 self.__set_len(
966 self.__len()
967 .checked_sub(count)
968 .expect("IoSlice::advance causes length to overflow"),
969 );
970 self.__set_ptr(self.__ptr().add(count));
971 }
972 }
973 #[must_use]
981 #[inline]
982 pub fn advance_within(mut slices: &mut [Self], mut n: usize) -> Option<&mut [Self]> {
983 while let Some(buffer) = slices.first_mut() {
984 if n == 0 {
985 return Some(slices);
986 };
987
988 let buffer_len = buffer.len();
989
990 if buffer_len > n {
991 buffer.advance(n);
992 } else {
993 slices = &mut slices[1..];
994 }
995 n -= core::cmp::min(buffer_len, n);
996 }
997 if n > 0 {
998 return None;
999 }
1000 Some(slices)
1001 }
1002 #[inline]
1005 pub fn inner_data(&self) -> &[I::DerefTargetItem] {
1006 unsafe {
1007 core::slice::from_raw_parts(self.__ptr() as *const I::DerefTargetItem, self.__len())
1008 }
1009 }
1010 #[inline]
1013 pub fn inner_data_mut(&mut self) -> &mut [I::DerefTargetItem] {
1014 unsafe {
1015 core::slice::from_raw_parts_mut(self.__ptr() as *mut I::DerefTargetItem, self.__len())
1016 }
1017 }
1018 #[inline]
1021 pub fn into_inner_data(self) -> &'a mut [I::DerefTargetItem] {
1022 unsafe {
1023 core::slice::from_raw_parts_mut(self.__ptr() as *mut I::DerefTargetItem, self.__len())
1024 }
1025 }
1026 #[inline]
1029 pub fn from_inner_data(inner_data: &'a mut [I::DerefTargetItem]) -> Self {
1030 unsafe { Self::__construct(inner_data.as_mut_ptr() as *mut u8, inner_data.len()) }
1031 }
1032
1033 #[inline]
1034 pub fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<u8>] {
1035 self.as_uninit().inner_data()
1036 }
1037 #[inline]
1038 pub fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1039 self.as_uninit_mut().inner_data_mut()
1040 }
1041
1042 #[inline]
1043 #[must_use]
1044 pub fn zeroed_by_ref<'b>(&'b mut self) -> &'b mut IoSliceMut<'a, Init> {
1045 self.as_maybe_uninit_slice_mut().fill(MaybeUninit::new(0));
1046 unsafe { self.assume_init_mut() }
1047 }
1048
1049 #[inline]
1050 fn __ptr(&self) -> *mut u8 {
1051 #[cfg(all(unix, feature = "libc"))]
1052 return self.inner.0.iov_base as *mut u8;
1053
1054 #[cfg(all(windows, feature = "libc"))]
1055 return self.inner.0.buf as *mut u8;
1056
1057 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1058 return self.inner.as_ptr() as *mut u8;
1059 }
1060 #[inline]
1061 fn __len(&self) -> usize {
1062 #[cfg(all(unix, feature = "libc"))]
1063 return self.inner.0.iov_len as usize;
1064
1065 #[cfg(all(windows, feature = "libc"))]
1066 return self.inner.0.len as usize;
1067
1068 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1069 return self.inner.len();
1070 }
1071 #[inline]
1072 unsafe fn __set_ptr(&mut self, ptr: *mut u8) {
1073 #[cfg(all(unix, feature = "libc"))]
1074 {
1075 self.inner.0.iov_base = ptr as *mut libc::c_void;
1076 }
1077
1078 #[cfg(all(windows, feature = "winapi"))]
1079 {
1080 self.inner.0.buf = ptr as *mut CHAR;
1081 }
1082
1083 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1084 {
1085 self.inner =
1086 core::slice::from_raw_parts_mut(ptr as *mut I::DerefTargetItem, self.__len());
1087 }
1088 }
1089 #[inline]
1090 unsafe fn __set_len(&mut self, len: usize) {
1091 #[cfg(all(unix, feature = "libc"))]
1092 {
1093 self.inner.0.iov_len = len as usize;
1094 }
1095
1096 #[cfg(all(windows, feature = "libc"))]
1097 {
1098 use core::convert::TryInto;
1099
1100 self.inner.0.len = len
1101 .try_into()
1102 .expect("length exceeding 2^32 bytes, which is the limit of WSABUF");
1103 }
1104
1105 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1106 {
1107 self.inner =
1108 core::slice::from_raw_parts_mut(self.__ptr() as *mut I::DerefTargetItem, len);
1109 }
1110 }
1111 #[inline]
1112 unsafe fn __construct(ptr: *mut u8, len: usize) -> Self {
1113 #[cfg(all(windows, feature = "winapi"))]
1114 use core::convert::TryInto;
1115
1116 Self {
1117 #[cfg(all(unix, feature = "libc"))]
1118 inner: (
1119 libc::iovec {
1120 iov_base: ptr as *mut libc::c_void,
1121 iov_len: len as usize,
1122 },
1123 PhantomData,
1124 ),
1125 #[cfg(all(windows, feature = "winapi"))]
1126 inner: (
1127 WSABUF {
1128 len: len.try_into().expect(
1129 "constructing an IoSlice that is larger than the 2^32 limits of WSABUF",
1130 ),
1131 buf: ptr as *mut CHAR,
1132 },
1133 PhantomData,
1134 ),
1135 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1136 inner: { core::slice::from_raw_parts_mut(ptr as *mut I::DerefTargetItem, len) },
1137
1138 _marker: PhantomData,
1139 }
1140 }
1141 #[inline]
1142 pub fn split_at(self, mid: usize) -> (Self, Self) {
1143 let (a, b) = self.into_inner_data().split_at_mut(mid);
1144 (Self::from_inner_data(a), Self::from_inner_data(b))
1145 }
1146}
1147impl<'a> IoSliceMut<'a, Uninit> {
1148 pub fn from_uninit(uninit: &'a mut [MaybeUninit<u8>]) -> Self {
1150 Self::from_inner_data(uninit)
1151 }
1152}
1153impl<'a> IoSliceMut<'a, Init> {
1154 #[inline]
1162 pub fn as_slice(&self) -> &[u8] {
1163 unsafe { crate::cast_slice_same_layout(self.inner_data()) }
1164 }
1165 #[inline]
1167 pub fn into_slice(self) -> &'a [u8] {
1168 &*self.into_slice_mut()
1169 }
1170
1171 #[inline]
1177 pub fn as_slice_mut(&mut self) -> &mut [u8] {
1178 unsafe { crate::cast_slice_same_layout_mut(self.inner_data_mut()) }
1179 }
1180
1181 #[inline]
1183 pub fn into_slice_mut(self) -> &'a mut [u8] {
1184 unsafe { core::slice::from_raw_parts_mut(self.__ptr(), self.__len()) }
1185 }
1186
1187 #[cfg(feature = "std")]
1191 #[inline]
1192 pub fn cast_to_std_ioslices<'b>(slices: &'b [Self]) -> &'b [std::io::IoSlice<'a>] {
1193 unsafe { crate::cast_slice_same_layout(slices) }
1194 }
1195
1196 #[cfg(feature = "std")]
1198 #[inline]
1199 pub fn cast_to_std_mut_ioslices<'b>(slices: &'b [Self]) -> &'b [std::io::IoSliceMut<'a>] {
1200 unsafe { crate::cast_slice_same_layout(slices) }
1201 }
1202 #[cfg(feature = "std")]
1204 #[inline]
1205 pub fn cast_to_std_ioslices_mut<'b>(slices: &'b mut [Self]) -> &'b mut [std::io::IoSlice<'a>] {
1206 unsafe { crate::cast_slice_same_layout_mut(slices) }
1207 }
1208
1209 #[cfg(feature = "std")]
1211 #[inline]
1212 pub fn cast_to_std_mut_ioslices_mut(
1213 slices: &'a mut [Self],
1214 ) -> &'a mut [std::io::IoSliceMut<'a>] {
1215 unsafe { crate::cast_slice_same_layout_mut(slices) }
1216 }
1217}
1218
1219impl<'a, I: InitMarker> AsRef<[I::DerefTargetItem]> for IoSliceMut<'a, I> {
1220 #[inline]
1221 fn as_ref(&self) -> &[I::DerefTargetItem] {
1222 self.inner_data()
1223 }
1224}
1225impl<'a> AsRef<[MaybeUninit<u8>]> for IoSliceMut<'a, Init> {
1226 #[inline]
1227 fn as_ref(&self) -> &[MaybeUninit<u8>] {
1228 self.as_maybe_uninit_slice()
1229 }
1230}
1231impl<'a, I: InitMarker> Borrow<[MaybeUninit<u8>]> for IoSliceMut<'a, I> {
1235 #[inline]
1236 fn borrow(&self) -> &[MaybeUninit<u8>] {
1237 self.as_maybe_uninit_slice()
1238 }
1239}
1240impl<'a> Borrow<[u8]> for IoSliceMut<'a, Init> {
1241 #[inline]
1242 fn borrow(&self) -> &[u8] {
1243 self.as_slice()
1244 }
1245}
1246impl<'a, I: InitMarker> Deref for IoSliceMut<'a, I> {
1247 type Target = [I::DerefTargetItem];
1248
1249 #[inline]
1250 fn deref(&self) -> &Self::Target {
1251 self.inner_data()
1252 }
1253}
1254impl<'a> AsMut<[u8]> for IoSliceMut<'a, Init> {
1255 #[inline]
1256 fn as_mut(&mut self) -> &mut [u8] {
1257 self.as_slice_mut()
1258 }
1259}
1260impl<'a, I: InitMarker> AsMut<[MaybeUninit<u8>]> for IoSliceMut<'a, I> {
1261 #[inline]
1262 fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1263 self.as_maybe_uninit_slice_mut()
1264 }
1265}
1266impl<'a, I: InitMarker> BorrowMut<[MaybeUninit<u8>]> for IoSliceMut<'a, I> {
1267 #[inline]
1268 fn borrow_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1269 self.as_maybe_uninit_slice_mut()
1270 }
1271}
1272impl<'a> BorrowMut<[u8]> for IoSliceMut<'a, Init> {
1273 #[inline]
1274 fn borrow_mut(&mut self) -> &mut [u8] {
1275 self.as_slice_mut()
1276 }
1277}
1278impl<'a, I: InitMarker> DerefMut for IoSliceMut<'a, I> {
1279 #[inline]
1280 fn deref_mut(&mut self) -> &mut Self::Target {
1281 self.inner_data_mut()
1282 }
1283}
1284#[cfg(all(unix, feature = "libc"))]
1285impl<'a, I: InitMarker> From<IoSliceMut<'a, I>> for libc::iovec {
1286 #[inline]
1287 fn from(slice: IoSliceMut<'a, I>) -> Self {
1288 slice.as_raw_iovec()
1289 }
1290}
1291
1292impl<'a, I: InitMarker> fmt::Debug for IoSliceMut<'a, I> {
1293 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1294 if I::IS_INITIALIZED {
1295 write!(f, "{:?}", self.inner_data())
1296 } else {
1297 write!(
1298 f,
1299 "[possibly uninitialized mutable I/O slice at {:p}, len {} bytes]",
1300 self.as_maybe_uninit_slice().as_ptr(),
1301 self.as_maybe_uninit_slice().len()
1302 )
1303 }
1304 }
1305}
1306impl<'a> PartialEq for IoSliceMut<'a, Init> {
1307 #[inline]
1308 fn eq(&self, other: &Self) -> bool {
1309 self.as_slice() == other.as_slice()
1310 }
1311}
1312impl<'a> PartialEq<[u8]> for IoSliceMut<'a, Init> {
1313 #[inline]
1314 fn eq(&self, other: &[u8]) -> bool {
1315 self.as_slice() == other
1316 }
1317}
1318impl<'a, 'b> PartialEq<&'b [u8]> for IoSliceMut<'a, Init> {
1319 #[inline]
1320 fn eq(&self, other: &&'b [u8]) -> bool {
1321 self.as_slice() == *other
1322 }
1323}
1324impl<'a, 'b> PartialEq<IoSlice<'b, Init>> for IoSliceMut<'a, Init> {
1325 #[inline]
1326 fn eq(&self, other: &IoSlice<'b>) -> bool {
1327 self.as_slice() == other.as_slice()
1328 }
1329}
1330#[cfg(feature = "nightly")]
1331impl<'a, const N: usize> PartialEq<[u8; N]> for IoSliceMut<'a, Init> {
1332 #[inline]
1333 fn eq(&self, other: &[u8; N]) -> bool {
1334 self.as_slice() == &other[..]
1335 }
1336}
1337impl<'a> Eq for IoSliceMut<'a, Init> {}
1338
1339impl<'a> PartialOrd for IoSliceMut<'a, Init> {
1340 #[inline]
1341 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1342 Some(Ord::cmp(self, other))
1343 }
1344}
1345impl<'a> PartialOrd<[u8]> for IoSliceMut<'a, Init> {
1346 #[inline]
1347 fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
1348 PartialOrd::partial_cmp(self.as_slice(), other)
1349 }
1350}
1351impl<'a, 'b> PartialOrd<IoSlice<'b, Init>> for IoSliceMut<'a, Init> {
1352 #[inline]
1353 fn partial_cmp(&self, other: &IoSlice<'b, Init>) -> Option<core::cmp::Ordering> {
1354 PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
1355 }
1356}
1357#[cfg(feature = "nightly")]
1358impl<'a, const N: usize> PartialOrd<[u8; N]> for IoSliceMut<'a, Init> {
1359 #[inline]
1360 fn partial_cmp(&self, other: &[u8; N]) -> Option<core::cmp::Ordering> {
1361 PartialOrd::partial_cmp(self.as_slice(), other)
1362 }
1363}
1364impl<'a> Ord for IoSliceMut<'a, Init> {
1365 #[inline]
1366 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1367 Ord::cmp(self.as_slice(), other.as_slice())
1368 }
1369}
1370impl<'a> core::hash::Hash for IoSliceMut<'a, Init> {
1371 #[inline]
1372 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1373 state.write(self.as_slice())
1374 }
1375}
1376impl<'a, I: InitMarker> From<&'a mut [I::DerefTargetItem]> for IoSliceMut<'a, I> {
1377 #[inline]
1378 fn from(slice: &'a mut [I::DerefTargetItem]) -> Self {
1379 Self::from_inner_data(slice)
1380 }
1381}
1382impl<'a> From<&'a mut [u8]> for IoSliceMut<'a, Uninit> {
1383 #[inline]
1384 fn from(slice: &'a mut [u8]) -> Self {
1385 Self::new(slice)
1386 }
1387}
1388#[cfg(feature = "nightly")]
1389impl<'a, I: InitMarker, const N: usize> From<&'a mut [I::DerefTargetItem; N]>
1390 for IoSliceMut<'a, I>
1391{
1392 #[inline]
1393 fn from(slice: &'a mut [I::DerefTargetItem; N]) -> Self {
1394 Self::from_inner_data(slice)
1395 }
1396}
1397
1398#[cfg(feature = "stable_deref_trait")]
1399unsafe impl<'a> stable_deref_trait::StableDeref for IoSliceMut<'a> {}
1400
1401#[cfg(feature = "alloc")]
1402mod io_box {
1403 use super::*;
1404
1405 #[cfg(any(all(unix, feature = "libc"), all(windows, feature = "winapi")))]
1406 use alloc::alloc::dealloc as deallocate;
1407 use alloc::alloc::{alloc as allocate, alloc_zeroed as allocate_zeroed, Layout};
1408
1409 #[allow(unused_imports)]
1410 use alloc::{boxed::Box, vec::Vec};
1411
1412 #[repr(transparent)]
1418 pub struct IoBox<I: InitMarker = Init> {
1419 #[cfg(all(unix, feature = "libc"))]
1420 inner: libc::iovec,
1421
1422 #[cfg(all(windows, feature = "winapi"))]
1423 inner: WSABUF,
1424
1425 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1426 inner: Box<[I::DerefTargetItem]>,
1427
1428 _marker: PhantomData<I>,
1429 }
1430 #[derive(Debug)]
1435 pub struct AllocationError(Layout);
1436
1437 impl AllocationError {
1438 #[inline]
1440 pub fn layout(&self) -> &Layout {
1441 &self.0
1442 }
1443 }
1444
1445 impl fmt::Display for AllocationError {
1446 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1447 write!(
1448 f,
1449 "failed to allocate {} bytes on a {}-byte alignment for buffer",
1450 self.layout().size(),
1451 self.layout().align()
1452 )
1453 }
1454 }
1455
1456 #[cfg(feature = "std")]
1457 impl std::error::Error for AllocationError {}
1458
1459 impl<I: InitMarker> IoBox<I> {
1460 fn try_alloc_inner<J: InitMarker>(
1464 length: usize,
1465 zeroed: bool,
1466 ) -> Result<IoBox<J>, AllocationError> {
1467 let layout = Layout::from_size_align(
1468 core::mem::size_of::<u8>()
1469 .checked_mul(length)
1470 .expect("overflow when multiplying length with size of u8"),
1471 core::mem::align_of::<u8>(),
1472 )
1473 .expect("error when creating allocation layout");
1474
1475 #[cfg(all(windows, feature = "winapi"))]
1476 if length > u32::MAX as usize {
1477 panic!("IoBox (or any WSABUF-based I/O slice) cannot be larger in size than ULONG, which is 32 bits on Windows.");
1478 }
1479
1480 let pointer = match zeroed {
1481 false => unsafe { allocate(layout) },
1482 true => unsafe { allocate_zeroed(layout) },
1483 };
1484
1485 if pointer.is_null() {
1486 return Err(AllocationError(layout));
1487 }
1488
1489 Ok(unsafe { IoBox::__construct(pointer as *mut J::DerefTargetItem, length) })
1490 }
1491 #[inline]
1509 pub fn try_alloc_zeroed(length: usize) -> Result<Self, AllocationError> {
1510 Self::try_alloc_inner(length, true)
1511 }
1512
1513 #[inline]
1522 pub fn alloc_zeroed(length: usize) -> Self {
1523 match Self::try_alloc_zeroed(length) {
1524 Ok(boxed) => boxed,
1525 Err(AllocationError(layout)) => alloc::alloc::handle_alloc_error(layout),
1526 }
1527 }
1528
1529 #[inline]
1531 pub fn into_raw_parts(self) -> (*mut u8, usize) {
1532 let ptr = self.__ptr();
1533 let len = self.__len();
1534 core::mem::forget(self);
1535 (ptr as *mut u8, len)
1536 }
1537 #[inline]
1544 pub unsafe fn from_raw_parts(base: *mut I::DerefTargetItem, len: usize) -> Self {
1545 Self::__construct(base, len)
1546 }
1547 #[cfg(all(unix, feature = "libc"))]
1548 pub fn into_raw_iovec(self) -> libc::iovec {
1549 let iovec = self.inner;
1550 core::mem::forget(self);
1551 iovec
1552 }
1553 #[cfg(all(windows, feature = "winapi"))]
1554 pub fn into_raw_wsabuf(self) -> WSABUF {
1555 let wsabuf = self.inner;
1556 core::mem::forget(self);
1557 wsabuf
1558 }
1559
1560 #[inline]
1561 pub fn into_box(self) -> Box<[I::DerefTargetItem]> {
1562 let (ptr, len) = self.into_raw_parts();
1563
1564 unsafe {
1565 Box::from_raw(core::slice::from_raw_parts_mut(
1566 ptr as *mut I::DerefTargetItem,
1567 len,
1568 ))
1569 }
1570 }
1571 #[inline]
1572 pub fn as_ioslice(&self) -> IoSlice<I> {
1573 IoSlice::from_inner_data(self.inner_data())
1574 }
1575 #[inline]
1576 pub fn as_ioslice_mut(&mut self) -> IoSliceMut<I> {
1577 IoSliceMut::from_inner_data(self.inner_data_mut())
1578 }
1579 #[inline]
1580 pub fn inner_data(&self) -> &[I::DerefTargetItem] {
1581 unsafe {
1582 core::slice::from_raw_parts(self.__ptr() as *const I::DerefTargetItem, self.__len())
1583 }
1584 }
1585 #[inline]
1586 pub fn inner_data_mut(&mut self) -> &mut [I::DerefTargetItem] {
1587 unsafe {
1588 core::slice::from_raw_parts_mut(
1589 self.__ptr() as *mut I::DerefTargetItem,
1590 self.__len(),
1591 )
1592 }
1593 }
1594 #[inline]
1595 pub fn cast_to_ioslices(these: &[Self]) -> &[IoSlice<I>] {
1596 unsafe { crate::cast_slice_same_layout(these) }
1597 }
1598 #[inline]
1609 pub unsafe fn cast_to_ioslices_mut(these: &mut [Self]) -> &mut [IoSlice<I>] {
1610 crate::cast_slice_same_layout_mut(these)
1611 }
1612 #[inline]
1613 pub fn cast_to_mut_ioslices(these: &[Self]) -> &[IoSliceMut<I>] {
1614 unsafe { crate::cast_slice_same_layout(these) }
1615 }
1616 #[inline]
1625 pub unsafe fn cast_to_mut_ioslices_mut(these: &mut [Self]) -> &mut [IoSliceMut<I>] {
1626 crate::cast_slice_same_layout_mut(these)
1627 }
1628 #[inline]
1640 pub unsafe fn assume_init(self) -> IoBox<Init> {
1641 let (ptr, len) = self.into_raw_parts();
1642 IoBox::from_raw_parts(ptr, len)
1643 }
1644 #[inline]
1645 pub fn as_maybe_uninit_slice(&self) -> &[MaybeUninit<u8>] {
1646 unsafe { crate::cast_slice_same_layout(self.inner_data()) }
1647 }
1648 #[inline]
1649 pub fn as_maybe_uninit_slice_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1650 unsafe { crate::cast_slice_same_layout_mut(self.inner_data_mut()) }
1651 }
1652
1653 #[inline]
1654 pub fn into_uninit(self) -> IoBox<Uninit> {
1655 unsafe {
1656 let (ptr, len) = self.into_raw_parts();
1657 IoBox::from_raw_parts(ptr as *mut MaybeUninit<u8>, len)
1658 }
1659 }
1660
1661 #[inline]
1662 pub fn into_uninit_box(self) -> Box<[MaybeUninit<u8>]> {
1663 self.into_uninit().into_box()
1664 }
1665
1666 fn __ptr(&self) -> *mut I::DerefTargetItem {
1667 #[cfg(all(unix, feature = "libc"))]
1668 {
1669 self.inner.iov_base as *mut I::DerefTargetItem
1670 }
1671 #[cfg(all(windows, feature = "winapi"))]
1672 {
1673 self.inner.buf as *mut I::DerefTargetItem
1674 }
1675 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1676 {
1677 self.inner.as_ptr() as *mut I::DerefTargetItem
1678 }
1679 }
1680 #[inline]
1681 fn __len(&self) -> usize {
1682 #[cfg(all(unix, feature = "libc"))]
1683 {
1684 self.inner.iov_len as usize
1685 }
1686 #[cfg(all(windows, feature = "winapi"))]
1687 {
1688 self.inner.len as usize
1689 }
1690 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1691 {
1692 self.inner.len()
1693 }
1694 }
1695 #[inline]
1696 unsafe fn __construct(ptr: *mut I::DerefTargetItem, len: usize) -> Self {
1697 Self {
1698 #[cfg(all(unix, feature = "libc"))]
1699 inner: libc::iovec {
1700 iov_base: ptr as *mut libc::c_void,
1701 iov_len: len,
1702 },
1703 #[cfg(all(windows, feature = "winapi"))]
1704 inner: WSABUF {
1705 buf: ptr as *mut CHAR,
1706 len: len as ULONG,
1707 },
1708 #[cfg(not(any(all(unix, feature = "libc"), all(windows, feature = "winapi"))))]
1709 inner: Box::from_raw(core::slice::from_raw_parts_mut(ptr, len)),
1710
1711 _marker: PhantomData,
1712 }
1713 }
1714 }
1715 impl IoBox<Uninit> {
1716 #[inline]
1729 pub fn try_alloc_uninit(length: usize) -> Result<IoBox<Uninit>, AllocationError> {
1730 Self::try_alloc_inner(length, false)
1731 }
1732
1733 #[inline]
1740 pub fn alloc_uninit(length: usize) -> IoBox<Uninit> {
1741 match Self::try_alloc_uninit(length) {
1742 Ok(boxed) => boxed,
1743 Err(AllocationError(layout)) => alloc::alloc::handle_alloc_error(layout),
1744 }
1745 }
1746 }
1747 impl IoBox<Init> {
1748 #[inline]
1749 pub fn as_slice(&self) -> &[u8] {
1750 self.inner_data()
1751 }
1752 #[inline]
1753 pub fn as_slice_mut(&mut self) -> &mut [u8] {
1754 self.inner_data_mut()
1755 }
1756 }
1757 impl<I: InitMarker> Drop for IoBox<I> {
1758 fn drop(&mut self) {
1759 #[cfg(any(all(unix, feature = "libc"), all(windows, feature = "winapi")))]
1760 unsafe {
1761 deallocate(
1762 self.__ptr() as *mut u8,
1763 Layout::from_size_align(
1764 self.__len()
1765 .checked_mul(core::mem::size_of::<u8>())
1766 .expect("overflow on multiplication that should be a no-op"),
1767 core::mem::align_of::<u8>(),
1768 )
1769 .expect("failed to deallocate due to invalid layout"),
1770 );
1771 }
1772 }
1773 }
1774 impl<I: InitMarker> From<Box<[I::DerefTargetItem]>> for IoBox<I> {
1775 #[inline]
1776 fn from(boxed: Box<[I::DerefTargetItem]>) -> Self {
1777 unsafe {
1778 let slice_ptr = Box::into_raw(boxed);
1779
1780 let len = (&*slice_ptr).len();
1784 let base = (&*slice_ptr).as_ptr() as *mut I::DerefTargetItem;
1785
1786 Self::from_raw_parts(base, len)
1787 }
1788 }
1789 }
1790 impl From<Box<[u8]>> for IoBox<Uninit> {
1791 #[inline]
1792 fn from(boxed: Box<[u8]>) -> Self {
1793 unsafe {
1794 let slice_ptr = Box::into_raw(boxed);
1795
1796 let len = (&*slice_ptr).len();
1800 let base = (&*slice_ptr).as_ptr() as *mut MaybeUninit<u8>;
1801
1802 Self::from_raw_parts(base, len)
1803 }
1804 }
1805 }
1806 impl<I: InitMarker> From<Vec<I::DerefTargetItem>> for IoBox<I> {
1807 #[inline]
1808 fn from(vector: Vec<I::DerefTargetItem>) -> Self {
1809 Self::from(vector.into_boxed_slice())
1810 }
1811 }
1812 impl From<Vec<u8>> for IoBox<Uninit> {
1813 #[inline]
1814 fn from(vector: Vec<u8>) -> Self {
1815 Self::from(vector.into_boxed_slice())
1816 }
1817 }
1818 impl<I: InitMarker> From<IoBox<I>> for Box<[I::DerefTargetItem]> {
1819 #[inline]
1820 fn from(io_box: IoBox<I>) -> Self {
1821 io_box.into_box()
1822 }
1823 }
1824 impl From<IoBox<Init>> for Box<[MaybeUninit<u8>]> {
1825 #[inline]
1826 fn from(io_box: IoBox<Init>) -> Self {
1827 io_box.into_uninit_box()
1828 }
1829 }
1830 impl<I: InitMarker> From<IoBox<I>> for Vec<I::DerefTargetItem> {
1831 #[inline]
1832 fn from(io_box: IoBox<I>) -> Self {
1833 Self::from(Box::from(io_box))
1834 }
1835 }
1836 impl From<IoBox<Init>> for Vec<MaybeUninit<u8>> {
1837 #[inline]
1838 fn from(io_box: IoBox<Init>) -> Self {
1839 io_box.into_uninit_box().into()
1840 }
1841 }
1842 impl core::fmt::Debug for IoBox {
1843 #[inline]
1844 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1845 write!(f, "{:?}", self.as_slice())
1846 }
1847 }
1848 impl<I: InitMarker> Deref for IoBox<I> {
1849 type Target = [I::DerefTargetItem];
1850
1851 #[inline]
1852 fn deref(&self) -> &Self::Target {
1853 self.inner_data()
1854 }
1855 }
1856 impl<I: InitMarker> DerefMut for IoBox<I> {
1857 #[inline]
1858 fn deref_mut(&mut self) -> &mut Self::Target {
1859 self.inner_data_mut()
1860 }
1861 }
1862 impl<I: InitMarker> AsRef<[MaybeUninit<u8>]> for IoBox<I> {
1863 #[inline]
1864 fn as_ref(&self) -> &[MaybeUninit<u8>] {
1865 self.as_maybe_uninit_slice()
1866 }
1867 }
1868 impl<I: InitMarker> AsMut<[MaybeUninit<u8>]> for IoBox<I> {
1869 #[inline]
1870 fn as_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1871 self.as_maybe_uninit_slice_mut()
1872 }
1873 }
1874 impl AsRef<[u8]> for IoBox<Init> {
1875 #[inline]
1876 fn as_ref(&self) -> &[u8] {
1877 self.as_slice()
1878 }
1879 }
1880 impl AsMut<[u8]> for IoBox<Init> {
1881 #[inline]
1882 fn as_mut(&mut self) -> &mut [u8] {
1883 self.as_slice_mut()
1884 }
1885 }
1886 impl<I: InitMarker> core::borrow::Borrow<[MaybeUninit<u8>]> for IoBox<I> {
1887 #[inline]
1888 fn borrow(&self) -> &[MaybeUninit<u8>] {
1889 self.as_maybe_uninit_slice()
1890 }
1891 }
1892 impl<I: InitMarker> core::borrow::BorrowMut<[MaybeUninit<u8>]> for IoBox<I> {
1893 #[inline]
1894 fn borrow_mut(&mut self) -> &mut [MaybeUninit<u8>] {
1895 self.as_maybe_uninit_slice_mut()
1896 }
1897 }
1898 impl core::borrow::Borrow<[u8]> for IoBox<Init> {
1899 #[inline]
1900 fn borrow(&self) -> &[u8] {
1901 self.as_slice()
1902 }
1903 }
1904 impl core::borrow::BorrowMut<[u8]> for IoBox<Init> {
1905 #[inline]
1906 fn borrow_mut(&mut self) -> &mut [u8] {
1907 self.as_slice_mut()
1908 }
1909 }
1910 impl PartialEq for IoBox<Init> {
1911 #[inline]
1912 fn eq(&self, other: &Self) -> bool {
1913 self.as_slice() == other.as_slice()
1914 }
1915 }
1916 impl PartialEq<[u8]> for IoBox<Init> {
1917 #[inline]
1918 fn eq(&self, other: &[u8]) -> bool {
1919 self.as_slice() == other
1920 }
1921 }
1922 impl<'a> PartialEq<IoSlice<'a, Init>> for IoBox<Init> {
1923 #[inline]
1924 fn eq(&self, other: &IoSlice<Init>) -> bool {
1925 self.as_slice() == other.as_slice()
1926 }
1927 }
1928 impl<'a> PartialEq<IoSliceMut<'a, Init>> for IoBox<Init> {
1929 #[inline]
1930 fn eq(&self, other: &IoSliceMut<Init>) -> bool {
1931 self.as_slice() == other.as_slice()
1932 }
1933 }
1934 impl Eq for IoBox<Init> {}
1935 }
1937#[cfg(feature = "alloc")]
1938pub use io_box::*;
1939
1940pub trait CastSlice<'a, T>: Sized {
1946 fn cast_slice(selves: &'a [Self]) -> &'a [T];
1947}
1948pub trait CastSliceMut<'a, T>: CastSlice<'a, T> {
1953 fn cast_slice_mut(selves: &'a mut [Self]) -> &'a mut [T];
1954}
1955
1956impl<T> CastSlice<'_, T> for T {
1957 #[inline]
1958 fn cast_slice(selves: &[Self]) -> &[T] {
1959 selves
1960 }
1961}
1962impl<T> CastSliceMut<'_, T> for T {
1963 #[inline]
1964 fn cast_slice_mut(selves: &mut [Self]) -> &mut [T] {
1965 selves
1966 }
1967}
1968#[cfg(feature = "alloc")]
1969impl<'a, I: InitMarker> CastSlice<'a, IoSlice<'a, I>> for IoBox<I> {
1970 #[inline]
1971 fn cast_slice(selves: &'a [Self]) -> &'a [IoSlice<'a, I>] {
1972 IoBox::cast_to_ioslices(selves)
1973 }
1974}
1975#[cfg(feature = "alloc")]
1976impl<'a, I: InitMarker> CastSlice<'a, IoSliceMut<'a, I>> for IoBox<I> {
1977 #[inline]
1978 fn cast_slice(selves: &'a [Self]) -> &'a [IoSliceMut<'a, I>] {
1979 IoBox::cast_to_mut_ioslices(selves)
1980 }
1981}
1982
1983#[cfg(test)]
1984mod tests {
1985 use super::*;
1986
1987 const FIRST: &[u8] = b"this";
1988 const SECOND: &[u8] = b"is";
1989 const THIRD: &[u8] = b"FAL";
1990 const FOURTH: &[u8] = b"-rs";
1991 const SPACE: &[u8] = b" ";
1992
1993 #[test]
1994 fn advance() {
1995 let original_slices = [FIRST, SPACE, SECOND, SPACE, THIRD, FOURTH];
1996 let mut original_ioslices = original_slices
1997 .iter()
1998 .copied()
1999 .map(|slice| IoSlice::from(slice))
2000 .collect::<Vec<_>>();
2001
2002 let original_slices = &original_slices[..];
2003 let original_ioslices = &mut original_ioslices[..];
2004
2005 fn check_slices(ioslices: &[IoSlice], slice: &[&[u8]]) {
2006 assert!(ioslices
2007 .iter()
2008 .map(|ioslice| ioslice.as_slice())
2009 .eq(slice.iter().copied()));
2010 }
2011
2012 let mut ioslices = original_ioslices;
2013
2014 check_slices(ioslices, original_slices);
2015
2016 ioslices = IoSlice::advance_within(ioslices, 0).unwrap();
2017 check_slices(ioslices, &[b"this", b" ", b"is", b" ", b"FAL", b"-rs"]);
2018
2019 ioslices = IoSlice::advance_within(ioslices, 2).unwrap();
2020 check_slices(ioslices, &[b"is", b" ", b"is", b" ", b"FAL", b"-rs"]);
2021
2022 ioslices = IoSlice::advance_within(ioslices, 5).unwrap();
2023 check_slices(ioslices, &[b" ", b"FAL", b"-rs"]);
2024
2025 ioslices = IoSlice::advance_within(ioslices, 6).unwrap();
2026 check_slices(ioslices, &[b"s"]);
2027
2028 ioslices = IoSlice::advance_within(ioslices, 1).unwrap();
2029 check_slices(ioslices, &[]);
2030
2031 assert_eq!(IoSlice::advance_within(ioslices, 1), None);
2032 }
2033
2034 macro_rules! splitting_inner(
2035 ($slice:ident) => {{
2036 let mut buf: [u8; 13] = *b"Hello, world!";
2037
2038 let full = $slice::<Init>::new(&mut buf);
2039 let (first, remainder) = full.split_at(4);
2040 assert_eq!(&*first, b"Hell");
2041
2042 let (second, third) = remainder.split_at(5);
2043 assert_eq!(&*second, b"o, wo");
2044 assert_eq!(&*third, b"rld!");
2045 }}
2046 );
2047 #[test]
2048 fn splitting_ioslice() {
2049 splitting_inner!(IoSlice)
2050 }
2051 #[test]
2052 fn splitting_ioslice_mut() {
2053 splitting_inner!(IoSliceMut)
2054 }
2055
2056 #[test]
2057 #[cfg(all(windows, feature = "winapi"))]
2058 #[cfg_attr(target_pointer_width = "32", ignore)]
2059 #[should_panic = "IoBox (or any WSABUF-based I/O slice) cannot be larger in size than ULONG, which is 32 bits on Windows."]
2060 fn wsabuf_limit() {
2061 let _ = IoBox::try_alloc_uninit(u32::MAX as usize + 1);
2062 }
2063
2064 #[test]
2065 #[cfg(feature = "std")]
2066 fn abi_compatibility_with_std() {
2067 assert_eq!(
2068 std::mem::size_of::<IoSlice>(),
2069 std::mem::size_of::<std::io::IoSlice>()
2070 );
2071 assert_eq!(
2072 std::mem::align_of::<IoSlice>(),
2073 std::mem::align_of::<std::io::IoSlice>()
2074 );
2075
2076 let slices = [FIRST, SECOND, THIRD, FOURTH];
2077 let mut ioslices = [
2078 IoSlice::new(FIRST),
2079 IoSlice::new(SECOND),
2080 IoSlice::new(THIRD),
2081 IoSlice::new(FOURTH),
2082 ];
2083 let std_ioslices = IoSlice::cast_to_std_ioslices(&ioslices);
2084
2085 assert!(std_ioslices
2086 .iter()
2087 .map(|ioslice| ioslice.as_ref())
2088 .eq(slices.iter().copied()));
2089
2090 use std::io::prelude::*;
2091
2092 let mut buffer =
2093 vec![0u8; slices.iter().copied().map(<[u8]>::len).sum()].into_boxed_slice();
2094
2095 let mut total = 0;
2096
2097 let mut ioslices = &mut ioslices[..];
2098
2099 loop {
2100 let std_ioslices = IoSlice::cast_to_std_ioslices(&ioslices);
2101
2102 match (&mut *buffer).write_vectored(std_ioslices) {
2103 Ok(0) => break,
2104 Ok(n) => {
2105 ioslices = IoSlice::advance_within(ioslices, n).unwrap();
2106 total += n
2107 }
2108 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue,
2109 Err(error) => Err(error).unwrap(),
2110 }
2111 }
2112 assert_eq!(total, buffer.len());
2113 assert_eq!(&*buffer, b"thisisFAL-rs");
2114 }
2115 #[test]
2116 #[cfg(all(unix, feature = "libc"))]
2117 #[cfg_attr(miri, ignore)]
2118 fn abi_compatibility_with_iovec() {
2119 use std::convert::TryInto;
2120
2121 assert_eq!(
2122 std::mem::size_of::<IoSlice>(),
2123 std::mem::size_of::<libc::iovec>()
2124 );
2125 assert_eq!(
2126 std::mem::align_of::<IoSlice>(),
2127 std::mem::align_of::<libc::iovec>()
2128 );
2129
2130 unsafe {
2131 let slice: &[u8] = b"Hello, world!";
2132
2133 let iov_base = slice.as_ptr() as *mut libc::c_void;
2134 let iov_len = slice.len();
2135
2136 let vec = libc::iovec { iov_base, iov_len };
2137
2138 let wrapped: IoSlice = std::mem::transmute::<libc::iovec, IoSlice>(vec);
2139 assert_eq!(wrapped.as_ptr(), iov_base as *const u8);
2140 assert_eq!(wrapped.len(), iov_len);
2141 }
2142
2143 let ioslices = [
2144 IoSlice::new(FIRST),
2145 IoSlice::new(SPACE),
2146 IoSlice::new(SECOND),
2147 IoSlice::new(SPACE),
2148 IoSlice::new(THIRD),
2149 IoSlice::new(FOURTH),
2150 ];
2151 let iovecs = IoSlice::cast_to_raw_iovecs(&ioslices);
2152
2153 let mut fds = [0; 2];
2154
2155 unsafe {
2156 libc::pipe(fds.as_mut_ptr());
2157 }
2158 let [receiver_fd, sender_fd] = fds;
2159
2160 let mut buffer = vec![0u8; ioslices.iter().map(|slice| slice.len()).sum()];
2161 let buffer_parts = buffer
2162 .chunks_mut(4)
2163 .map(|slice| IoSliceMut::new(slice))
2164 .collect::<Vec<_>>();
2165 let buffer_parts_iovecs = IoSliceMut::cast_to_raw_iovecs(&*buffer_parts);
2166
2167 unsafe {
2168 let result = libc::writev(sender_fd, iovecs.as_ptr(), iovecs.len().try_into().unwrap());
2170
2171 if result == -1 {
2172 panic!("failed to writev: {}", std::io::Error::last_os_error());
2173 }
2174
2175 let result = libc::readv(
2176 receiver_fd,
2177 buffer_parts_iovecs.as_ptr(),
2178 buffer_parts_iovecs.len().try_into().unwrap(),
2179 );
2180
2181 if result == -1 {
2182 panic!("failed to readv: {}", std::io::Error::last_os_error());
2183 }
2184 }
2185 let src_iter = ioslices
2186 .iter()
2187 .flat_map(|ioslice| ioslice.as_slice())
2188 .copied();
2189 let dst_iter = buffer_parts
2190 .iter()
2191 .flat_map(|ioslice| ioslice.as_slice())
2192 .copied();
2193 assert!(Iterator::eq(src_iter, dst_iter));
2194 }
2195 }