ioslice/
iovec.rs

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} // pub mod init_marker
41use self::init_marker::*;
42
43/// A `#![no_std]`-friendly wrapper over the [`std::io::IoSliceMut`].
44///
45/// Internally, the struct will store the following based on crate features:
46///
47/// * `std` - wrapping [`std::io::IoSlice`] directly, with accessors for it as well as conversion
48///   functions and From impls.
49/// * `libc` (with `#[cfg(unix)]` - wrapping [`libc::iovec`] directly on platforms that support it.
50/// * `winapi` (with `#[cfg(windows)]`) - wrapping `WSABUF` directly.
51/// * (none) - wrapping a regular slice, that may not have the same ABI guarantees as the types
52///   from std or libc have.
53#[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
71// SAFETY: This is safe because whatever pointer that is sent to this slice must be Send in the
72// first place. Regular slices implement Send and Sync because of this.
73unsafe impl<'a, I: InitMarker> Send for IoSlice<'a, I> {}
74// SAFETY: Same as above.
75unsafe 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    /// Convert a regular slice into an I/O slice.
85    ///
86    /// The initializedness of the resulting I/O slice is dependent on the `I` generic parameter,
87    /// which by default is [`Init`]. Note that it is highly recommended not to call this
88    /// with [`Uninit`], since immutable slices cannot be made initialized, and one
89    /// therefore has to prove externally that the memory is in fact initialized before using it.
90    #[inline]
91    pub fn new(slice: &'a [u8]) -> Self {
92        unsafe { Self::__construct(slice.as_ptr(), slice.len()) }
93    }
94
95    /// Cast any I/O slice into an [`Uninit`] slice, forgetting about the original
96    /// initializedness.
97    #[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    /// Cast any slice of I/O slice into its uninitialized counterpart.
107    #[inline]
108    pub fn cast_to_uninit_slices(selves: &[Self]) -> &[IoSlice<'a, Uninit>] {
109        unsafe { crate::cast_slice_same_layout(selves) }
110    }
111    /// Cast any mutable slice of I/O slice into its uninitialized counterpart.
112    #[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    /// Turn any I/O slice into an [`Uninit`] slice, forgetting about the original
118    /// initializedness.
119    #[inline]
120    pub fn into_uninit(self) -> IoSlice<'a, Uninit> {
121        unsafe { IoSlice::__construct(self.__ptr(), self.__len()) }
122    }
123
124    /// Unsafely turn an I/O slice, being already [`Init`] or not, into an I/O slice that is [`Init`].
125    ///
126    /// # Safety
127    ///
128    /// For this to be safe, the initialization invariant must be upheld. Refer to the
129    /// [`std::mem::MaybeUninit`] docs.
130    #[inline]
131    pub unsafe fn assume_init(self) -> IoSlice<'a, Init> {
132        IoSlice::__construct(self.__ptr(), self.__len())
133    }
134
135    /// Wrap a system [`libc::iovec`] into a wrapped I/O slice, assuming the iovec can be
136    /// represented as borrowed for the lifetime `'a`. If the iovec is otherwise owned and
137    /// allocated via the system allocator, consider wrapping it in [`IoBox`] if the `alloc`
138    /// feature is used.
139    ///
140    /// _This is only available on Unix targets with the `libc` feature enabled_.
141    ///
142    /// # Safety
143    ///
144    /// This is unsafe because the slice must be valid (refer to libstd's section about pointer and
145    /// slice validity near [`std::ptr`]).
146    #[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    /// Wrap a system `WSABUF` into a wrapped I/O slice, assuming the buffer can be represented as
165    /// borrowed for the lifetime `'a`. Consider wrapping it in an [`IoBox`] if ownership of the
166    /// `WSABUF` is desired.
167    ///
168    /// # Safety
169    ///
170    /// For this to be safe, the slice must be _valid_ (refer to the [`std::ptr`] docs) and not
171    /// aliased mutably. If the generic parameter `I` is set to `Init`, the slice must also
172    /// contain initialized data.
173    #[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    /// Retrieve the inner iovec from this I/O slice.
182    ///
183    /// The raw iovec must be considered borrowed from this slice, even though it is not tracked
184    /// with a lifetime.
185    ///
186    /// _This is only available on Unix targets with the `libc` feature enabled_.
187    #[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    /// Retrieve the inner WSABUF from this I/O slice.
201    ///
202    /// The raw WSABUF must be considered borrowed from this slice, even though it is not
203    /// explicitly tracked using a lifetime.
204    ///
205    /// _This is only available on Windows targets with the `winapi` feature enabled._
206    #[cfg(all(windows, feature = "winapi"))]
207    #[inline]
208    pub fn as_raw_wsabuf(&self) -> WSABUF {
209        self.inner.0
210    }
211
212    /// Cast a slice of I/O slices into a slice of iovecs. Since these must share the same ABI
213    /// layout, this is completely safe, and can be directly passed to system calls.
214    ///
215    /// _This is only available on Unix targets with the `libc` feature enabled_.
216    #[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    /// Cast a slice of I/O slices into a slice of `WSABUF`s. Since these must share the same ABI
223    /// layout, this is completely safe, and the resulting slice can directly be passed to system
224    /// calls.
225    ///
226    /// _This is only available on Windows targets with the `winapi` feature enabled_.
227    #[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    /// Cast a mutable slice of I/O slices into a mutable slice of iovecs. iovecs share the exact
233    /// same ABI guarantees as this wrapper.
234    ///
235    /// _This is only available on Unix targets with the `libc` feature enabled_.
236    ///
237    /// # Safety
238    ///
239    /// This is unsafe, since the iovecs can be mutated, which will cause the original wrapped
240    /// slices to be changed as well. If the iovecs are changed to invalid values in any way, this
241    /// breaks the validity invariant upheld by this wrapped type, leading to UB.
242    #[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    /// Cast a mutable slice of I/O slices into a mutable slice of `WSABUF`s. Those share the exact
248    /// same ABI guarantees as this wrapper does.
249    ///
250    /// _This is only available on WIndows targets with the `winapi` feature enabled_.
251    ///
252    /// # Safety
253    ///
254    /// This is unsafe, since the `WSABUF`s can be mutated entirely in safe code, which will cause
255    /// the original wrapped slices to be changed as well. If the buffers are changed to invalid
256    /// values in any way, this breaks the validity invariant upheld by this wrapped type, leading
257    /// to UB.
258    #[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    // TODO: from_raw_{iovec,wsabuf}s{,_mut}
265
266    /// Advance the start offset of an I/O slice, effectively shrinking it from the start.
267    ///
268    /// # Panics
269    ///
270    /// This will panic if count is greater than the current length. On Windows, this will also
271    /// therefore instantly fail if count is greater than 2^32, since larger buffers cannot be
272    /// constructed.
273    #[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    /// Advance a range of slices by a specific offset, by advancing each slice individually until
285    /// the offset is reached.
286    ///
287    /// __Note that while this may modify the original slices in-place, the return value should
288    /// always be used, since the original value may contain old slices that were completely
289    /// skipped and never made empty__.
290    ///
291    /// This returns an Option rather than panicking when `n` is greater than the total length, to
292    /// reduce the need for counting, or blind reliance on system call correctness.
293    #[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    /// Get a slice to the "inner data" pointed to by this slice, which may be either `[u8]` or
315    /// `[MaybeUninit<u8>]`, depending on the `I` generic parameter. Prefer [`as_slice`] or
316    /// [`as_maybe_uninit_slice`] instead; this is only used to make various methods easier to
317    /// implement generically.
318    ///
319    /// [`as_slice`]: #method.as_slice
320    /// [`as_maybe_uninit_slice`]: #method.as_maybe_uninit_slice
321    #[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    /// Construct an I/O slice based on the inner data, which is either `[u8]` or `[MaybeUninit]`.
328    #[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    /// Retrieve a slice of possibly uninitialized data, but which is still always valid.
333    #[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    /// Retrieve an initialized byte slice from this I/O slice.
457    #[inline]
458    pub fn as_slice(&self) -> &'a [u8] {
459        self.inner_data()
460    }
461    /// Convert this slice into an initialized [`std::io::IoSlice`].
462    ///
463    /// _This is only available with the `std` feature enabled_.
464    #[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    /// Cast a slice of I/O slices, into a slice of libstd's [`std::io::IoSlice`]. This is safe
470    /// since they both must share the same ABI layout as [`libc::iovec`].
471    ///
472    /// _This is only available with the `std` feature enabled_.
473    #[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    /// Cast a mutable slice of I/O slices, into a mutable slice of libstd's [`std::io::IoSlice`].
479    /// This is safe since they both must share the same ABI layout as [`libc::iovec`], and since
480    /// libstd's I/O slices have the same validity invariant as this wrapper and slices in general.
481    ///
482    /// _This is only available with the `std` feature enabled_.
483    #[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/// A `#![no_std]`-friendly wrapper over the [`std::io::IoSliceMut`].
684///
685/// Internally, the struct will store the following based on crate features:
686///
687/// * `std` - wrapping [`std::io::IoSliceMut`] directly, with accessors for it as well as conversion
688///   functions and From impls.
689/// * `libc` (with `#[cfg(unix)]` - wrapping [`libc::iovec`] directly on platforms that support it,
690///   together with a marker making rustc think this stores a `&'a mut [u8]`.
691/// * (none) - wrapping a regular slice, that may not have the same ABI guarantees as the types
692///   from std or libc have.
693#[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}
706// SAFETY: Same as the safety section of impl Send for IoSlice.
707unsafe impl<'a, I: InitMarker> Send for IoSliceMut<'a, I> {}
708// SAFETY: Same as the safety section of impl Send for IoSlice.
709unsafe 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    /// Construct a new mutable I/O slice, from an existing initialized slice. The initializedness
719    /// is determined based on the generic parameter `I`, while the original slice obviously has to
720    /// be initialized since its type is [`u8`] and not [`MaybeUninit<u8>`].
721    #[inline]
722    pub fn new(slice: &'a mut [u8]) -> Self {
723        unsafe { Self::__construct(slice.as_mut_ptr(), slice.len()) }
724    }
725    /// Unsafely cast a possibly uninitialized slice into an initialized slice.
726    ///
727    /// __NOTE: THIS MUST NOT BE USED FOR INITIALIZATION; THAT IS DIRECT UB__
728    ///
729    /// # Safety
730    ///
731    /// For this to be safe, the initialization invariant must be upheld. Refer to the
732    /// [`std::mem::MaybeUninit`] docs.
733    #[inline]
734    pub unsafe fn assume_init(self) -> IoSliceMut<'a, Init> {
735        IoSliceMut::__construct(self.__ptr(), self.__len())
736    }
737
738    /// Unsafely cast a possibly uninitialized slice into an initialized slice, by reference.
739    ///
740    /// # Safety
741    ///
742    /// This must uphold the initialization invariant.
743    #[inline]
744    pub unsafe fn assume_init_ref(&self) -> &IoSliceMut<'a, Init> {
745        &*(self as *const Self as *const IoSliceMut<'a, Init>)
746    }
747    /// Unsafely cast a possibly uninitialized slice into an initialized slice, by mutable reference.
748    ///
749    /// # Safety
750    ///
751    /// This must uphold the initialization invariant.
752    #[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    /// Cast an I/O slice, being [`Init`] or not, into an [`Uninit`] I/O slice.
758    #[inline]
759    pub fn into_uninit(self) -> IoSliceMut<'a, Uninit> {
760        unsafe { IoSliceMut::__construct(self.__ptr(), self.__len()) }
761    }
762    /// Cast an I/O slice, being [`Init`] or not, into an [`Uninit`] I/O slice, by
763    /// reference.
764    #[inline]
765    pub fn as_uninit(&self) -> &IoSliceMut<'a, Uninit> {
766        unsafe { &*(self as *const Self as *const IoSliceMut<'a, Uninit>) }
767    }
768    /// Cast an I/O slice, being [`Init`] or not, into an [`Uninit`] I/O slice, by
769    /// mutable reference.
770    #[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    /// Cast any slice of I/O slice into its uninitialized counterpart.
776    #[inline]
777    pub fn cast_to_uninit_slices(selves: &[Self]) -> &[IoSliceMut<'a, Uninit>] {
778        unsafe { crate::cast_slice_same_layout(selves) }
779    }
780    /// Cast any mutable slice of I/O slice into its uninitialized counterpart.
781    ///
782    /// # Safety
783    ///
784    /// The returned slice must not be used to de-initialize any data.
785    #[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    /// Cast any slice of I/O slice into its uninitialized counterpart.
791    ///
792    /// # Safety
793    ///
794    /// The initialization invariant must be upheld.
795    #[inline]
796    pub unsafe fn cast_to_init_slices(selves: &[Self]) -> &[IoSliceMut<'a, Init>] {
797        crate::cast_slice_same_layout(selves)
798    }
799    /// Cast any mutable slice of I/O slice into its uninitialized counterpart.
800    ///
801    /// # Safety
802    ///
803    /// The initialization invariant must be upheld.
804    #[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    /// Wrap a system [`libc::iovec`] into this wrapper.
810    ///
811    /// _This is only available on Unix targets with the `libc` feature enabled_.
812    ///
813    /// # Safety
814    ///
815    /// For this to be safe, the validity invariant must be upheld, which takes things like size,
816    /// alignment, concurrent use, etc. in parallel. In short, the slice must be considered mutably
817    /// borrowed, and it must be safe to assume that it will not outlive the lifetime `'a`. Refer
818    /// to the [`std::ptr`] docs for more information regarding validity.
819    ///
820    /// Additionally, if the `I` generic parameter is [`Init`], the iovec must also point to
821    /// initialized data.
822    #[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    /// Wrap a system `WSABUF` into this wrapper.
831    ///
832    /// _This is only available on Windows targets with the `winapi` feature enabled._
833    #[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    /// Retrieve the wrapped raw [`libc::iovec ] from this wrapper.
842    ///
843    /// The resulting slice is considered immutable, even though it is neither UB nor more unsafe
844    /// than [`as_raw_iovecs_mut`]. This simply exists to prevent accidentally obtaining a
845    /// "mutable" [`libc::iovec`] where that is not possible (e.g. inside an [`std::sync::Arc`]).
846    ///
847    /// [`as_raw_iovecs_mut`]: #method.as_raw_iovecs_mut
848    #[cfg(all(unix, feature = "libc"))]
849    #[inline]
850    pub fn as_raw_iovec(&self) -> libc::iovec {
851        self.inner.0
852    }
853    /// Retrieve the wrapped raw [`libc::iovec ] from this wrapper, requiring exclusive access of
854    /// this slice, to obtain.
855    #[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    /// Cast a slice of wrapped I/O slices into a slice of [`libc::iovec`]s.
873    #[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    /// Cast a slice of wrapped I/O slices into a slice of `WSABUF`s.
879    #[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    /// Unsafely cast a mutable slice of wrapped I/O slices into a mutable slice of
885    /// [`libc::iovec`]s.
886    ///
887    /// # Safety
888    ///
889    /// This is unsafe because the initialization or validity invariants may be broken since the
890    /// iovecs can be changed arbitrarily in a mutable reference.
891    #[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    /// Unsafely cast a mutable slice of wrapped I/O slices into a mutable slice of
897    /// `WSABUF`s.
898    ///
899    /// # Safety
900    ///
901    /// This is unsafe because the initialization or validity invariants may be broken since the
902    /// WSABUFs can be changed arbitrarily in a mutable reference.
903    #[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    /// Unsafely cast a slice of [`libc::iovec`]s into a slice of [`IoSliceMut`].
910    ///
911    /// _This is only available on Unix platforms with the `libc` feature enabled._
912    ///
913    /// # Safety
914    ///
915    /// This is unsafe since the iovecs must uphold the validity and initialization invariants.
916    #[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    /// Unsafely cast a mutable slice of [`libc::iovec`]s into a mutable slice of [`IoSliceMut`].
922    ///
923    /// _This is only available on Unix platforms with the `libc` feature enabled._
924    ///
925    /// # Safety
926    ///
927    /// This is unsafe since the iovecs must uphold the validity and initialization invariants.
928    #[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    /// Unsafely cast a slice of `WSABUF`s into a slice of [`IoSliceMut`].
934    ///
935    /// _This is only available on Windows platforms with the `winapi` feature enabled._
936    ///
937    /// # Safety
938    ///
939    /// This is unsafe since the buffers must uphold the validity and initialization invariants.
940    #[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    /// Unsafely cast a mutable slice of `WSABUF`s into a mutable slice of [`IoSliceMut`].
946    ///
947    /// _This is only available on Windows platforms with the `winapi` feature enabled._
948    ///
949    /// # Safety
950    ///
951    /// This is unsafe since the buffers must uphold the validity and initialization invariants.
952    #[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    /// Advance the start offset of a single slice by `count` bytes, reducing the length as well.
958    ///
959    /// # Panics
960    ///
961    /// This will panic if `count` is greater than the current length.
962    #[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    /// Advance multiple slices by `n`, skipping and truncating slices until there are `n` less
974    /// total bytes.
975    ///
976    /// They are always advanced from start to end, and only the last slice will actually be
977    /// changed if the count turned out to be uneven. `None` is returned if `n` turns out to be
978    /// greater than the total length of the slices, so that counting beforehand becomes
979    /// unnecessary.
980    #[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    /// Retrieve the "inner data" immutably, pointed to by the I/O slice, being to either `&[u8]`
1003    /// or `&[MaybeUninit<u8>]` depending on the generic type parameter `I`.
1004    #[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    /// Retrieve the "inner data" mutably, pointed to by the I/O slice, being to either `&mut [u8]`
1011    /// or `&mut [MaybeUninit<u8>]` depending on the generic type parameter `I`.
1012    #[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    /// Get the "inner data" mutably, but with the lifetime `'a` rather than the lifetime of
1019    /// `self`.
1020    #[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    /// Convert a regular slice that points to either `u8` or `MaybeUninit<u8>`, into
1027    /// [`IoSliceMut`].
1028    #[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    /// Create an uninitialized mutable I/O slice from a regular uninitialized mutable byte slice.
1149    pub fn from_uninit(uninit: &'a mut [MaybeUninit<u8>]) -> Self {
1150        Self::from_inner_data(uninit)
1151    }
1152}
1153impl<'a> IoSliceMut<'a, Init> {
1154    /// Retrieve the inner slice immutably. This requires the I/O slice to be initialized.
1155    ///
1156    /// Unlike the immutable [`IoSlice`], this will require a secondary lifetime of `self`, to
1157    /// prevent aliasing when the data can be mutated. If it is necessary to obtain a byte slice
1158    /// with lifetime `'a`, use [`to_slice`].
1159    ///
1160    /// [`to_slice`]: #method.to_slice
1161    #[inline]
1162    pub fn as_slice(&self) -> &[u8] {
1163        unsafe { crate::cast_slice_same_layout(self.inner_data()) }
1164    }
1165    /// Take an [`IoSliceMut`] by value, turning it into an immutable byte slice of lifetime `'a`.
1166    #[inline]
1167    pub fn into_slice(self) -> &'a [u8] {
1168        &*self.into_slice_mut()
1169    }
1170
1171    /// Retrieve the inner slice mutably. This requires the I/O slice to be initialized.
1172    ///
1173    /// Note that unlike [`into_slice_mut`], this will have the lifetime of `self`, not `'a`.
1174    ///
1175    /// [`into_slice_mut`]: #method.into_slice_mut
1176    #[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    /// Take an [`IoSliceMut`] by value, turning it into a mutable byte slice of lifetime `'a`.
1182    #[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    // TODO: conversion by reference between std I/O slices
1188
1189    /// Cast `&[IoSliceMut]` to `&[std::io::IoSlice]`.
1190    #[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    /// Cast `&[IoSliceMut]` to `&[std::io::IoSliceMut]`.
1197    #[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    /// Cast `&mut [IoSliceMut]` to `&mut [std::io::IoSlice]`.
1203    #[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    /// Cast `&mut [IoSliceMut]` to `&mut [std::io::IoSliceMut]`.
1210    #[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}
1231// TODO: Use #![feature(specialization)] and make sure that there is always an AsRef and Borrow
1232// impl for MaybeUninit and u8 regardless of the generic parameter.
1233// TODO: What about #![feature(const_generics)] and use an exhaustive enum for the type markers?
1234impl<'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    /// An owned chunk of memory, that is ABI-compatible with [`libc::iovec`] or `WSABUF`,
1413    /// depending on the platform and Cargo features used.
1414    ///
1415    /// This must be allocated via the system alloc; importing pointers from _malloc(2)_ is
1416    /// currently not possible.
1417    #[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    /// An error that may occur if allocating an I/O box fails.
1431    ///
1432    /// This will most likely never occur on real operating systems, but being able to handle this
1433    /// error is crucial when working in resource-limited environments, or in e.g. OS kernels.
1434    #[derive(Debug)]
1435    pub struct AllocationError(Layout);
1436
1437    impl AllocationError {
1438        /// Retrieve the layout that the allocator failed to allocate.
1439        #[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        // TODO: While really niche (except maybe for O_DIRECT where buffers need to be
1461        // page-aligned?), one should also be able to directly specify a layout.
1462
1463        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        /// Attempt to allocate `length` bytes, which are initially set to zero.
1492        ///
1493        /// This allocation may fail, but should not be used unless the global allocator actually
1494        /// does return null when there is no memory. This is generally not the case for userspace
1495        /// processes, where the kernel gives more memory than physically available, but is
1496        /// obviously useful in `#![no_std]`.
1497        ///
1498        /// Since the allocator may be able to already have zeroed blocks of memory, this should be
1499        /// preferred over manually initializing it using [`zeroed`].
1500        ///
1501        /// # Panics
1502        ///
1503        /// This associated function will panic on Windows platforms when using the `winapi`
1504        /// feature, if the length exceeds the `WSABUF` limit of 2^32 bytes. Always check
1505        /// beforehand; this will never be returned as a regular allocation error.
1506        ///
1507        /// [`zeroed`]: #method.zeroed
1508        #[inline]
1509        pub fn try_alloc_zeroed(length: usize) -> Result<Self, AllocationError> {
1510            Self::try_alloc_inner(length, true)
1511        }
1512
1513        /// Allocate `length` bytes, which are initially set to zero.
1514        ///
1515        /// # Panics
1516        ///
1517        /// This associated function will, like most other heap-allocated structures in the `alloc`
1518        /// crate, panic when there is no available memory left. On Windows platforms with using
1519        /// the `winapi` feature, this will also panic if the length exceeds the `WSABUF` limit of
1520        /// 2^32 bytes.
1521        #[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        /// Turn the I/O box into the underlying pointer and size.
1530        #[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        /// Convert an underlying pointer and size, into an [`IoBox`].
1538        ///
1539        /// # Safety
1540        ///
1541        /// For this to be safe, the validity and initialization invariants must be held. In
1542        /// addition to that, the pointer must be allocated using the system allocator.
1543        #[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        /// Cast `&mut [IoBox]` to `&mut [IoSlice]`.
1599        ///
1600        /// # Safety
1601        ///
1602        /// To avoid being able to change the pointers, which are likely going to be deallocated in
1603        /// this `Drop` code, unless they are changed back, this is marked as "unsafe".
1604        ///
1605        /// Refer to [`cast_to_mut_ioslices_mut`].
1606        ///
1607        /// [`cast_to_mut_ioslices_mut`]: #method.cast_to_mut_ioslices_mut
1608        #[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        /// Cast `&mut [IoBox]` to `&mut [IoSliceMut]`.
1617        ///
1618        /// # Safety
1619        ///
1620        /// Since a mutable slice that mirrors these allows it to change the start offsets and
1621        /// advancing them in other ways (and even changing them to global variables etc.), this
1622        /// can cause the Drop code to cause UB. The caller must ensure that any pointers are
1623        /// changed back to what they were previously, before the drop code is run.
1624        #[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        /// Convert `IoBox<_>` into `IoBox<Init>`, assuming that the data is initialized.
1629        ///
1630        /// # Safety
1631        ///
1632        /// __This shall not be used for initializing data. In that case, initialize it manually
1633        /// via [`as_maybe_uninit_slice_mut`], and then call this.__
1634        ///
1635        /// While the validity invariant is already upheld when creating this type, the caller must
1636        /// ensure that the data be initialized. Refer to the [`std::mem::MaybeUninit`] docs.
1637        ///
1638        /// [`as_maybe_uninit_slice_mut`]: #method.as_maybe_uninit_slice_mut
1639        #[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        /// Attempt to allocate `length` bytes, returning either an uninitialized heap-allocated
1717        /// buffer, or an error if the allocator was unable to allocate that many bytes. Note that
1718        /// unless called in an `#![no_std]` environment, the OS will likely give more memory than
1719        /// physically present, so prefer [`alloc_uninit`] instead in that case.
1720        ///
1721        /// # Panics
1722        ///
1723        /// This associated function will panic on Windows platforms when using the `winapi`
1724        /// feature, if the length exceeds the `WSABUF` limit of 2^32 bytes. Always check
1725        /// beforehand; this will never be returned as a regular allocation error.
1726        ///
1727        /// [`alloc_uninit`]: #method.alloc_uninit
1728        #[inline]
1729        pub fn try_alloc_uninit(length: usize) -> Result<IoBox<Uninit>, AllocationError> {
1730            Self::try_alloc_inner(length, false)
1731        }
1732
1733        /// Allocate `length` uninitialized bytes.
1734        ///
1735        /// # Panics
1736        ///
1737        /// This associated function will panic if out of memory, or if the length is greater than
1738        /// 2^32 on Windows platforms.
1739        #[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                // TODO: #![feature(slice_ptr_len)]
1781                //let iov_len = slice_ptr.len();
1782
1783                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                // TODO: #![feature(slice_ptr_len)]
1797                //let iov_len = slice_ptr.len();
1798
1799                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    // TODO: more impls
1936}
1937#[cfg(feature = "alloc")]
1938pub use io_box::*;
1939
1940// TODO: Replace the million different methods for casting slices to and from system types of I/O
1941// vectors, with these traits.
1942
1943/// A trait for casting slices of different types to and from each other, provided that they have
1944/// the same memory layout.
1945pub trait CastSlice<'a, T>: Sized {
1946    fn cast_slice(selves: &'a [Self]) -> &'a [T];
1947}
1948/// A trait for casting slices of different types to and from each other, mutably, provided that
1949/// they have the same memory layout.
1950///
1951/// Any modifications to the target type must not be able to violate invariants of the source type.
1952pub 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            // TODO: Maybe repeat since writev and readv don't have to return everything?
2169            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    // TODO: Fix test.
2196    /*
2197    #[test]
2198    #[cfg(all(feature = "std"))]
2199    fn iobox() {
2200        use uninit_tools::initializer::BufferInitializer;
2201        use std::io::Write;
2202
2203        let iobox = IoBox::alloc_uninit(1024);
2204        let initialized = BufferInitializer::uninit(iobox).finish_init_by_filling(0xFF).into();
2205
2206        let iobox2 = IoBox::alloc_zeroed(2048);
2207
2208        let boxes = [initialized, iobox2];
2209
2210        let io_slices = IoBox::cast_to_ioslices(&boxes);
2211        let io_slices = IoSlice::cast_to_std_ioslices(io_slices);
2212
2213        // NOTE: This test currently depends on the fact that the Write impl for slices, never
2214        // only writes part of the buffers.
2215        let mut original_buf = [0u8; 1024 + 2048];
2216        let mut buf = &mut original_buf[..];
2217        buf.write_vectored(io_slices).unwrap();
2218
2219        assert!(original_buf[..1024]
2220            .iter()
2221            .copied()
2222            .eq(std::iter::repeat(0xFF).take(1024)));
2223        assert!(original_buf[1024..1024 + 2048]
2224            .iter()
2225            .copied()
2226            .eq(std::iter::repeat(0x00).take(2048)));
2227
2228        // TODO: Test more things.
2229    }
2230    */
2231    // TODO: Make IoSlice compatible with WSABUF without std as well.
2232}