Trait a10::io::BufMut

source ·
pub unsafe trait BufMut: 'static {
    // Required methods
    unsafe fn parts_mut(&mut self) -> (*mut u8, u32);
    unsafe fn set_init(&mut self, n: usize);
}
Expand description

Trait that defines the behaviour of buffers used in reading, which requires mutable access.

§Safety

Unlike normal buffers the buffer implementations for A10 have additional requirements.

If the operation (that uses this buffer) is not polled to completion, i.e. the Future is dropped before it returns Poll::Ready, the kernel still has access to the buffer and will still attempt to write into it. This means that we must delay deallocation in such a way that the kernel will not write into memory we don’t have access to any more. This makes, for example, stack based buffers unfit to implement BufMut. Because we can’t delay the deallocation once its dropped and the kernel will overwrite part of your stack (where the buffer used to be)!

Required Methods§

source

unsafe fn parts_mut(&mut self) -> (*mut u8, u32)

Returns the writable buffer as pointer and length parts.

§Safety

Only initialised bytes may be written to the pointer returned. The pointer may point to uninitialised bytes, so reading from the pointer is UB.

The implementation must ensure that the pointer is valid, i.e. not null and pointing to memory owned by the buffer. Furthermore it must ensure that the returned length is, in combination with the pointer, valid. In other words the memory the pointer and length are pointing to must be a valid memory address and owned by the buffer.

Note that the above requirements are only required for implementations outside of A10. This trait is unfit for external use!

§Why not a slice?

Returning a slice &[u8] would prevent us to use unitialised bytes, meaning we have to zero the buffer before usage, not ideal for performance. So, naturally you would suggest &[MaybeUninit<u8>], however that would prevent buffer types with only initialised bytes. Returning a slice with MaybeUninit to such as type would be unsound as it would allow the caller to write unitialised bytes without using unsafe.

§Notes

Most Rust API use a usize for length, but io_uring uses u32, hence we do also.

source

unsafe fn set_init(&mut self, n: usize)

Mark n bytes as initialised.

§Safety

The caller must ensure that n bytes, starting at the pointer returned by BufMut::parts_mut, are initialised.

Implementations on Foreign Types§

source§

impl BufMut for Vec<u8>

The implementation for Vec<u8> only uses the unused capacity, so any bytes already in the buffer will be untouched.

source§

unsafe fn parts_mut(&mut self) -> (*mut u8, u32)

source§

unsafe fn set_init(&mut self, n: usize)

Implementors§

source§

impl BufMut for ReadBuf

The implementation for ReadBuf is a special one as we don’t actually pass a “real” buffer. Instead we pass special flags to the kernel that allows it to select a buffer from the connected ReadBufPool once the actual read operation starts.

If the ReadBuf is used a second time in a read call this changes as at that point it owns an actual buffer. At that point it will behave more like the Vec<u8> implementation is that it only uses the unused capacity, so any bytes already in the buffer will be untouched.

To revert to the original behaviour of allowing the kernel to select a buffer call ReadBuf::release first.

Note that this can not be used in vectored I/O as a part of the ButMutSlice trait.