Skip to main content

Buffer

Trait Buffer 

Source
pub unsafe trait Buffer<T>
where Self: Sized,
{ type Output; // Required methods fn buffer_ptr(&mut self) -> *mut T; fn buffer_len(&self) -> usize; unsafe fn assume_init(self, len: usize) -> Self::Output; // Provided method fn cursor(self) -> Cursor<T, Self> { ... } }
Expand description

A memory buffer that may be uninitialized.

When a function has a Buffer argument, the type of the argument determines the return type of the function:

If you pass a…You get back a…
&mut [T]usize, indicating the number of elements initialized.
&mut [MaybeUninit<T>](&mut [T], &mut [MaybeUninit<T>]), holding the initialized and uninitialized subslices.
SpareCapacityusize, indicating the number of elements initialized. And the Vec is extended.
&mut Cursor<T, B>usize, indicating the number of elements initialized. And the Cursor is advanced. Be sure to call Cursor::finish when you’re done writing to it.

§Safety

This trait is unsafe to implement because safe code, such as Cursor::write, trusts the values it returns and performs raw pointer writes into the buffer without further checks. Implementations must ensure all the following:

  • buffer_ptr returns a pointer that is non-null, properly aligned, and valid for writes of buffer_len consecutive elements of T.

  • buffer_len returns the length in elements of the region that buffer_ptr points to.

  • Unless the buffer is mutated through means outside of this trait, successive calls to buffer_ptr and buffer_len describe the same region, as callers such as Cursor call them repeatedly while tracking how many elements they have initialized.

  • Implementations do not read the contents of the buffer, which may be uninitialized. In particular, assume_init may assume only that the first len elements are initialized.

§Examples

Passing a &mut [T]:

let mut buf = [0_u8; 64];
let nread = read(fd, &mut buf)?;
// `nread` is the number of bytes read.

Passing a &mut [MaybeUninit<T>]:

let mut buf = [MaybeUninit::<u8>::uninit(); 64];
let (init, uninit) = read(fd, &mut buf)?;
// `init` is a `&mut [u8]` with the initialized bytes.
// `uninit` is a `&mut [MaybeUninit<u8>]` with the remaining bytes.

Passing a SpareCapacity, via the spare_capacity helper function:

let mut buf = Vec::with_capacity(64);
let nread = read(fd, spare_capacity(&mut buf))?;
// `nread` is the number of bytes read.
// Also, `buf.len()` is now `nread` elements longer than it was before.

Passing a &mut Cursor<T, B>:

let mut buf = [0_u8; 64];
let mut cursor = Cursor::new(&mut buf);
let _nread = read(fd, &mut cursor)?;
let _nread = read(fd, &mut cursor)?;
let _nread = read(fd, &mut cursor)?;
let total_nread = cursor.finish();
// `total_nread` is the total number of bytes read.

Accepting a Buffer argument, using unsafe:

pub fn read_into_buffer<B: Buffer<u8>>(mut b: B) -> B::Output {
    let ptr = b.buffer_ptr();
    let len = b.buffer_len();

    unsafe {
        // Some FFI call to do I/O.
        read_bytes(ptr, len);

        // Assume we just wrote `len` elements.
        b.assume_init(len)
    }
}

Accepting a Buffer argument, without using unsafe:

pub fn read_into_buffer<B: Buffer<u8>>(b: B) -> B::Output {
    let mut cursor = b.cursor();

    // Without `unsafe`, we can't do FFI I/O directly into the buffer, so
    // we use the `Cursor` type's API to write some data in. The advantage
    // of this approach is that we don't need an `unsafe` block in the
    // code here.
    let num = min(cursor.remaining(), 3);
    for i in 0..num {
        cursor.write(read_one_byte());
    }
    let more: Vec<u8> = read_some_more_bytes(cursor.remaining());
    cursor.write_slice(&more);

    cursor.finish()
}

§Guide to error messages

Sometimes code using Buffer can encounter non-obvious error messages. Here are some we’ve encountered, along with ways to fix them.

If you see errors like “cannot move out of self which is behind a mutable reference” and “move occurs because x has type &mut [u8], which does not implement the Copy trait”, replace x with &mut *x. See error_buffer_wrapper in examples/buffer_errors.rs.

If you see errors like “type annotations needed” and “cannot infer type of the type parameter Buf declared on the function read”, you may need to change a &mut [] to &mut [0_u8; 0]. See error_empty_slice in examples/buffer_errors.rs.

If you see errors like “the trait bound [MaybeUninit<u8>; 1]: Buffer<u8> is not satisfied”, add a &mut to pass the array by reference instead of by value. See error_array_by_value in examples/buffer_errors.rs.

If you see errors like “cannot move out of x, a captured variable in an FnMut closure”, try replacing x with &mut *x, or, if that doesn’t work, try moving a let into the closure body. See error_retry_closure and error_retry_indirect_closure in examples/buffer_errors.rs.

If you see errors like “captured variable cannot escape FnMut closure body”, use an explicit loop instead of retry_on_intr, assuming you’re using that. See error_retry_closure_uninit in examples/buffer_errors.rs.

Required Associated Types§

Source

type Output

The type of the value returned by functions with Buffer arguments.

Required Methods§

Source

fn buffer_ptr(&mut self) -> *mut T

Return a raw mutable pointer to the underlying buffer.

The returned pointer may be used to write data into the buffer, which requires use of unsafe. For an alternative safe API, see cursor.

After using this pointer to initialize some elements, call assume_init to declare how many were initialized.

Source

fn buffer_len(&self) -> usize

Return the length in elements of the underlying buffer.

Source

unsafe fn assume_init(self, len: usize) -> Self::Output

Assert that len elements were written to, and provide a return value.

§Safety

At least the first len elements of the buffer must be initialized.

Provided Methods§

Source

fn cursor(self) -> Cursor<T, Self>

Return a Cursor for safely writing to the buffer.

Calling finish on the cursor returns the Self::Output.

This is an alternative to buffer_ptr/assume_init which allows callers to avoid using unsafe.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<'a, T, const N: usize> Buffer<T> for &'a mut [MaybeUninit<T>; N]

Source§

type Output = (&'a mut [T], &'a mut [MaybeUninit<T>])

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<'a, T> Buffer<T> for &'a mut Box<[MaybeUninit<T>]>

Available on crate feature alloc only.
Source§

type Output = (&'a mut [T], &'a mut [MaybeUninit<T>])

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<'a, T> Buffer<T> for &'a mut Vec<MaybeUninit<T>>

Available on crate feature alloc only.
Source§

type Output = (&'a mut [T], &'a mut [MaybeUninit<T>])

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<'a, T> Buffer<T> for &'a mut [MaybeUninit<T>]

Source§

type Output = (&'a mut [T], &'a mut [MaybeUninit<T>])

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<'a> Buffer<u8> for &mut IoSliceMut<'a>

Available on crate feature std only.
Source§

type Output = usize

Source§

fn buffer_ptr(&mut self) -> *mut u8

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<T, const N: usize> Buffer<T> for &mut [T; N]

Source§

type Output = usize

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<T> Buffer<T> for &mut Box<[T]>

Available on crate feature alloc only.
Source§

type Output = usize

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<T> Buffer<T> for &mut Vec<T>

Available on crate feature alloc only.
Source§

type Output = usize

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Source§

impl<T> Buffer<T> for &mut [T]

Source§

type Output = usize

Source§

fn buffer_ptr(&mut self) -> *mut T

Source§

fn buffer_len(&self) -> usize

Source§

unsafe fn assume_init(self, len: usize) -> Self::Output

Implementors§

Source§

impl<'a, T> Buffer<T> for SpareCapacity<'a, T>

Available on crate feature alloc only.
Source§

impl<T, B: Buffer<T>> Buffer<T> for &mut Cursor<T, B>

Source§

impl<T, B: Buffer<T>> Buffer<T> for Cursor<T, B>

Source§

type Output = <B as Buffer<T>>::Output