[−][src]Trait uniffi::ViaFfi
Trait defining how to transfer values via the FFI layer.
The ViaFfi
trait defines how to pass values of a particular type back-and-forth over
the uniffi generated FFI layer, both as standalone argument or return values, and as
part of serialized compound data structures.
(This trait is Like the InfoFfi
trait from ffi_support
, but local to this crate
so that we can add some alternative implementations for different builtin types,
and so that we can add support for receiving as well as returning).
Safety
This is an unsafe trait (implementing it requires unsafe impl
) because we can't guarantee
that it's safe to pass your type out to foreign-language code and back again. Buggy
implementations of this trait might violate some assumptions made by the generated code,
or might not match with the corresponding code in the generated foreign-language bindings.
In general, you should not need to implement this trait by hand, and should instead rely on
implementations generated from your component IDL via the uniffi-bindgen scaffolding
command.
Associated Types
type FfiType
The low-level type used for passing values of this type over the FFI.
This must be a C-compatible type (e.g. a numeric primitive, a #[repr(C)]
struct) into
which values of the target rust type can be converted.
For complex data types, we currently recommend using ffi_support::ByteBuffer
and
serializing the data for transfer. In theory it could be possible to build a matching
#[repr(C)]
struct for a complex data type and pass that instead, but explicit
serialization is simpler and safer as a starting point.
Required methods
fn lower(self) -> Self::FfiType
Lower a rust value of the target type, into an FFI value of type Self::FfiType.
This trait method is used for sending data from rust to the foreign language code, by (hopefully cheaply!) converting it into someting that can be passed over the FFI and reconstructed on the other side.
Note that this method takes an owned self
; this allows it to transfer ownership
in turn to the foreign language code, e.g. by boxing the value and passing a pointer.
fn try_lift(v: Self::FfiType) -> Result<Self>
Lift a rust value of the target type, from an FFI value of type Self::FfiType.
This trait method is used for receiving data from the foreign language code in rust, by (hopefully cheaply!) converting it from a low-level FFI value of type Self::FfiType into a high-level rust value of the target type.
Since we cannot statically guarantee that the foreign-language code will send valid values of type Self::FfiType, this method is fallible.
fn write<B: BufMut>(&self, buf: &mut B)
Write a rust value into a bytebuffer, to send over the FFI in serialized form.
This trait method can be used for sending data from rust to the foreign language code, in cases where we're not able to use a special-purpose FFI type and must fall back to sending serialized bytes.
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
Read a rust value from a bytebuffer, received over the FFI in serialized form.
This trait method can be used for receiving data from the foreign language code in rust, in cases where we're not able to use a special-purpose FFI type and must fall back to receiving serialized bytes.
Since we cannot statically guarantee that the foreign-language code will send valid serialized bytes for the target type, this method is fallible.
Implementations on Foreign Types
impl ViaFfi for i8
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for u8
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for i16
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for u16
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for i32
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for u32
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for i64
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for u64
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for f32
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for f64
[src]
type FfiType = Self
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for bool
[src]
Support for passing boolean values via the FFI.
Booleans are passed as a u8
in order to avoid problems with handling
C-compatible boolean values on JVM-based languages.
type FfiType = u8
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl<T: ViaFfi> ViaFfi for Option<T>
[src]
Support for passing optional values via the FFI.
Optional values are currently always passed by serializing to a bytebuffer.
We write either a zero byte for None
, or a one byte followed by the containing
item for Some
.
In future we could do the same optimization as rust uses internally, where the
None
option is represented as a null pointer and the Some
as a valid pointer,
but that seems more fiddly and less safe in the short term, so it can wait.
type FfiType = ByteBuffer
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl<T: ViaFfi> ViaFfi for Vec<T>
[src]
Support for passing vectors of values via the FFI.
Vectors are currently always passed by serializing to a bytebuffer.
We write a u32
item count followed by each item in turn.
You can imagine a world where we pass some sort of (pointer, count) pair but that seems tremendously fiddly and unsafe in the short term. Maybe one day...
type FfiType = ByteBuffer
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl<V: ViaFfi> ViaFfi for HashMap<String, V>
[src]
Support for associative arrays via the FFI. Note that because of webidl limitations, the key must always be of the String type.
HashMaps are currently always passed by serializing to a bytebuffer.
We write a u32
entries count
followed by each entry (string key followed by the value) in turn.
type FfiType = ByteBuffer
fn lower(self) -> Self::FfiType
[src]
fn try_lift(v: Self::FfiType) -> Result<Self>
[src]
fn write<B: BufMut>(&self, buf: &mut B)
[src]
fn try_read<B: Buf>(buf: &mut B) -> Result<Self>
[src]
impl ViaFfi for String
[src]
Support for passing Strings via the FFI.
Unlike many other implementations of ViaFfi
, this passes a pointer rather
than copying the data from one side to the other. This is a safety hazard,
but turns out to be pretty nice for useability. This pointer *must be one owned
by the rust allocator and it must point to valid utf-8 data (in other words,
it must be an actual rust String
).
When serialized in a bytebuffer, strings are represented as a u32 byte length followed by utf8-encoded bytes.
(In practice, we currently do end up copying the data, the copying just happens on the foreign language side rather than here in the rust code.)