3 releases (breaking)
0.3.0 | Mar 2, 2023 |
---|---|
0.1.0 | Nov 2, 2022 |
0.0.0 | Nov 2, 2022 |
#2 in #possibly
Used in async-io-traits
24KB
335 lines
owned-buf
An owned buffer type for reading into possibly uninitialized memory. An owned equivalent of
BorrowedBuf
.
lib.rs
:
An owned, fixed length buffer of bytes (u8
s) and helper types.
The primary type is OwnedBuf
which is a sort-of abstract wrapper type for an owned
sequence of bytes. OwnedSlice
and OwnedCursor
give read access to the filled
part of an OwnedBuf
and write access to the unfilled part of an OwnedBuf
, respectively.
An OwnedBuf
is primarily useful where an IO operation takes ownership of supplied buffers, for
example async OwnedRead
.
An OwnedBuf
's data can be in either filled (i.e., data has been written to a byte) or unfilled.
Unfilled data may be with initialized or uninitialized. An OwnedBuf
may contain all three
kinds of data at the same time and tracks the state of bytes.
Lifecycle
An OwnedBuf
is never directly created. Instead, an existing sequence of bytes (e.g., a
Vec<u8>
) is transformed into an OwnedBuf
. Unlike when taking a slice, the previous sequence
type is consumed and ownership of its memory is transferred to the OwnedBuf
(the memory itself
does not move).
The OwnedBuf
is then used. It is transformed into an OwnedCursor
to write to it and into an
OwnedSlice
to read from it. These types can be transformed back into an OwnedBuf
as needed.
With each transformation, ownership is passed to the new type. If needed the OwnedBuf
can be
reset.
An OwnedBuf
can be transformed back into the original sequence type. Any data written to the
OwnedBuf
can be read. The sequence type can be used in the usual way, including its
destruction. If an OwnedBuf
is not transformed back into the previous type, then its destructor
calls a function supplied when the buffer is created. Typically, that converts the buffer into
the original sequence type and calls it destructor.
Destructor safety
An OwnedBuf
takes a destructor as a function pointer and calls it from the OwnedBuf
's
destructor. The function pointer is marked as unsafe
and the safety invariant is that the
OwnedBuf
was created from the collection type expected by the destructor function. This
invariant must be ensured when the OwnedBuf
is created, thus OwnedBuf::new
is unsafe
.
Conversion from user types
This module includes functionality to transform an OwnedBuf
from and to a Vec<u8>
or
Vec<MaybeUninit<u8>>
. OwnedBuf
is designed to be usable with any owned sequence of bytes. To
create an OwnedBuf
use OwnedBuf::new
, you'll supply a data pointer, some metadata, and a
destructor function (see below). To transform from an OwnedBuf
, you use into_raw_parts
to
get the internal state of the OwnedBuf
and then create the sequence type in the usual way.
An OwnedBuf
's destructor function has type &'static dyn Fn(&mut OwnedBuf<A>)
, it passes a
mutable reference to the destructor, however, it is guaranteed that the OwnedBuf
will not be
accessed after calling the destructor function. Typically, the destructor function will use
std::ptr::read
to get the OwnedBuf
by value, transform it into the original sequence type,
and (implicitly) call its destructor.
Fields
The fields of an OwnedBuf
are private and cannot be modified directly to help ensure safety
invariants. However, creating an OwnedBuf
using new
or calling into_raw_parts
exposes all
its fields. These fields are only intended to be used for implementing conversions from and to
other collection types, not for end users. We'll summarise the fields here rather than across
multiple functions.
data: *mut MaybeUninit<u8>
a pointer to the data in the bufferdtor: unsafe fn(&mut OwnedBuf)
a function pointer to the backing-buffer-dependent destructor functionuser_data: *const ()
a pointer to any data, intended to be used byself.dtor
capacity: usize
the total size of the bufferfilled: usize
the number of bytes in the buffer known to be filledinit: usize
the number of bytes in the buffer known to be initialized
Examples
Creating an OwnedBuf
from a Vec
.
let vec = vec![1u8, 2, 3];
let buf: OwnedBuf = vec.into();
// Use `filled` to view `buf` as an `OwnedSlice` to read from it.
assert_eq!(1, buf.filled()[0]);
// `Vec`'s destructor will be called via `OwnedBuf`'s.
Writing into an OwnedBuf
and converting it back into a Vec
.
let vec: Vec<u8> = Vec::with_capacity(8);
let buf: OwnedBuf = vec.into();
assert_eq!(0, buf.filled_len());
assert_eq!(8, buf.capacity());
// Get a cursor to write into the `OwnedBuf`.
let mut cursor = buf.unfilled();
cursor.write_slice(&[0, 1, 2, 3]);
// Convert the cursor back into an `OwnedBuf`.
let buf = cursor.into_buf();
assert_eq!(4, buf.filled_len());
let vec = unsafe { buf.into_vec() };
assert_eq!(4, vec.len());
assert_eq!(8, vec.capacity());
assert_eq!(3, vec[3]);