ByteBuffer

Struct ByteBuffer 

Source
#[repr(C)]
pub struct ByteBuffer { /* private fields */ }
Expand description

ByteBuffer is a struct that represents an array of bytes to be sent over the FFI boundaries. There are several cases when you might want to use this, but the primary one for us is for returning protobuf-encoded data to Swift and Java. The type is currently rather limited (implementing almost no functionality), however in the future it may be more expanded.

§Caveats

Note that the order of the fields is len (an i32) then data (a *mut u8), getting this wrong on the other side of the FFI will cause memory corruption and crashes. i32 is used for the length instead of u64 and usize because JNA has interop issues with both these types.

ByteBuffer does not implement Drop. This is intentional. Memory passed into it will be leaked if it is not explicitly destroyed by calling ByteBuffer::destroy. This is because in the future, we may allow it’s use for passing data into Rust code. ByteBuffer assuming ownership of the data would make this a problem.

§Layout/fields

This struct’s field are not pub (mostly so that we can soundly implement Send, but also so that we can verify Rust users are constructing them appropriately), the fields, their types, and their order are very much a part of the public API of this type. Consumers on the other side of the FFI will need to know its layout.

If this were a C struct, it would look like

struct ByteBuffer {
    int64_t len;
    uint8_t *data; // note: nullable
};

In Rust, there are two fields, in this order: len: i32, and data: *mut u8.

§Description of fields

data is a pointer to an array of len bytes. Not that data can be a null pointer and therefore should be checked.

The bytes array is allocated on the heap and must be freed on it as well. Critically, if there are multiple rust packages using being used in the same application, it must be freed on the same heap that allocated it, or you will corrupt both heaps.

Implementations§

Source§

impl ByteBuffer

Source

pub fn new_with_size(size: usize) -> Self

Creates a ByteBuffer of the requested size, zero-filled.

The contents of the vector will not be dropped. Instead, destroy must be called later to reclaim this memory or it will be leaked.

§Caveats

This will panic if the buffer length (usize) cannot fit into a i32.

Source

pub fn from_vec(bytes: Vec<u8>) -> Self

Creates a ByteBuffer instance from a Vec instance.

The contents of the vector will not be dropped. Instead, destroy must be called later to reclaim this memory or it will be leaked.

§Caveats

This will panic if the buffer length (usize) cannot fit into a i32.

Source

pub fn into_vec(self) -> Vec<u8>

Convert this ByteBuffer into a Vec. This is the only way to access the data from inside the buffer.

Source

pub fn destroy(self)

Reclaim memory stored in this ByteBuffer.

§Caveats

This is safe so long as the buffer is empty, or the data was allocated by Rust code, e.g. this is a ByteBuffer created by ByteBuffer::from_vec or Default::default.

If the ByteBuffer were passed into Rust (which you shouldn’t do, since theres no way to see the data in Rust currently), then calling destroy is fundamentally broken.

Trait Implementations§

Source§

impl Default for ByteBuffer

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl From<Vec<u8>> for ByteBuffer

Source§

fn from(bytes: Vec<u8>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> ErasedDestructor for T
where T: 'static,