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§
sourceunsafe fn parts_mut(&mut self) -> (*mut u8, u32)
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.
sourceunsafe fn set_init(&mut self, n: usize)
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>
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.
Implementors§
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.