Skip to content

Commit b8d27c0

Browse files
authored
Add UninitSlice::as_uninit_slice_mut() (#548)
This adds an unsafe method to convert a `&mut UninitSlice` into a `&mut [MaybeUninit<u8>]`. This method is unsafe because some of the bytes in the slice may be initialized, and the caller should not overwrite them with uninitialized bytes. This came about when auditing [tokio-util's udp frame], where they want to pass the unitialized portion of a `BytesMut` to [ReadBuf::uninit]. They need to do this unsafe pointer casting in a few places, which complicates audits. This method lets us document the safety invariants the caller needs to maintain when doing this conversion. [tokio-util's udp frame]: https://github.com/tokio-rs/tokio/blob/master/tokio-util/src/udp/frame.rs#L87 [ReadBuf::uninit]: https://docs.rs/tokio/latest/tokio/io/struct.ReadBuf.html#method.uninit
1 parent 0ce4fe3 commit b8d27c0

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

src/buf/uninit_slice.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,32 @@ impl UninitSlice {
124124
self.0.as_mut_ptr() as *mut _
125125
}
126126

127+
/// Return a `&mut [MaybeUninit<u8>]` to this slice's buffer.
128+
///
129+
/// # Safety
130+
///
131+
/// The caller **must not** read from the referenced memory and **must not** write
132+
/// **uninitialized** bytes to the slice either. This is because `BufMut` implementation
133+
/// that created the `UninitSlice` knows which parts are initialized. Writing uninitalized
134+
/// bytes to the slice may cause the `BufMut` to read those bytes and trigger undefined
135+
/// behavior.
136+
///
137+
/// # Examples
138+
///
139+
/// ```
140+
/// use bytes::BufMut;
141+
///
142+
/// let mut data = [0, 1, 2];
143+
/// let mut slice = &mut data[..];
144+
/// unsafe {
145+
/// let uninit_slice = BufMut::chunk_mut(&mut slice).as_uninit_slice_mut();
146+
/// };
147+
/// ```
148+
#[inline]
149+
pub unsafe fn as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>] {
150+
&mut *(self as *mut _ as *mut [MaybeUninit<u8>])
151+
}
152+
127153
/// Returns the number of bytes in the slice.
128154
///
129155
/// # Examples

0 commit comments

Comments
 (0)