Trait uniffi::FfiConverter
pub unsafe trait FfiConverter<UT>: Sized {
type FfiType: FfiDefault;
const TYPE_ID_META: MetadataBuffer;
// Required methods
fn lower(obj: Self) -> Self::FfiType;
fn try_lift(v: Self::FfiType) -> Result<Self, Error>;
fn write(obj: Self, buf: &mut Vec<u8, Global>);
fn try_read(buf: &mut &[u8]) -> Result<Self, Error>;
}
Expand description
Generalized FFI conversions
This trait is not used directly by the code generation, but implement this and calling [derive_ffi_traits] is a simple way to implement all the traits that are.
Safety
All traits are unsafe (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.
These traits should not be used directly, only in generated code, and the generated code should
have fixture tests to test that everything works correctly together.
Required Associated Types§
type FfiType: FfiDefault
type FfiType: FfiDefault
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 RustBuffer
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.
If a type implements multiple FFI traits, FfiType
must be the same for all of them.
Required Associated Constants§
const TYPE_ID_META: MetadataBuffer
const TYPE_ID_META: MetadataBuffer
Type ID metadata, serialized into a MetadataBuffer.
If a type implements multiple FFI traits, TYPE_ID_META
must be the same for all of them.
Required Methods§
fn lower(obj: Self) -> Self::FfiType
fn lower(obj: 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 something that can be passed over the FFI and reconstructed on the other side.
Note that this method takes an owned value; 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, Error>
fn try_lift(v: Self::FfiType) -> Result<Self, Error>
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(obj: Self, buf: &mut Vec<u8, Global>)
fn write(obj: Self, buf: &mut Vec<u8, Global>)
Write a rust value into a buffer, 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.
Note that this method takes an owned value because it’s transferring ownership to the foreign language code via the RustBuffer.
fn try_read(buf: &mut &[u8]) -> Result<Self, Error>
fn try_read(buf: &mut &[u8]) -> Result<Self, Error>
Read a rust value from a buffer, 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.
Note the slightly unusual type here - we want a mutable reference to a slice of bytes, because we want to be able to advance the start of the slice after reading an item from it (but will not mutate the actual contents of the slice).
Implementations on Foreign Types§
§impl<UT> FfiConverter<UT> for i16
impl<UT> FfiConverter<UT> for i16
type FfiType = i16
fn lower(obj: i16) -> <i16 as FfiConverter<UT>>::FfiType
fn try_lift(v: <i16 as FfiConverter<UT>>::FfiType) -> Result<i16, Error>
fn write(obj: i16, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<i16, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_I16)
§impl<UT> FfiConverter<UT> for SystemTime
impl<UT> FfiConverter<UT> for SystemTime
Support for passing timestamp values via the FFI.
Timestamps values are currently always passed by serializing to a buffer.
Timestamps are represented on the buffer by an i64 that indicates the direction and the magnitude in seconds of the offset from epoch, and a u32 that indicates the nanosecond portion of the offset magnitude. The nanosecond portion is expected to be between 0 and 999,999,999.
To build an epoch offset the absolute value of the seconds portion of the offset should be combined with the nanosecond portion. This is because the sign of the seconds portion represents the direction of the offset overall. The sign of the seconds portion can then be used to determine if the total offset should be added to or subtracted from the unix epoch.
type FfiType = RustBuffer
fn lower(v: SystemTime) -> RustBuffer
fn try_lift(buf: RustBuffer) -> Result<SystemTime, Error>
fn write(obj: SystemTime, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<SystemTime, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_SYSTEM_TIME)
§impl<UT> FfiConverter<UT> for u32
impl<UT> FfiConverter<UT> for u32
type FfiType = u32
fn lower(obj: u32) -> <u32 as FfiConverter<UT>>::FfiType
fn try_lift(v: <u32 as FfiConverter<UT>>::FfiType) -> Result<u32, Error>
fn write(obj: u32, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<u32, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_U32)
§impl<UT> FfiConverter<UT> for String
impl<UT> FfiConverter<UT> for String
Support for passing Strings via the FFI.
Unlike many other implementations of FfiConverter
, this passes a struct containing
a raw 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 struct
must be a valid RustBuffer
and it must contain valid utf-8 data (in other
words, it must be a Vec<u8>
suitable for use as an actual rust String
).
When serialized in a buffer, strings are represented as a i32 byte length followed by utf8-encoded bytes. (It’s a signed integer because unsigned types are currently experimental in Kotlin).
type FfiType = RustBuffer
fn lower(obj: String) -> <String as FfiConverter<UT>>::FfiType
fn try_lift(v: <String as FfiConverter<UT>>::FfiType) -> Result<String, Error>
fn write(obj: String, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<String, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_STRING)
§impl<UT> FfiConverter<UT> for f64
impl<UT> FfiConverter<UT> for f64
type FfiType = f64
fn lower(obj: f64) -> <f64 as FfiConverter<UT>>::FfiType
fn try_lift(v: <f64 as FfiConverter<UT>>::FfiType) -> Result<f64, Error>
fn write(obj: f64, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<f64, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_F64)
§impl<UT> FfiConverter<UT> for u16
impl<UT> FfiConverter<UT> for u16
type FfiType = u16
fn lower(obj: u16) -> <u16 as FfiConverter<UT>>::FfiType
fn try_lift(v: <u16 as FfiConverter<UT>>::FfiType) -> Result<u16, Error>
fn write(obj: u16, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<u16, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_U16)
§impl<UT> FfiConverter<UT> for bool
impl<UT> FfiConverter<UT> for bool
Support for passing boolean values via the FFI.
Booleans are passed as an i8
in order to avoid problems with handling
C-compatible boolean values on JVM-based languages.
type FfiType = i8
fn lower(obj: bool) -> <bool as FfiConverter<UT>>::FfiType
fn try_lift(v: <bool as FfiConverter<UT>>::FfiType) -> Result<bool, Error>
fn write(obj: bool, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<bool, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_BOOL)
§impl<UT> FfiConverter<UT> for i64
impl<UT> FfiConverter<UT> for i64
type FfiType = i64
fn lower(obj: i64) -> <i64 as FfiConverter<UT>>::FfiType
fn try_lift(v: <i64 as FfiConverter<UT>>::FfiType) -> Result<i64, Error>
fn write(obj: i64, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<i64, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_I64)
§impl<T, UT> FfiConverter<UT> for Arc<T>where
T: FfiConverterArc<UT> + ?Sized,
impl<T, UT> FfiConverter<UT> for Arc<T>where T: FfiConverterArc<UT> + ?Sized,
type FfiType = <T as FfiConverterArc<UT>>::FfiType
fn lower(obj: Arc<T>) -> <Arc<T> as FfiConverter<UT>>::FfiType
fn try_lift(v: <Arc<T> as FfiConverter<UT>>::FfiType) -> Result<Arc<T>, Error>
fn write(obj: Arc<T>, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<Arc<T>, Error>
const TYPE_ID_META: MetadataBuffer = T::TYPE_ID_META
§impl<UT> FfiConverter<UT> for i32
impl<UT> FfiConverter<UT> for i32
type FfiType = i32
fn lower(obj: i32) -> <i32 as FfiConverter<UT>>::FfiType
fn try_lift(v: <i32 as FfiConverter<UT>>::FfiType) -> Result<i32, Error>
fn write(obj: i32, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<i32, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_I32)
§impl<UT> FfiConverter<UT> for i8
impl<UT> FfiConverter<UT> for i8
type FfiType = i8
fn lower(obj: i8) -> <i8 as FfiConverter<UT>>::FfiType
fn try_lift(v: <i8 as FfiConverter<UT>>::FfiType) -> Result<i8, Error>
fn write(obj: i8, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<i8, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_I8)
§impl<UT> FfiConverter<UT> for f32
impl<UT> FfiConverter<UT> for f32
type FfiType = f32
fn lower(obj: f32) -> <f32 as FfiConverter<UT>>::FfiType
fn try_lift(v: <f32 as FfiConverter<UT>>::FfiType) -> Result<f32, Error>
fn write(obj: f32, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<f32, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_F32)
§impl<UT> FfiConverter<UT> for u8
impl<UT> FfiConverter<UT> for u8
type FfiType = u8
fn lower(obj: u8) -> <u8 as FfiConverter<UT>>::FfiType
fn try_lift(v: <u8 as FfiConverter<UT>>::FfiType) -> Result<u8, Error>
fn write(obj: u8, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<u8, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_U8)
§impl<UT> FfiConverter<UT> for u64
impl<UT> FfiConverter<UT> for u64
type FfiType = u64
fn lower(obj: u64) -> <u64 as FfiConverter<UT>>::FfiType
fn try_lift(v: <u64 as FfiConverter<UT>>::FfiType) -> Result<u64, Error>
fn write(obj: u64, buf: &mut Vec<u8, Global>)
fn try_read(buf: &mut &[u8]) -> Result<u64, Error>
const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_U64)
Implementors§
§impl<UT> FfiConverter<UT> for Duration
impl<UT> FfiConverter<UT> for Duration
Support for passing duration values via the FFI.
Duration values are currently always passed by serializing to a buffer.
Durations are represented on the buffer by a u64 that indicates the magnitude in seconds, and a u32 that indicates the nanosecond portion of the magnitude. The nanosecond portion is expected to be between 0 and 999,999,999.