Struct uniffi::RustBuffer
#[repr(C)]pub struct RustBuffer {
capacity: u64,
len: u64,
data: *mut u8,
}
Expand description
Support for passing an allocated-by-Rust buffer of bytes over the FFI.
We can pass a Vec<u8>
to foreign language code by decomposing it into
its raw parts (buffer pointer, length, and capacity) and passing those
around as a struct. Naturally, this can be tremendously unsafe! So here
are the details:
-
RustBuffer
structs must only ever be constructed from aVec<u8>
, either explicitly viaRustBuffer::from_vec
or indirectly by calling one of theRustBuffer::new*
constructors. -
RustBuffer
structs do not implementDrop
, since they are intended to be passed to foreign-language code outside of the control of Rust’s ownership system. To avoid memory leaks they must passed back into Rust and either explicitly destroyed usingRustBuffer::destroy
, or converted back to aVec<u8>
usingRustBuffer::destroy_into_vec
(which will then be dropped via Rust’s usual ownership-tracking system).
Foreign-language code should not construct RustBuffer
structs other than
by receiving them from a call into the Rust code, and should not modify them
apart from the following safe operations:
-
Writing bytes into the buffer pointed to by
data
, without writing beyond the indicatedcapacity
. -
Adjusting the
len
property to indicate the amount of data written, while ensuring that 0 <=len
<=capacity
. -
As a special case, constructing a
RustBuffer
with zero capacity, zero length, and a nulldata
pointer to indicate an empty buffer.
In particular, it is not safe for foreign-language code to construct a RustBuffer
that points to its own allocated memory; use the ForeignBytes
struct to
pass a view of foreign-owned memory in to Rust code.
Implementation note: all the fields of this struct are private, so you can’t
manually construct instances that don’t come from a Vec<u8>
. If you’ve got
a RustBuffer
then it either came from a public constructor (all of which
are safe) or it came from foreign-language code (which should have in turn
received it by calling some Rust function, and should be respecting the
invariants listed above).
This struct is based on ByteBuffer
from the ffi-support
crate, but modified
to retain unallocated capacity rather than truncating to the occupied length.
Fields§
§capacity: u64
§len: u64
§data: *mut u8
Implementations§
§impl RustBuffer
impl RustBuffer
pub fn new() -> RustBuffer
pub fn new() -> RustBuffer
Creates an empty RustBuffer
.
The buffer will not allocate.
The resulting vector will not be automatically dropped; you must
arrange to call destroy
or destroy_into_vec
when finished with it.
pub unsafe fn from_raw_parts(
data: *mut u8,
len: u64,
capacity: u64
) -> RustBuffer
pub unsafe fn from_raw_parts( data: *mut u8, len: u64, capacity: u64 ) -> RustBuffer
Creates a RustBuffer
from its constituent fields.
This is intended mainly as an internal convenience function and should not be used outside of this module.
Safety
You must ensure that the raw parts uphold the documented invariants of this class.
pub fn len(&self) -> usize
pub fn len(&self) -> usize
Get the current length of the buffer, as a usize
.
This is mostly a helper function to convert the i32
length field
into a usize
, which is what Rust code usually expects.
Panics
Panics if called on an invalid struct obtained from foreign-language code,
in which the len
field is negative.
pub fn data_pointer(&self) -> *const u8
pub fn data_pointer(&self) -> *const u8
Get a pointer to the data
pub fn new_with_size(size: u64) -> RustBuffer
pub fn new_with_size(size: u64) -> RustBuffer
Creates a RustBuffer
zero-filed to the requested size.
The resulting vector will not be automatically dropped; you must
arrange to call destroy
or destroy_into_vec
when finished with it.
Panics
Panics if the requested size is too large to fit in an i32
, and
hence would risk incompatibility with some foreign-language code.
pub fn from_vec(v: Vec<u8, Global>) -> RustBuffer
pub fn from_vec(v: Vec<u8, Global>) -> RustBuffer
Consumes a Vec<u8>
and returns its raw parts as a RustBuffer
.
The resulting vector will not be automatically dropped; you must
arrange to call destroy
or destroy_into_vec
when finished with it.
Panics
Panics if the vector’s length or capacity are too large to fit in an i32
,
and hence would risk incompatibility with some foreign-language code.
pub fn destroy_into_vec(self) -> Vec<u8, Global>
pub fn destroy_into_vec(self) -> Vec<u8, Global>
Converts this RustBuffer
back into an owned Vec<u8>
.
This restores ownership of the underlying buffer to Rust, meaning it will
be dropped when the Vec<u8>
is dropped. The RustBuffer
must have been
previously obtained from a valid Vec<u8>
owned by this Rust code.
Panics
Panics if called on an invalid struct obtained from foreign-language code,
which does not respect the invairiants on len
and capacity
.