diff options
author | 2022-05-10 05:22:19 -0400 | |
---|---|---|
committer | 2022-05-10 11:22:19 +0200 | |
commit | b8d27c016f53f0c1fea920223bc5a92f329d47df (patch) | |
tree | 805fc151dddb71d191a41e4baa52a2fd99e80508 | |
parent | 0ce4fe3c91f0d008674869348ffd804b78846eca (diff) | |
download | bytes-b8d27c016f53f0c1fea920223bc5a92f329d47df.tar.gz bytes-b8d27c016f53f0c1fea920223bc5a92f329d47df.tar.zst bytes-b8d27c016f53f0c1fea920223bc5a92f329d47df.zip |
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
-rw-r--r-- | src/buf/uninit_slice.rs | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/buf/uninit_slice.rs b/src/buf/uninit_slice.rs index fb67c0a..a6c9ead 100644 --- a/src/buf/uninit_slice.rs +++ b/src/buf/uninit_slice.rs @@ -124,6 +124,32 @@ impl UninitSlice { self.0.as_mut_ptr() as *mut _ } + /// Return a `&mut [MaybeUninit<u8>]` to this slice's buffer. + /// + /// # Safety + /// + /// The caller **must not** read from the referenced memory and **must not** write + /// **uninitialized** bytes to the slice either. This is because `BufMut` implementation + /// that created the `UninitSlice` knows which parts are initialized. Writing uninitalized + /// bytes to the slice may cause the `BufMut` to read those bytes and trigger undefined + /// behavior. + /// + /// # Examples + /// + /// ``` + /// use bytes::BufMut; + /// + /// let mut data = [0, 1, 2]; + /// let mut slice = &mut data[..]; + /// unsafe { + /// let uninit_slice = BufMut::chunk_mut(&mut slice).as_uninit_slice_mut(); + /// }; + /// ``` + #[inline] + pub unsafe fn as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>] { + &mut *(self as *mut _ as *mut [MaybeUninit<u8>]) + } + /// Returns the number of bytes in the slice. /// /// # Examples |