summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-15 03:35:49 +0000
commitd8bbc7858622b6d9c278469aab701ca0b609cddf (patch)
treeeff41dc61d9f714852212739e6b3738b82a2af87 /third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift
parentReleasing progress-linux version 125.0.3-1~progress7.99u1. (diff)
downloadfirefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz
firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift')
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/callback_interface.rs12
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/compounds.rs5
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/executor.rs23
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/external.rs2
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs209
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/object.rs18
-rw-r--r--third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/primitives.rs8
7 files changed, 203 insertions, 74 deletions
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/callback_interface.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/callback_interface.rs
index 5d8b37e0af..dab89e0259 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/callback_interface.rs
+++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/callback_interface.rs
@@ -6,21 +6,25 @@ use super::CodeType;
#[derive(Debug)]
pub struct CallbackInterfaceCodeType {
- id: String,
+ name: String,
}
impl CallbackInterfaceCodeType {
- pub fn new(id: String) -> Self {
- Self { id }
+ pub fn new(name: String) -> Self {
+ Self { name }
}
}
impl CodeType for CallbackInterfaceCodeType {
fn type_label(&self) -> String {
- super::SwiftCodeOracle.class_name(&self.id)
+ super::SwiftCodeOracle.class_name(&self.name)
}
fn canonical_name(&self) -> String {
format!("CallbackInterface{}", self.type_label())
}
+
+ fn initialization_fn(&self) -> Option<String> {
+ Some(format!("uniffiCallbackInit{}", self.name))
+ }
}
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/compounds.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/compounds.rs
index 8e6dddf3f9..d89fdfd386 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/compounds.rs
+++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/compounds.rs
@@ -30,8 +30,9 @@ impl CodeType for OptionalCodeType {
fn literal(&self, literal: &Literal) -> String {
match literal {
- Literal::Null => "nil".into(),
- _ => super::SwiftCodeOracle.find(&self.inner).literal(literal),
+ Literal::None => "nil".into(),
+ Literal::Some { inner } => super::SwiftCodeOracle.find(&self.inner).literal(inner),
+ _ => panic!("Invalid literal for Optional type: {literal:?}"),
}
}
}
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/executor.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/executor.rs
deleted file mode 100644
index b488b004cf..0000000000
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/executor.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use super::CodeType;
-
-#[derive(Debug)]
-pub struct ForeignExecutorCodeType;
-
-impl CodeType for ForeignExecutorCodeType {
- fn type_label(&self) -> String {
- // On Swift, we define a struct to represent a ForeignExecutor
- "UniFfiForeignExecutor".into()
- }
-
- fn canonical_name(&self) -> String {
- "ForeignExecutor".into()
- }
-
- fn initialization_fn(&self) -> Option<String> {
- Some("uniffiInitForeignExecutor".into())
- }
-}
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/external.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/external.rs
index 0b6728ba84..3960b7aae1 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/external.rs
+++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/external.rs
@@ -17,7 +17,7 @@ impl ExternalCodeType {
impl CodeType for ExternalCodeType {
fn type_label(&self) -> String {
- self.name.clone()
+ super::SwiftCodeOracle.class_name(&self.name)
}
fn canonical_name(&self) -> String {
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs
index 12db4afc66..16c1625123 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs
+++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs
@@ -10,25 +10,49 @@ use std::fmt::Debug;
use anyhow::{Context, Result};
use askama::Template;
-use heck::{ToLowerCamelCase, ToUpperCamelCase};
+use camino::Utf8Path;
+use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
use serde::{Deserialize, Serialize};
use super::Bindings;
use crate::backend::TemplateExpression;
+use crate::bindings::swift;
use crate::interface::*;
-use crate::BindingsConfig;
+use crate::{BindingGenerator, BindingsConfig};
mod callback_interface;
mod compounds;
mod custom;
mod enum_;
-mod executor;
mod external;
mod miscellany;
mod object;
mod primitives;
mod record;
+pub struct SwiftBindingGenerator;
+impl BindingGenerator for SwiftBindingGenerator {
+ type Config = Config;
+
+ fn write_bindings(
+ &self,
+ ci: &ComponentInterface,
+ config: &Config,
+ out_dir: &Utf8Path,
+ try_format_code: bool,
+ ) -> Result<()> {
+ swift::write_bindings(config, ci, out_dir, try_format_code)
+ }
+
+ fn check_library_path(
+ &self,
+ _library_path: &Utf8Path,
+ _cdylib_name: Option<&str>,
+ ) -> Result<()> {
+ Ok(())
+ }
+}
+
/// A trait tor the implementation.
trait CodeType: Debug {
/// The language specific label used to reference this type. This will be used in
@@ -196,6 +220,8 @@ pub struct Config {
ffi_module_filename: Option<String>,
generate_module_map: Option<bool>,
omit_argument_labels: Option<bool>,
+ generate_immutable_records: Option<bool>,
+ experimental_sendable_value_types: Option<bool>,
#[serde(default)]
custom_types: HashMap<String, CustomTypeConfig>,
}
@@ -261,6 +287,16 @@ impl Config {
pub fn omit_argument_labels(&self) -> bool {
self.omit_argument_labels.unwrap_or(false)
}
+
+ /// Whether to generate immutable records (`let` instead of `var`)
+ pub fn generate_immutable_records(&self) -> bool {
+ self.generate_immutable_records.unwrap_or(false)
+ }
+
+ /// Whether to mark value types as 'Sendable'
+ pub fn experimental_sendable_value_types(&self) -> bool {
+ self.experimental_sendable_value_types.unwrap_or(false)
+ }
}
impl BindingsConfig for Config {
@@ -400,7 +436,6 @@ pub struct SwiftWrapper<'a> {
ci: &'a ComponentInterface,
type_helper_code: String,
type_imports: BTreeSet<String>,
- has_async_fns: bool,
}
impl<'a> SwiftWrapper<'a> {
pub fn new(config: Config, ci: &'a ComponentInterface) -> Self {
@@ -412,7 +447,6 @@ impl<'a> SwiftWrapper<'a> {
ci,
type_helper_code,
type_imports,
- has_async_fns: ci.has_async_fns(),
}
}
@@ -425,10 +459,6 @@ impl<'a> SwiftWrapper<'a> {
.iter_types()
.map(|t| SwiftCodeOracle.find(t))
.filter_map(|ct| ct.initialization_fn())
- .chain(
- self.has_async_fns
- .then(|| "uniffiInitContinuationCallback".into()),
- )
.collect()
}
}
@@ -464,12 +494,11 @@ impl SwiftCodeOracle {
Type::Duration => Box::new(miscellany::DurationCodeType),
Type::Enum { name, .. } => Box::new(enum_::EnumCodeType::new(name)),
- Type::Object { name, .. } => Box::new(object::ObjectCodeType::new(name)),
+ Type::Object { name, imp, .. } => Box::new(object::ObjectCodeType::new(name, imp)),
Type::Record { name, .. } => Box::new(record::RecordCodeType::new(name)),
Type::CallbackInterface { name, .. } => {
Box::new(callback_interface::CallbackInterfaceCodeType::new(name))
}
- Type::ForeignExecutor => Box::new(executor::ForeignExecutorCodeType),
Type::Optional { inner_type } => {
Box::new(compounds::OptionalCodeType::new(*inner_type))
}
@@ -509,7 +538,22 @@ impl SwiftCodeOracle {
nm.to_string().to_lower_camel_case()
}
- fn ffi_type_label_raw(&self, ffi_type: &FfiType) -> String {
+ /// Get the idiomatic Swift rendering of an FFI callback function name
+ fn ffi_callback_name(&self, nm: &str) -> String {
+ format!("Uniffi{}", nm.to_upper_camel_case())
+ }
+
+ /// Get the idiomatic Swift rendering of an FFI struct name
+ fn ffi_struct_name(&self, nm: &str) -> String {
+ format!("Uniffi{}", nm.to_upper_camel_case())
+ }
+
+ /// Get the idiomatic Swift rendering of an if guard name
+ fn if_guard_name(&self, nm: &str) -> String {
+ format!("UNIFFI_FFIDEF_{}", nm.to_shouty_snake_case())
+ }
+
+ fn ffi_type_label(&self, ffi_type: &FfiType) -> String {
match ffi_type {
FfiType::Int8 => "Int8".into(),
FfiType::UInt8 => "UInt8".into(),
@@ -521,40 +565,74 @@ impl SwiftCodeOracle {
FfiType::UInt64 => "UInt64".into(),
FfiType::Float32 => "Float".into(),
FfiType::Float64 => "Double".into(),
+ FfiType::Handle => "UInt64".into(),
FfiType::RustArcPtr(_) => "UnsafeMutableRawPointer".into(),
FfiType::RustBuffer(_) => "RustBuffer".into(),
+ FfiType::RustCallStatus => "RustCallStatus".into(),
FfiType::ForeignBytes => "ForeignBytes".into(),
- FfiType::ForeignCallback => "ForeignCallback".into(),
- FfiType::ForeignExecutorHandle => "Int".into(),
- FfiType::ForeignExecutorCallback => "ForeignExecutorCallback".into(),
- FfiType::RustFutureContinuationCallback => "UniFfiRustFutureContinuation".into(),
- FfiType::RustFutureHandle | FfiType::RustFutureContinuationData => {
- "UnsafeMutableRawPointer".into()
+ // Note: @escaping is required for Swift versions before 5.7 for callbacks passed into
+ // async functions. Swift 5.7 and later does not require it. We should probably remove
+ // it once we upgrade our minimum requirement to 5.7 or later.
+ FfiType::Callback(name) => format!("@escaping {}", self.ffi_callback_name(name)),
+ FfiType::Struct(name) => self.ffi_struct_name(name),
+ FfiType::Reference(inner) => {
+ format!("UnsafeMutablePointer<{}>", self.ffi_type_label(inner))
}
+ FfiType::VoidPointer => "UnsafeMutableRawPointer".into(),
}
}
- fn ffi_type_label(&self, ffi_type: &FfiType) -> String {
- match ffi_type {
- FfiType::ForeignCallback
- | FfiType::ForeignExecutorCallback
- | FfiType::RustFutureHandle
- | FfiType::RustFutureContinuationCallback
- | FfiType::RustFutureContinuationData => {
- format!("{} _Nonnull", self.ffi_type_label_raw(ffi_type))
- }
- _ => self.ffi_type_label_raw(ffi_type),
+ /// Default values for FFI types
+ ///
+ /// Used to set a default return value when returning an error
+ fn ffi_default_value(&self, return_type: Option<&FfiType>) -> String {
+ match return_type {
+ Some(t) => match t {
+ FfiType::UInt8
+ | FfiType::Int8
+ | FfiType::UInt16
+ | FfiType::Int16
+ | FfiType::UInt32
+ | FfiType::Int32
+ | FfiType::UInt64
+ | FfiType::Int64 => "0".to_owned(),
+ FfiType::Float32 | FfiType::Float64 => "0.0".to_owned(),
+ FfiType::RustArcPtr(_) => "nil".to_owned(),
+ FfiType::RustBuffer(_) => "RustBuffer.empty()".to_owned(),
+ _ => unimplemented!("FFI return type: {t:?}"),
+ },
+ // When we need to use a value for void returns, we use a `u8` placeholder
+ None => "0".to_owned(),
}
}
fn ffi_canonical_name(&self, ffi_type: &FfiType) -> String {
- self.ffi_type_label_raw(ffi_type)
+ self.ffi_type_label(ffi_type)
+ }
+
+ /// Get the name of the protocol and class name for an object.
+ ///
+ /// If we support callback interfaces, the protocol name is the object name, and the class name is derived from that.
+ /// Otherwise, the class name is the object name and the protocol name is derived from that.
+ ///
+ /// This split determines what types `FfiConverter.lower()` inputs. If we support callback
+ /// interfaces, `lower` must lower anything that implements the protocol. If not, then lower
+ /// only lowers the concrete class.
+ fn object_names(&self, obj: &Object) -> (String, String) {
+ let class_name = self.class_name(obj.name());
+ if obj.has_callback_interface() {
+ let impl_name = format!("{class_name}Impl");
+ (class_name, impl_name)
+ } else {
+ (format!("{class_name}Protocol"), class_name)
+ }
}
}
pub mod filters {
use super::*;
pub use crate::backend::filters::*;
+ use uniffi_meta::LiteralMetadata;
fn oracle() -> &'static SwiftCodeOracle {
&SwiftCodeOracle
@@ -564,6 +642,13 @@ pub mod filters {
Ok(oracle().find(&as_type.as_type()).type_label())
}
+ pub fn return_type_name(as_type: Option<&impl AsType>) -> Result<String, askama::Error> {
+ Ok(match as_type {
+ Some(as_type) => oracle().find(&as_type.as_type()).type_label(),
+ None => "()".to_owned(),
+ })
+ }
+
pub fn canonical_name(as_type: &impl AsType) -> Result<String, askama::Error> {
Ok(oracle().find(&as_type.as_type()).canonical_name())
}
@@ -572,6 +657,15 @@ pub mod filters {
Ok(oracle().find(&as_type.as_type()).ffi_converter_name())
}
+ pub fn ffi_error_converter_name(as_type: &impl AsType) -> Result<String, askama::Error> {
+ // special handling for types used as errors.
+ let mut name = oracle().find(&as_type.as_type()).ffi_converter_name();
+ if matches!(&as_type.as_type(), Type::Object { .. }) {
+ name.push_str("__as_error")
+ }
+ Ok(name)
+ }
+
pub fn lower_fn(as_type: &impl AsType) -> Result<String, askama::Error> {
Ok(oracle().find(&as_type.as_type()).lower())
}
@@ -595,6 +689,16 @@ pub mod filters {
Ok(oracle().find(&as_type.as_type()).literal(literal))
}
+ // Get the idiomatic Swift rendering of an individual enum variant's discriminant
+ pub fn variant_discr_literal(e: &Enum, index: &usize) -> Result<String, askama::Error> {
+ let literal = e.variant_discr(*index).expect("invalid index");
+ match literal {
+ LiteralMetadata::UInt(v, _, _) => Ok(v.to_string()),
+ LiteralMetadata::Int(v, _, _) => Ok(v.to_string()),
+ _ => unreachable!("expected an UInt!"),
+ }
+ }
+
/// Get the Swift type for an FFIType
pub fn ffi_type_name(ffi_type: &FfiType) -> Result<String, askama::Error> {
Ok(oracle().ffi_type_label(ffi_type))
@@ -604,6 +708,10 @@ pub mod filters {
Ok(oracle().ffi_canonical_name(ffi_type))
}
+ pub fn ffi_default_value(return_type: Option<FfiType>) -> Result<String, askama::Error> {
+ Ok(oracle().ffi_default_value(return_type.as_ref()))
+ }
+
/// Like `ffi_type_name`, but used in `BridgingHeaderTemplate.h` which uses a slightly different
/// names.
pub fn header_ffi_type_name(ffi_type: &FfiType) -> Result<String, askama::Error> {
@@ -618,18 +726,17 @@ pub mod filters {
FfiType::UInt64 => "uint64_t".into(),
FfiType::Float32 => "float".into(),
FfiType::Float64 => "double".into(),
+ FfiType::Handle => "uint64_t".into(),
FfiType::RustArcPtr(_) => "void*_Nonnull".into(),
FfiType::RustBuffer(_) => "RustBuffer".into(),
+ FfiType::RustCallStatus => "RustCallStatus".into(),
FfiType::ForeignBytes => "ForeignBytes".into(),
- FfiType::ForeignCallback => "ForeignCallback _Nonnull".into(),
- FfiType::ForeignExecutorCallback => "UniFfiForeignExecutorCallback _Nonnull".into(),
- FfiType::ForeignExecutorHandle => "size_t".into(),
- FfiType::RustFutureContinuationCallback => {
- "UniFfiRustFutureContinuation _Nonnull".into()
- }
- FfiType::RustFutureHandle | FfiType::RustFutureContinuationData => {
- "void* _Nonnull".into()
+ FfiType::Callback(name) => {
+ format!("{} _Nonnull", SwiftCodeOracle.ffi_callback_name(name))
}
+ FfiType::Struct(name) => SwiftCodeOracle.ffi_struct_name(name),
+ FfiType::Reference(inner) => format!("{}* _Nonnull", header_ffi_type_name(inner)?),
+ FfiType::VoidPointer => "void* _Nonnull".into(),
})
}
@@ -664,6 +771,30 @@ pub mod filters {
Ok(oracle().enum_variant_name(nm))
}
+ /// Get the idiomatic Swift rendering of an FFI callback function name
+ pub fn ffi_callback_name(nm: &str) -> Result<String, askama::Error> {
+ Ok(oracle().ffi_callback_name(nm))
+ }
+
+ /// Get the idiomatic Swift rendering of an FFI struct name
+ pub fn ffi_struct_name(nm: &str) -> Result<String, askama::Error> {
+ Ok(oracle().ffi_struct_name(nm))
+ }
+
+ /// Get the idiomatic Swift rendering of an if guard name
+ pub fn if_guard_name(nm: &str) -> Result<String, askama::Error> {
+ Ok(oracle().if_guard_name(nm))
+ }
+
+ /// Get the idiomatic Swift rendering of docstring
+ pub fn docstring(docstring: &str, spaces: &i32) -> Result<String, askama::Error> {
+ let middle = textwrap::indent(&textwrap::dedent(docstring), " * ");
+ let wrapped = format!("/**\n{middle}\n */");
+
+ let spaces = usize::try_from(*spaces).unwrap_or_default();
+ Ok(textwrap::indent(&wrapped, &" ".repeat(spaces)))
+ }
+
pub fn error_handler(result: &ResultType) -> Result<String, askama::Error> {
Ok(match &result.throws_type {
Some(t) => format!("{}.lift", ffi_converter_name(t)?),
@@ -685,4 +816,8 @@ pub mod filters {
}
))
}
+
+ pub fn object_names(obj: &Object) -> Result<(String, String), askama::Error> {
+ Ok(SwiftCodeOracle.object_names(obj))
+ }
}
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/object.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/object.rs
index ea140c998d..d4497a7b19 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/object.rs
+++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/object.rs
@@ -3,24 +3,32 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use super::CodeType;
+use crate::interface::ObjectImpl;
#[derive(Debug)]
pub struct ObjectCodeType {
- id: String,
+ name: String,
+ imp: ObjectImpl,
}
impl ObjectCodeType {
- pub fn new(id: String) -> Self {
- Self { id }
+ pub fn new(name: String, imp: ObjectImpl) -> Self {
+ Self { name, imp }
}
}
impl CodeType for ObjectCodeType {
fn type_label(&self) -> String {
- super::SwiftCodeOracle.class_name(&self.id)
+ super::SwiftCodeOracle.class_name(&self.name)
}
fn canonical_name(&self) -> String {
- format!("Type{}", self.id)
+ format!("Type{}", self.name)
+ }
+
+ fn initialization_fn(&self) -> Option<String> {
+ self.imp
+ .has_callback_interface()
+ .then(|| format!("uniffiCallbackInit{}", self.name))
}
}
diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/primitives.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/primitives.rs
index 86424658a3..e0c670520e 100644
--- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/primitives.rs
+++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/primitives.rs
@@ -9,7 +9,11 @@ use paste::paste;
fn render_literal(literal: &Literal) -> String {
fn typed_number(type_: &Type, num_str: String) -> String {
- match type_ {
+ let unwrapped_type = match type_ {
+ Type::Optional { inner_type } => inner_type,
+ t => t,
+ };
+ match unwrapped_type {
// special case Int32.
Type::Int32 => num_str,
// otherwise use constructor e.g. UInt8(x)
@@ -29,7 +33,7 @@ fn render_literal(literal: &Literal) -> String {
super::SwiftCodeOracle.find(type_).type_label()
)
}
- _ => panic!("Unexpected literal: {num_str} is not a number"),
+ _ => panic!("Unexpected literal: {num_str} for type: {type_:?}"),
}
}