uninit-read 0.1.1

A marker trait and utilities for safe, high-performance reads into uninitialized buffers.
Documentation
//! This module provides `UninitRead` implementations for common `Read` and `AsyncRead` types.

use crate::UninitRead;
use std::ops::{Deref, DerefMut};

unsafe impl<T: ?Sized + UninitRead + Unpin> UninitRead for Box<T> {}
unsafe impl<T: ?Sized + UninitRead + Unpin> UninitRead for &mut T {}
unsafe impl<T: UninitRead + DerefMut + Unpin> UninitRead for std::pin::Pin<T> where
    <T as Deref>::Target: UninitRead
{
}

pub mod std_io {
    use crate::UninitRead;
    use std::fs::File;
    use std::io::{Cursor, Empty, Read, Stdin};
    use std::net::TcpStream;
    unsafe impl UninitRead for File {}
    unsafe impl UninitRead for Stdin {}
    unsafe impl UninitRead for TcpStream {}
    unsafe impl UninitRead for Empty {}
    unsafe impl<T> UninitRead for Cursor<T> where Cursor<T>: Read {}

    //todo: more std impls

    #[cfg(unix)]
    pub mod unix {
        use crate::UninitRead;
        use std::os::unix::net::UnixStream;

        unsafe impl UninitRead for UnixStream {}
    }
}

#[cfg(feature = "async")]
pub mod async_impls {
    use crate::UninitRead;

    unsafe impl UninitRead for &[u8] {}
}

/// Implementations for `futures-lite` I/O types.
#[cfg(feature = "futures-lite")]
pub mod futures_lite {
    use crate::UninitRead;
    use futures_io::AsyncRead;
    use futures_lite::io::{BufReader, Bytes, Chain, Cursor, Empty, ReadHalf, Take};

    // Blanket implementations for common futures-lite I/O adapters.
    // Safety: These types delegate their `AsyncRead` implementation to an inner type,
    // so if the inner type is `UninitRead`, the wrapper is also `UninitRead`.

    unsafe impl<R> UninitRead for BufReader<R> where R: UninitRead {}

    unsafe impl<R> UninitRead for Bytes<R> where R: UninitRead {}

    unsafe impl<T> UninitRead for Cursor<T> where Cursor<T>: AsyncRead {}

    unsafe impl<R1, R2> UninitRead for Chain<R1, R2>
    where
        R1: UninitRead,
        R2: UninitRead,
    {
    }

    unsafe impl UninitRead for Empty {}

    unsafe impl<T: Unpin> UninitRead for ReadHalf<T> where T: UninitRead {}

    unsafe impl<R> UninitRead for Take<R> where R: UninitRead {}
}

/// Implementations for `async-fs` I/O types.
#[cfg(feature = "async-fs")]
pub mod async_fs {
    use crate::UninitRead;
    use async_fs::File;

    /// Safety: `async_fs::File` is known to not read from the buffer before writing.
    unsafe impl UninitRead for File {}
}

/// Implementations for `async-net` I/O types.
#[cfg(feature = "async-net")]
pub mod async_net {
    use crate::UninitRead;
    use async_net::TcpStream;

    /// Safety: `async_net::TcpStream` is known to not read from the buffer before writing.
    unsafe impl UninitRead for TcpStream {}

    #[cfg(unix)]
    pub mod unix {
        use crate::UninitRead;
        use async_net::unix::UnixStream;

        /// Safety: `async_net::unix::UnixStream` is known to not read from the buffer before writing.
        unsafe impl UninitRead for UnixStream {}
    }
}

/// Implementations for `tokio` compatibility types.
#[cfg(feature = "tokio")]
pub mod tokio {
    use crate::UninitRead;
    use tokio_util::compat::Compat;

    /// Safety: `tokio_util::compat::Compat<T>` delegates to an inner `tokio::io::AsyncRead`
    /// which is known to correctly handle uninitialized buffers via `ReadBuf`.
    unsafe impl<T: tokio::io::AsyncRead> UninitRead for Compat<T> where Compat<T>: futures_io::AsyncRead {}
}