Skip to content

Commit

Permalink
Implement BufMut for &mut [MaybeUninit<u8>]
Browse files Browse the repository at this point in the history
This will allow using BufMut without having to initialise memory
first.  In particular, this will allow simple integration with tokio:

    #![feature(maybe_uninit_slice)]

    use tokio::io::AsyncSeekExt;

    let mut tokio_file = /* ... */;
    let mut buf = [MaybeUninit::uninit(); 4096];
    let len = tokio_file.read_buf(&mut buf);
    // SAFETY: read above initialised first len bytes of the buffer.
    let buf = unsafe {
        MaybeUninit::slice_assume_init_mut(&buf[..len])
    };
  • Loading branch information
mina86 committed Feb 9, 2023
1 parent 74b04c7 commit e0b4e8c
Showing 1 changed file with 35 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/buf/buf_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,41 @@ unsafe impl BufMut for &mut [u8] {
}
}

unsafe impl BufMut for &mut [core::mem::MaybeUninit<u8>] {
#[inline]
fn remaining_mut(&self) -> usize {
self.len()
}

#[inline]
fn chunk_mut(&mut self) -> &mut UninitSlice {
UninitSlice::from_slice(self)
}

#[inline]
unsafe fn advance_mut(&mut self, cnt: usize) {
// Lifetime dance taken from `impl Write for &mut [u8]`.
let (_, b) = core::mem::replace(self, &mut []).split_at_mut(cnt);
*self = b;
}

#[inline]
fn put_slice(&mut self, src: &[u8]) {
self.chunk_mut().copy_from_slice(src);
unsafe {
self.advance_mut(src.len());
}
}

fn put_bytes(&mut self, val: u8, cnt: usize) {
assert!(self.remaining_mut() >= cnt);
unsafe {
ptr::write_bytes(self.as_mut_ptr() as *mut u8, val, cnt);
self.advance_mut(cnt);
}
}
}

unsafe impl BufMut for Vec<u8> {
#[inline]
fn remaining_mut(&self) -> usize {
Expand Down

0 comments on commit e0b4e8c

Please sign in to comment.