diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /third_party/rust/uniffi_bindgen/src/interface/ffi.rs | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | third_party/rust/uniffi_bindgen/src/interface/ffi.rs | 195 |
1 files changed, 179 insertions, 16 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/interface/ffi.rs b/third_party/rust/uniffi_bindgen/src/interface/ffi.rs index d18aaf8262..b27cb78477 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/ffi.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/ffi.rs @@ -47,20 +47,49 @@ pub enum FfiType { /// A borrowed reference to some raw bytes owned by foreign language code. /// The provider of this reference must keep it alive for the duration of the receiving call. ForeignBytes, - /// Pointer to a callback function that handles all callbacks on the foreign language side. - ForeignCallback, - /// Pointer-sized opaque handle that represents a foreign executor. Foreign bindings can - /// either use an actual pointer or a usized integer. - ForeignExecutorHandle, - /// Pointer to the callback function that's invoked to schedule calls with a ForeignExecutor - ForeignExecutorCallback, - /// Pointer to a Rust future - RustFutureHandle, - /// Continuation function for a Rust future - RustFutureContinuationCallback, - RustFutureContinuationData, - // TODO: you can imagine a richer structural typesystem here, e.g. `Ref<String>` or something. - // We don't need that yet and it's possible we never will, so it isn't here for now. + /// Pointer to a callback function. The inner value which matches one of the callback + /// definitions in [crate::ComponentInterface::ffi_definitions]. + Callback(String), + /// Pointer to a FFI struct (e.g. a VTable). The inner value matches one of the struct + /// definitions in [crate::ComponentInterface::ffi_definitions]. + Struct(String), + /// Opaque 64-bit handle + /// + /// These are used to pass objects across the FFI. + Handle, + RustCallStatus, + /// Pointer to an FfiType. + Reference(Box<FfiType>), + /// Opaque pointer + VoidPointer, +} + +impl FfiType { + pub fn reference(self) -> FfiType { + FfiType::Reference(Box::new(self)) + } + + /// Unique name for an FFI return type + pub fn return_type_name(return_type: Option<&FfiType>) -> String { + match return_type { + Some(t) => match t { + FfiType::UInt8 => "u8".to_owned(), + FfiType::Int8 => "i8".to_owned(), + FfiType::UInt16 => "u16".to_owned(), + FfiType::Int16 => "i16".to_owned(), + FfiType::UInt32 => "u32".to_owned(), + FfiType::Int32 => "i32".to_owned(), + FfiType::UInt64 => "u64".to_owned(), + FfiType::Int64 => "i64".to_owned(), + FfiType::Float32 => "f32".to_owned(), + FfiType::Float64 => "f64".to_owned(), + FfiType::RustArcPtr(_) => "pointer".to_owned(), + FfiType::RustBuffer(_) => "rust_buffer".to_owned(), + _ => unimplemented!("FFI return type: {t:?}"), + }, + None => "void".to_owned(), + } + } } /// When passing data across the FFI, each `Type` value will be lowered into a corresponding @@ -94,7 +123,6 @@ impl From<&Type> for FfiType { Type::Object { name, .. } => FfiType::RustArcPtr(name.to_owned()), // Callback interfaces are passed as opaque integer handles. Type::CallbackInterface { .. } => FfiType::UInt64, - Type::ForeignExecutor => FfiType::ForeignExecutorHandle, // Other types are serialized into a bytebuffer and deserialized on the other side. Type::Enum { .. } | Type::Record { .. } @@ -107,6 +135,11 @@ impl From<&Type> for FfiType { name, kind: ExternalKind::Interface, .. + } + | Type::External { + name, + kind: ExternalKind::Trait, + .. } => FfiType::RustArcPtr(name.clone()), Type::External { name, @@ -131,6 +164,24 @@ impl From<&&Type> for FfiType { } } +/// An Ffi definition +#[derive(Debug, Clone)] +pub enum FfiDefinition { + Function(FfiFunction), + CallbackFunction(FfiCallbackFunction), + Struct(FfiStruct), +} + +impl FfiDefinition { + pub fn name(&self) -> &str { + match self { + Self::Function(f) => f.name(), + Self::CallbackFunction(f) => f.name(), + Self::Struct(s) => s.name(), + } + } +} + /// Represents an "extern C"-style function that will be part of the FFI. /// /// These can't be declared explicitly in the UDL, but rather, are derived automatically @@ -150,6 +201,19 @@ pub struct FfiFunction { } impl FfiFunction { + pub fn callback_init(module_path: &str, trait_name: &str, vtable_name: String) -> Self { + Self { + name: uniffi_meta::init_callback_vtable_fn_symbol_name(module_path, trait_name), + arguments: vec![FfiArgument { + name: "vtable".to_string(), + type_: FfiType::Struct(vtable_name).reference(), + }], + return_type: None, + has_rust_call_status_arg: false, + ..Self::default() + } + } + pub fn name(&self) -> &str { &self.name } @@ -181,7 +245,7 @@ impl FfiFunction { ) { self.arguments = args.into_iter().collect(); if self.is_async() { - self.return_type = Some(FfiType::RustFutureHandle); + self.return_type = Some(FfiType::Handle); self.has_rust_call_status_arg = false; } else { self.return_type = return_type; @@ -212,14 +276,113 @@ pub struct FfiArgument { } impl FfiArgument { + pub fn new(name: impl Into<String>, type_: FfiType) -> Self { + Self { + name: name.into(), + type_, + } + } + pub fn name(&self) -> &str { &self.name } + pub fn type_(&self) -> FfiType { self.type_.clone() } } +/// Represents an "extern C"-style callback function +/// +/// These are defined in the foreign code and passed to Rust as a function pointer. +#[derive(Debug, Default, Clone)] +pub struct FfiCallbackFunction { + // Name for this function type. This matches the value inside `FfiType::Callback` + pub(super) name: String, + pub(super) arguments: Vec<FfiArgument>, + pub(super) return_type: Option<FfiType>, + pub(super) has_rust_call_status_arg: bool, +} + +impl FfiCallbackFunction { + pub fn name(&self) -> &str { + &self.name + } + + pub fn arguments(&self) -> Vec<&FfiArgument> { + self.arguments.iter().collect() + } + + pub fn return_type(&self) -> Option<&FfiType> { + self.return_type.as_ref() + } + + pub fn has_rust_call_status_arg(&self) -> bool { + self.has_rust_call_status_arg + } +} + +/// Represents a repr(C) struct used in the FFI +#[derive(Debug, Default, Clone)] +pub struct FfiStruct { + pub(super) name: String, + pub(super) fields: Vec<FfiField>, +} + +impl FfiStruct { + /// Get the name of this struct + pub fn name(&self) -> &str { + &self.name + } + + /// Get the fields for this struct + pub fn fields(&self) -> &[FfiField] { + &self.fields + } +} + +/// Represents a field of an [FfiStruct] +#[derive(Debug, Clone)] +pub struct FfiField { + pub(super) name: String, + pub(super) type_: FfiType, +} + +impl FfiField { + pub fn new(name: impl Into<String>, type_: FfiType) -> Self { + Self { + name: name.into(), + type_, + } + } + + pub fn name(&self) -> &str { + &self.name + } + + pub fn type_(&self) -> FfiType { + self.type_.clone() + } +} + +impl From<FfiFunction> for FfiDefinition { + fn from(value: FfiFunction) -> FfiDefinition { + FfiDefinition::Function(value) + } +} + +impl From<FfiStruct> for FfiDefinition { + fn from(value: FfiStruct) -> FfiDefinition { + FfiDefinition::Struct(value) + } +} + +impl From<FfiCallbackFunction> for FfiDefinition { + fn from(value: FfiCallbackFunction) -> FfiDefinition { + FfiDefinition::CallbackFunction(value) + } +} + #[cfg(test)] mod test { // There's not really much to test here to be honest, |