# `uninit-read`
[](https://crates.io/crates/uninit-read)
[](https://docs.rs/uninit-read)

A marker trait and utilities for safe, high-performance reads into uninitialized buffers.
## The Problem
The standard I/O traits, `std::io::Read` and `futures::io::AsyncRead`, require a `&mut [u8]` buffer. By Rust's safety
rules, this slice must be fully initialized. In performance-critical applications, the cost of zeroing a large buffer
before a read can be significant.
The common workaround is to create an uninitialized buffer and `unsafe`ly cast it to `&mut [u8]`:
```rust
use std::mem::MaybeUninit;
let mut uninit_buf = MaybeUninit::<[u8; 8192] >::uninit();
// This is potentially UNDEFINED BEHAVIOR!
let buf_slice = unsafe { uninit_buf.assume_init_mut() };
// reader.read(buf_slice)?;
```
This is dangerous because the `Read` contract does not forbid the implementation from reading from the buffer before
writing to it. While most readers don't, the caller is relying on an unverified implementation detail.
## A Solution: `UninitRead`
This crate provides a single, `unsafe` marker trait that formalizes this contract:
```rust
pub unsafe trait UninitRead {}
```
By implementing `UninitRead` for a reader type, an author makes a **guarantee**:
> The reader implementation will not read from any part of the provided buffer that has not been written to *by the
implementation itself within the same call*. It must treat the buffer as if it were completely uninitialized on entry.
This contract makes it sound for callers to use an uninitialized buffer with any reader that implements `UninitRead`.
## Usage
### For Library Authors (Implementing `UninitRead`)
If your reader upholds the safety contract, you can implement the trait for it. This is an `unsafe impl` because you are
making a promise the compiler cannot check.
```rust
use std::io::{Read, Result};
use uninit_read::UninitRead;
pub struct MySafeReader<R>(R);
impl<R: Read> Read for MySafeReader<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
// This implementation only writes to `buf` and never reads from it.
self.0.read(buf)
}
}
// SAFETY: The `read` implementation for `MySafeReader` is well-behaved and
// only writes to the buffer, never reading from uninitialized portions.
unsafe impl<R: Read> UninitRead for MySafeReader<R> {}
```
### For Crate Users (Consuming `UninitRead`)
You can use the `UninitReadExt` traits (enabled by the `exts` feature) for ergonomic and safe reads into uninitialized
buffers.
```rust
use std::io::{Cursor, Result};
use std::mem::MaybeUninit;
use uninit_read::{UninitRead, UninitSyncReadExt};
// `Cursor<&[u8]>` has `UninitRead` implemented for it (with the `impls` feature).
let mut reader = Cursor::new([1, 2, 3, 4, 5]);
let mut buffer = [MaybeUninit::<u8>::uninit(); 10];
// read_uninit abstracts away the unsafe code and returns a slice to the
// initialized part of the buffer.
let initialized_part: & [u8] = reader.read_uninit( & mut buffer) ?;
assert_eq!(initialized_part, &[1, 2, 3, 4, 5]);
```
## Features
This crate uses feature flags to remain lightweight and dependency-free where possible.
- `default`: `["async", "futures-lite", "impls", "reflection", "exts", "assume-uninit-read"]`
- **`exts`**: (Enabled by default) Provides the [`UninitSyncReadExt`] and [`UninitAsyncReadExt`] extension traits for
ergonomic reads.
- **`impls`**: (Enabled by default) Provides `UninitRead` implementations for common standard library types like
`std::fs::File`, `std::net::TcpStream`, and `&[u8]`.
- **`async`**: Enables `futures-io` support. Required for all other async features.
- **`tokio`**: Provides `UninitRead` implementation for Tokio `Compat`.
- **`reflection`**: (Enabled by default) Enables the `is_uninit_read` function to check for the trait implementation at
runtime.
- **`assume-uninit-read`**: Enables the `AssumeUninitRead` wrapper type, which allows the caller to mark third-party
readers as
`UninitRead`-compliant when they are known to uphold the safety contract.
### For Library Authors
If you only need to implement the `UninitRead` trait and do not need any implementations or utilities, you can disable
all default features for a dependency-free build:
```toml
[dependencies]
uninit-read = { version = "0.1", default-features = false }
```
## License
This project is licensed under either of
- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.