1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! 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`.
pub use UninitAsyncReadExt;
pub use UninitSyncReadExt;
pub use AssumeUninitRead;
pub use is_uninit_read;
/// A marker trait for readers that are safe to use with uninitialized buffers.
///
/// The standard I/O traits, [`std::io::Read`] and [`futures::io::AsyncRead`],
/// pass a `&mut [u8]` buffer to their read methods. Rust's safety rules require
/// that any `&mut [u8]` be fully initialized. This forces users to zero-out
/// buffers before passing them to a read function, which can be a performance
/// penalty in hot code paths or high-performance workloads.
///
/// This trait provides a formal contract to address this. By implementing
/// `UninitRead`, a type guarantees that its I/O methods will not read from the
/// provided buffer before writing to it, making it safe for callers to pass a
/// buffer that contains uninitialized memory.
///
/// # Safety
///
/// This trait is `unsafe` because the compiler cannot verify the guarantee it
/// provides. The implementor of this trait **must guarantee** that their
/// implementation of `Read::read()` and/or `AsyncRead::poll_read()` will not
/// read from any part of the provided buffer that has not been written to
/// by the implementation itself.
///
/// The implementation must treat the buffer as if it were completely
/// uninitialized at the start of the call. It is permissible to read from
/// portions of the buffer that have been written to *within the same call*
/// to a read method (e.g., for an in-place decryption routine).
///
/// Violating this contract by reading from a part of the buffer that has not
/// yet been written to will result in undefined behavior when a consumer of
/// this trait passes an uninitialized buffer.
pub unsafe