summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_udl
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_udl')
-rw-r--r--third_party/rust/uniffi_udl/.cargo-checksum.json2
-rw-r--r--third_party/rust/uniffi_udl/Cargo.toml12
-rw-r--r--third_party/rust/uniffi_udl/README.md81
-rw-r--r--third_party/rust/uniffi_udl/src/attributes.rs199
-rw-r--r--third_party/rust/uniffi_udl/src/collectors.rs18
-rw-r--r--third_party/rust/uniffi_udl/src/converters/callables.rs16
-rw-r--r--third_party/rust/uniffi_udl/src/converters/enum_.rs79
-rw-r--r--third_party/rust/uniffi_udl/src/converters/interface.rs6
-rw-r--r--third_party/rust/uniffi_udl/src/converters/mod.rs10
-rw-r--r--third_party/rust/uniffi_udl/src/finder.rs60
-rw-r--r--third_party/rust/uniffi_udl/src/lib.rs2
-rw-r--r--third_party/rust/uniffi_udl/src/literal.rs8
-rw-r--r--third_party/rust/uniffi_udl/src/resolver.rs1
13 files changed, 372 insertions, 122 deletions
diff --git a/third_party/rust/uniffi_udl/.cargo-checksum.json b/third_party/rust/uniffi_udl/.cargo-checksum.json
index 233a1e7795..88ed1cb4b7 100644
--- a/third_party/rust/uniffi_udl/.cargo-checksum.json
+++ b/third_party/rust/uniffi_udl/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"8bb1bcb6089114c92a0d06f884e64769edc493bd26d271eb659d6592d8d2f5fa","src/attributes.rs":"faf1c53c17ff511f587113afdb37de4890087150f32e19c9af4d878daebe7c89","src/collectors.rs":"3d80f169ccb7a64c434a6890948e49a64947062c29487b5bea58721189cb2786","src/converters/callables.rs":"c41d15cf816f5838e74f0c1d7a5806c4f1c1b2d925ca11b2b6658a978b2373fb","src/converters/enum_.rs":"1742441b812949b83ec28c2c2c4684c34fd618195cff47af2934c7ee9c895c59","src/converters/interface.rs":"a3deb1915eb4be80d21116f24bec7163736bdffbad4eb2236fb531386a97c4f8","src/converters/mod.rs":"4035ec70c56917fa7c61cced5f8a8398c99028e13959662acc1f7a48aa71ae3b","src/finder.rs":"c496aca0ac640d4ca5fd57b32131297544e5468c9e792f8b5da1644df6d22d2e","src/lib.rs":"11a5d3c288f5786164471b0870b5ca9190305757461c6a6d20777a96622457f1","src/literal.rs":"30e50d7c1d3f061bb6aaa7ad3a6eb31d75a6ea21159dfe454f7ab9ae4bdb580e","src/resolver.rs":"96212b52c4f4f7637713d0a39f5c4972e6480e4ce98070dcb8647d67c9b8d5e2"},"package":"889edb7109c6078abe0e53e9b4070cf74a6b3468d141bdf5ef1bd4d1dc24a1c3"} \ No newline at end of file
+{"files":{"Cargo.toml":"e4553df91528daadbc52244f436c3ae17d9c6a4629d232643a20ed63c1311625","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/attributes.rs":"f1cdee01db837920dbd109d60b39dd4b0ece56f83797fe4ace1e0caf97c02483","src/collectors.rs":"00c9cd8e8f7be6949996f069b449f120f0b0694ff2f1ca92b79201721c18c594","src/converters/callables.rs":"1ad26c2782629e98272edc75c38343f58194ebf9626ae451ba84546a60d45a48","src/converters/enum_.rs":"aa0ca7a7a50521a45e296c6f53be5f1981a41872443946f72c2ca8baebe4d69b","src/converters/interface.rs":"6042d4abd5e236ed6158c5f6d4d9b81bb01fbbcb8b42bf8a5b385b978c68f6f8","src/converters/mod.rs":"c34a30e3b7a2e3c092a7074f4bab6f6c34364177c096af59a7dda13e44ffdc3c","src/finder.rs":"3586ffd3772151eabbc3d6062725933c88978e1b5feb64312bbf42cd43af30fa","src/lib.rs":"56c50ce61ba5e7266fe7fc9fa9d0022cdbfbe9801730753bd4ee66fed040221c","src/literal.rs":"4f28ad49a17246b4dc30a677cfff65b345bfac0924856e19f58e7574a74c2c40","src/resolver.rs":"c4ff362055dc4ed489e94a063ec0fd3becb8787ad35ce65cdec437a1aae518a0"},"package":"8c43c9ed40a8d20a5c3eae2d23031092db6b96dc8e571beb449ba9757484cea0"} \ No newline at end of file
diff --git a/third_party/rust/uniffi_udl/Cargo.toml b/third_party/rust/uniffi_udl/Cargo.toml
index 346cd71c27..fd03f3434a 100644
--- a/third_party/rust/uniffi_udl/Cargo.toml
+++ b/third_party/rust/uniffi_udl/Cargo.toml
@@ -12,10 +12,11 @@
[package]
edition = "2021"
name = "uniffi_udl"
-version = "0.25.3"
+version = "0.27.1"
description = "udl parsing for the uniffi project"
homepage = "https://mozilla.github.io/uniffi-rs"
documentation = "https://mozilla.github.io/uniffi-rs"
+readme = "README.md"
keywords = [
"ffi",
"bindgen",
@@ -26,11 +27,14 @@ repository = "https://github.com/mozilla/uniffi-rs"
[dependencies.anyhow]
version = "1"
+[dependencies.textwrap]
+version = "0.16"
+
[dependencies.uniffi_meta]
-version = "=0.25.3"
+version = "=0.27.1"
[dependencies.uniffi_testing]
-version = "=0.25.3"
+version = "=0.27.1"
[dependencies.weedle2]
-version = "4.0.0"
+version = "5.0.0"
diff --git a/third_party/rust/uniffi_udl/README.md b/third_party/rust/uniffi_udl/README.md
new file mode 100644
index 0000000000..64ac3486a3
--- /dev/null
+++ b/third_party/rust/uniffi_udl/README.md
@@ -0,0 +1,81 @@
+# UniFFI - a multi-language bindings generator for Rust
+
+UniFFI is a toolkit for building cross-platform software components in Rust.
+
+For the impatient, see [**the UniFFI user guide**](https://mozilla.github.io/uniffi-rs/)
+or [**the UniFFI examples**](https://github.com/mozilla/uniffi-rs/tree/main/examples#example-uniffi-components).
+
+By writing your core business logic in Rust and describing its interface in an "object model",
+you can use UniFFI to help you:
+
+* Compile your Rust code into a shared library for use on different target platforms.
+* Generate bindings to load and use the library from different target languages.
+
+You can describe your object model in an [interface definition file](https://mozilla.github.io/uniffi-rs/udl_file_spec.html)
+or [by using proc-macros](https://mozilla.github.io/uniffi-rs/proc_macro/index.html).
+
+UniFFI is currently used extensively by Mozilla in Firefox mobile and desktop browsers;
+written once in Rust, auto-generated bindings allow that functionality to be called
+from both Kotlin (for Android apps) and Swift (for iOS apps).
+It also has a growing community of users shipping various cool things to many users.
+
+UniFFI comes with support for **Kotlin**, **Swift**, **Python** and **Ruby** with 3rd party bindings available for **C#** and **Golang**.
+Additional foreign language bindings can be developed externally and we welcome contributions to list them here.
+See [Third-party foreign language bindings](#third-party-foreign-language-bindings).
+
+## User Guide
+
+You can read more about using the tool in [**the UniFFI user guide**](https://mozilla.github.io/uniffi-rs/).
+
+We consider it ready for production use, but UniFFI is a long way from a 1.0 release with lots of internal work still going on.
+We try hard to avoid breaking simple consumers, but more advanced things might break as you upgrade over time.
+
+### Etymology and Pronunciation
+
+ˈjuːnɪfaɪ. Pronounced to rhyme with "unify".
+
+A portmanteau word that also puns with "unify", to signify the joining of one codebase accessed from many languages.
+
+uni - [Latin ūni-, from ūnus, one]
+FFI - [Abbreviation, Foreign Function Interface]
+
+## Alternative tools
+
+Other tools we know of which try and solve a similarly shaped problem are:
+
+* [Diplomat](https://github.com/rust-diplomat/diplomat/) - see our [writeup of
+ the different approach taken by that tool](docs/diplomat-and-macros.md)
+* [Interoptopus](https://github.com/ralfbiedert/interoptopus/)
+
+(Please open a PR if you think other tools should be listed!)
+
+## Third-party foreign language bindings
+
+* [Kotlin Multiplatform support](https://gitlab.com/trixnity/uniffi-kotlin-multiplatform-bindings). The repository contains Kotlin Multiplatform bindings generation for UniFFI, letting you target both JVM and Native.
+* [Go bindings](https://github.com/NordSecurity/uniffi-bindgen-go)
+* [C# bindings](https://github.com/NordSecurity/uniffi-bindgen-cs)
+* [Dart bindings](https://github.com/NiallBunting/uniffi-rs-dart)
+
+### External resources
+
+There are a few third-party resources that make it easier to work with UniFFI:
+
+* [Plugin support for `.udl` files](https://github.com/Lonami/uniffi-dl) for the IDEA platform ([*uniffi-dl* in the JetBrains marketplace](https://plugins.jetbrains.com/plugin/20527-uniffi-dl)). It provides syntax highlighting, code folding, code completion, reference resolution and navigation (among others features) for the [UniFFI Definition Language (UDL)](https://mozilla.github.io/uniffi-rs/).
+* [cargo swift](https://github.com/antoniusnaumann/cargo-swift), a cargo plugin to build a Swift Package from Rust code. It provides an init command for setting up a UniFFI crate and a package command for building a Swift package from Rust code - without the need for additional configuration or build scripts.
+* [Cargo NDK Gradle Plugin](https://github.com/willir/cargo-ndk-android-gradle) allows you to build Rust code using [`cargo-ndk`](https://github.com/bbqsrc/cargo-ndk), which generally makes Android library builds less painful.
+* [`uniffi-starter`](https://github.com/ianthetechie/uniffi-starter) is a minimal project demonstrates a wide range of UniFFI in a complete project in a compact manner. It includes a full Android library build process, an XCFramework generation script, and example Swift package structure.
+
+(Please open a PR if you think other resources should be listed!)
+
+## Contributing
+
+If this tool sounds interesting to you, please help us develop it! You can:
+
+* View the [contributor guidelines](./docs/contributing.md).
+* File or work on [issues](https://github.com/mozilla/uniffi-rs/issues) here in GitHub.
+* Join discussions in the [#uniffi:mozilla.org](https://matrix.to/#/#uniffi:mozilla.org)
+ room on Matrix.
+
+## Code of Conduct
+
+This project is governed by Mozilla's [Community Participation Guidelines](./CODE_OF_CONDUCT.md).
diff --git a/third_party/rust/uniffi_udl/src/attributes.rs b/third_party/rust/uniffi_udl/src/attributes.rs
index f06b4f29c1..7bb05808c4 100644
--- a/third_party/rust/uniffi_udl/src/attributes.rs
+++ b/third_party/rust/uniffi_udl/src/attributes.rs
@@ -37,10 +37,29 @@ pub(super) enum Attribute {
kind: ExternalKind,
export: bool,
},
+ Rust {
+ kind: RustKind,
+ },
// Custom type on the scaffolding side
Custom,
// The interface described is implemented as a trait.
Trait,
+ // Modifies `Trait` to enable foreign implementations (callback interfaces)
+ WithForeign,
+ Async,
+ NonExhaustive,
+}
+
+// A type defined in Rust via procmacros but which should be available
+// in UDL.
+#[derive(Debug, Copy, Clone, Checksum)]
+pub(super) enum RustKind {
+ Object,
+ CallbackTrait,
+ Trait,
+ Record,
+ Enum,
+ CallbackInterface,
}
impl Attribute {
@@ -67,6 +86,9 @@ impl TryFrom<&weedle::attribute::ExtendedAttribute<'_>> for Attribute {
"Error" => Ok(Attribute::Error),
"Custom" => Ok(Attribute::Custom),
"Trait" => Ok(Attribute::Trait),
+ "WithForeign" => Ok(Attribute::WithForeign),
+ "Async" => Ok(Attribute::Async),
+ "NonExhaustive" => Ok(Attribute::NonExhaustive),
_ => anyhow::bail!("ExtendedAttributeNoArgs not supported: {:?}", (attr.0).0),
},
// Matches assignment-style attributes like ["Throws=Error"]
@@ -95,6 +117,19 @@ impl TryFrom<&weedle::attribute::ExtendedAttribute<'_>> for Attribute {
kind: ExternalKind::Interface,
export: true,
}),
+ "ExternalTrait" => Ok(Attribute::External {
+ crate_name: name_from_id_or_string(&identity.rhs),
+ kind: ExternalKind::Trait,
+ export: false,
+ }),
+ "ExternalTraitExport" => Ok(Attribute::External {
+ crate_name: name_from_id_or_string(&identity.rhs),
+ kind: ExternalKind::Trait,
+ export: true,
+ }),
+ "Rust" => Ok(Attribute::Rust {
+ kind: rust_kind_from_id_or_string(&identity.rhs)?,
+ }),
_ => anyhow::bail!(
"Attribute identity Identifier not supported: {:?}",
identity.lhs_identifier.0
@@ -130,6 +165,26 @@ fn name_from_id_or_string(nm: &weedle::attribute::IdentifierOrString<'_>) -> Str
}
}
+fn rust_kind_from_id_or_string(nm: &weedle::attribute::IdentifierOrString<'_>) -> Result<RustKind> {
+ Ok(match nm {
+ weedle::attribute::IdentifierOrString::String(str_lit) => match str_lit.0 {
+ // support names which match either procmacro or udl
+ "interface" => RustKind::Object,
+ "object" => RustKind::Object,
+ "record" => RustKind::Record,
+ "dictionary" => RustKind::Record,
+ "enum" => RustKind::Enum,
+ "trait" => RustKind::Trait,
+ "callback" => RustKind::CallbackInterface,
+ "trait_with_foreign" => RustKind::CallbackTrait,
+ _ => anyhow::bail!("Unknown `[Rust=]` kind {:?}", str_lit.0),
+ },
+ weedle::attribute::IdentifierOrString::Identifier(_) => {
+ anyhow::bail!("Expected string attribute value, got identifier")
+ }
+ })
+}
+
/// Parse a weedle `ExtendedAttributeList` into a list of `Attribute`s,
/// erroring out on duplicates.
fn parse_attributes<F>(
@@ -161,7 +216,6 @@ where
}
/// Attributes that can be attached to an `enum` definition in the UDL.
-/// There's only one case here: using `[Error]` to mark an enum as an error class.
#[derive(Debug, Clone, Checksum, Default)]
pub(super) struct EnumAttributes(Vec<Attribute>);
@@ -169,6 +223,12 @@ impl EnumAttributes {
pub fn contains_error_attr(&self) -> bool {
self.0.iter().any(|attr| attr.is_error())
}
+
+ pub fn contains_non_exhaustive_attr(&self) -> bool {
+ self.0
+ .iter()
+ .any(|attr| matches!(attr, Attribute::NonExhaustive))
+ }
}
impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for EnumAttributes {
@@ -178,6 +238,10 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for EnumAttributes {
) -> Result<Self, Self::Error> {
let attrs = parse_attributes(weedle_attributes, |attr| match attr {
Attribute::Error => Ok(()),
+ Attribute::NonExhaustive => Ok(()),
+ // Allow `[Enum]`, since we may be parsing an attribute list from an interface with the
+ // `[Enum]` attribute.
+ Attribute::Enum => Ok(()),
_ => bail!(format!("{attr:?} not supported for enums")),
})?;
Ok(Self(attrs))
@@ -196,8 +260,9 @@ impl<T: TryInto<EnumAttributes, Error = anyhow::Error>> TryFrom<Option<T>> for E
/// Represents UDL attributes that might appear on a function.
///
-/// This supports the `[Throws=ErrorName]` attribute for functions that
-/// can produce an error.
+/// This supports:
+/// * `[Throws=ErrorName]` attribute for functions that can produce an error.
+/// * `[Async] for async functions
#[derive(Debug, Clone, Checksum, Default)]
pub(super) struct FunctionAttributes(Vec<Attribute>);
@@ -210,6 +275,10 @@ impl FunctionAttributes {
_ => None,
})
}
+
+ pub(super) fn is_async(&self) -> bool {
+ self.0.iter().any(|attr| matches!(attr, Attribute::Async))
+ }
}
impl FromIterator<Attribute> for FunctionAttributes {
@@ -224,7 +293,7 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for FunctionAttribut
weedle_attributes: &weedle::attribute::ExtendedAttributeList<'_>,
) -> Result<Self, Self::Error> {
let attrs = parse_attributes(weedle_attributes, |attr| match attr {
- Attribute::Throws(_) => Ok(()),
+ Attribute::Throws(_) | Attribute::Async => Ok(()),
_ => bail!(format!("{attr:?} not supported for functions")),
})?;
Ok(Self(attrs))
@@ -294,12 +363,25 @@ impl InterfaceAttributes {
self.0.iter().any(|attr| attr.is_error())
}
- pub fn object_impl(&self) -> ObjectImpl {
- if self.0.iter().any(|attr| matches!(attr, Attribute::Trait)) {
- ObjectImpl::Trait
- } else {
- ObjectImpl::Struct
- }
+ pub fn contains_trait(&self) -> bool {
+ self.0.iter().any(|attr| matches!(attr, Attribute::Trait))
+ }
+
+ pub fn contains_with_foreign(&self) -> bool {
+ self.0
+ .iter()
+ .any(|attr| matches!(attr, Attribute::WithForeign))
+ }
+
+ pub fn object_impl(&self) -> Result<ObjectImpl> {
+ Ok(
+ match (self.contains_trait(), self.contains_with_foreign()) {
+ (true, true) => ObjectImpl::CallbackTrait,
+ (true, false) => ObjectImpl::Trait,
+ (false, false) => ObjectImpl::Struct,
+ (false, true) => bail!("WithForeign can't be specified without Trait"),
+ },
+ )
}
pub fn get_traits(&self) -> Vec<String> {
self.0
@@ -321,6 +403,7 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for InterfaceAttribu
Attribute::Enum => Ok(()),
Attribute::Error => Ok(()),
Attribute::Trait => Ok(()),
+ Attribute::WithForeign => Ok(()),
Attribute::Traits(_) => Ok(()),
_ => bail!(format!("{attr:?} not supported for interface definition")),
})?;
@@ -373,6 +456,10 @@ impl ConstructorAttributes {
_ => None,
})
}
+
+ pub(super) fn is_async(&self) -> bool {
+ self.0.iter().any(|attr| matches!(attr, Attribute::Async))
+ }
}
impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for ConstructorAttributes {
@@ -383,6 +470,7 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for ConstructorAttri
let attrs = parse_attributes(weedle_attributes, |attr| match attr {
Attribute::Throws(_) => Ok(()),
Attribute::Name(_) => Ok(()),
+ Attribute::Async => Ok(()),
_ => bail!(format!("{attr:?} not supported for constructors")),
})?;
Ok(Self(attrs))
@@ -406,6 +494,10 @@ impl MethodAttributes {
})
}
+ pub(super) fn is_async(&self) -> bool {
+ self.0.iter().any(|attr| matches!(attr, Attribute::Async))
+ }
+
pub(super) fn get_self_by_arc(&self) -> bool {
self.0
.iter()
@@ -425,8 +517,7 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for MethodAttributes
weedle_attributes: &weedle::attribute::ExtendedAttributeList<'_>,
) -> Result<Self, Self::Error> {
let attrs = parse_attributes(weedle_attributes, |attr| match attr {
- Attribute::SelfType(_) => Ok(()),
- Attribute::Throws(_) => Ok(()),
+ Attribute::SelfType(_) | Attribute::Throws(_) | Attribute::Async => Ok(()),
_ => bail!(format!("{attr:?} not supported for methods")),
})?;
Ok(Self(attrs))
@@ -498,10 +589,18 @@ impl TypedefAttributes {
})
}
+ pub(super) fn rust_kind(&self) -> Option<RustKind> {
+ self.0.iter().find_map(|attr| match attr {
+ Attribute::Rust { kind, .. } => Some(*kind),
+ _ => None,
+ })
+ }
+
pub(super) fn external_tagged(&self) -> Option<bool> {
// If it was "exported" via a proc-macro the FfiConverter was not tagged.
self.0.iter().find_map(|attr| match attr {
Attribute::External { export, .. } => Some(!*export),
+ Attribute::Rust { .. } => Some(false),
_ => None,
})
}
@@ -513,7 +612,7 @@ impl TryFrom<&weedle::attribute::ExtendedAttributeList<'_>> for TypedefAttribute
weedle_attributes: &weedle::attribute::ExtendedAttributeList<'_>,
) -> Result<Self, Self::Error> {
let attrs = parse_attributes(weedle_attributes, |attr| match attr {
- Attribute::External { .. } | Attribute::Custom => Ok(()),
+ Attribute::External { .. } | Attribute::Custom | Attribute::Rust { .. } => Ok(()),
_ => bail!(format!("{attr:?} not supported for typedefs")),
})?;
Ok(Self(attrs))
@@ -641,14 +740,22 @@ mod test {
}
#[test]
- fn test_throws_attribute() {
+ fn test_function_attributes() {
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Throws=Error]").unwrap();
let attrs = FunctionAttributes::try_from(&node).unwrap();
assert!(matches!(attrs.get_throws_err(), Some("Error")));
+ assert!(!attrs.is_async());
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[]").unwrap();
let attrs = FunctionAttributes::try_from(&node).unwrap();
assert!(attrs.get_throws_err().is_none());
+ assert!(!attrs.is_async());
+
+ let (_, node) =
+ weedle::attribute::ExtendedAttributeList::parse("[Throws=Error, Async]").unwrap();
+ let attrs = FunctionAttributes::try_from(&node).unwrap();
+ assert!(matches!(attrs.get_throws_err(), Some("Error")));
+ assert!(attrs.is_async());
}
#[test]
@@ -673,22 +780,34 @@ mod test {
let attrs = MethodAttributes::try_from(&node).unwrap();
assert!(!attrs.get_self_by_arc());
assert!(matches!(attrs.get_throws_err(), Some("Error")));
+ assert!(!attrs.is_async());
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[]").unwrap();
let attrs = MethodAttributes::try_from(&node).unwrap();
assert!(!attrs.get_self_by_arc());
assert!(attrs.get_throws_err().is_none());
+ assert!(!attrs.is_async());
let (_, node) =
weedle::attribute::ExtendedAttributeList::parse("[Self=ByArc, Throws=Error]").unwrap();
let attrs = MethodAttributes::try_from(&node).unwrap();
assert!(attrs.get_self_by_arc());
assert!(attrs.get_throws_err().is_some());
+ assert!(!attrs.is_async());
+
+ let (_, node) =
+ weedle::attribute::ExtendedAttributeList::parse("[Self=ByArc, Throws=Error, Async]")
+ .unwrap();
+ let attrs = MethodAttributes::try_from(&node).unwrap();
+ assert!(attrs.get_self_by_arc());
+ assert!(attrs.get_throws_err().is_some());
+ assert!(attrs.is_async());
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Self=ByArc]").unwrap();
let attrs = MethodAttributes::try_from(&node).unwrap();
assert!(attrs.get_self_by_arc());
assert!(attrs.get_throws_err().is_none());
+ assert!(!attrs.is_async());
}
#[test]
@@ -710,6 +829,11 @@ mod test {
let attrs = ConstructorAttributes::try_from(&node).unwrap();
assert!(matches!(attrs.get_throws_err(), Some("Error")));
assert!(matches!(attrs.get_name(), Some("MyFactory")));
+ assert!(!attrs.is_async());
+
+ let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Async]").unwrap();
+ let attrs = ConstructorAttributes::try_from(&node).unwrap();
+ assert!(attrs.is_async());
}
#[test]
@@ -754,15 +878,24 @@ mod test {
fn test_trait_attribute() {
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Trait]").unwrap();
let attrs = InterfaceAttributes::try_from(&node).unwrap();
- assert_eq!(attrs.object_impl(), ObjectImpl::Trait);
+ assert_eq!(attrs.object_impl().unwrap(), ObjectImpl::Trait);
+
+ let (_, node) =
+ weedle::attribute::ExtendedAttributeList::parse("[Trait, WithForeign]").unwrap();
+ let attrs = InterfaceAttributes::try_from(&node).unwrap();
+ assert_eq!(attrs.object_impl().unwrap(), ObjectImpl::CallbackTrait);
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[]").unwrap();
let attrs = InterfaceAttributes::try_from(&node).unwrap();
- assert_eq!(attrs.object_impl(), ObjectImpl::Struct);
+ assert_eq!(attrs.object_impl().unwrap(), ObjectImpl::Struct);
+
+ let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[WithForeign]").unwrap();
+ let attrs = InterfaceAttributes::try_from(&node).unwrap();
+ assert!(attrs.object_impl().is_err())
}
#[test]
- fn test_enum_attribute() {
+ fn test_enum_attribute_on_interface() {
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Enum]").unwrap();
let attrs = InterfaceAttributes::try_from(&node).unwrap();
assert!(matches!(attrs.contains_enum_attr(), true));
@@ -783,6 +916,38 @@ mod test {
);
}
+ // Test parsing attributes for enum definitions
+ #[test]
+ fn test_enum_attributes() {
+ let (_, node) =
+ weedle::attribute::ExtendedAttributeList::parse("[Error, NonExhaustive]").unwrap();
+ let attrs = EnumAttributes::try_from(&node).unwrap();
+ assert!(attrs.contains_error_attr());
+ assert!(attrs.contains_non_exhaustive_attr());
+
+ let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Trait]").unwrap();
+ let err = EnumAttributes::try_from(&node).unwrap_err();
+ assert_eq!(err.to_string(), "Trait not supported for enums");
+ }
+
+ // Test parsing attributes for interface definitions with the `[Enum]` attribute
+ #[test]
+ fn test_enum_attributes_from_interface() {
+ let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Enum]").unwrap();
+ assert!(EnumAttributes::try_from(&node).is_ok());
+
+ let (_, node) =
+ weedle::attribute::ExtendedAttributeList::parse("[Enum, Error, NonExhaustive]")
+ .unwrap();
+ let attrs = EnumAttributes::try_from(&node).unwrap();
+ assert!(attrs.contains_error_attr());
+ assert!(attrs.contains_non_exhaustive_attr());
+
+ let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Enum, Trait]").unwrap();
+ let err = EnumAttributes::try_from(&node).unwrap_err();
+ assert_eq!(err.to_string(), "Trait not supported for enums");
+ }
+
#[test]
fn test_other_attributes_not_supported_for_interfaces() {
let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Trait, ByRef]").unwrap();
diff --git a/third_party/rust/uniffi_udl/src/collectors.rs b/third_party/rust/uniffi_udl/src/collectors.rs
index 6a91ab4a93..de5489f5f9 100644
--- a/third_party/rust/uniffi_udl/src/collectors.rs
+++ b/third_party/rust/uniffi_udl/src/collectors.rs
@@ -5,7 +5,7 @@
//! # Collects metadata from UDL.
use crate::attributes;
-use crate::converters::APIConverter;
+use crate::converters::{convert_docstring, APIConverter};
use crate::finder;
use crate::resolver::TypeResolver;
use anyhow::{bail, Result};
@@ -138,6 +138,7 @@ impl From<InterfaceCollector> for uniffi_meta::MetadataGroup {
crate_name: value.types.module_path(),
name: value.types.namespace,
},
+ namespace_docstring: value.types.namespace_docstring.clone(),
items: value.items,
}
}
@@ -171,15 +172,13 @@ impl APIBuilder for weedle::Definition<'_> {
match self {
weedle::Definition::Namespace(d) => d.process(ci)?,
weedle::Definition::Enum(d) => {
+ let mut e: uniffi_meta::EnumMetadata = d.convert(ci)?;
// We check if the enum represents an error...
let attrs = attributes::EnumAttributes::try_from(d.attributes.as_ref())?;
if attrs.contains_error_attr() {
- let e: uniffi_meta::ErrorMetadata = d.convert(ci)?;
- ci.add_definition(e.into())?;
- } else {
- let e: uniffi_meta::EnumMetadata = d.convert(ci)?;
- ci.add_definition(e.into())?;
+ e.forced_flatness = Some(true);
}
+ ci.add_definition(e.into())?;
}
weedle::Definition::Dictionary(d) => {
let rec = d.convert(ci)?;
@@ -187,12 +186,9 @@ impl APIBuilder for weedle::Definition<'_> {
}
weedle::Definition::Interface(d) => {
let attrs = attributes::InterfaceAttributes::try_from(d.attributes.as_ref())?;
- if attrs.contains_enum_attr() {
+ if attrs.contains_enum_attr() || attrs.contains_error_attr() {
let e: uniffi_meta::EnumMetadata = d.convert(ci)?;
ci.add_definition(e.into())?;
- } else if attrs.contains_error_attr() {
- let e: uniffi_meta::ErrorMetadata = d.convert(ci)?;
- ci.add_definition(e.into())?;
} else {
let obj: uniffi_meta::ObjectMetadata = d.convert(ci)?;
ci.add_definition(obj.into())?;
@@ -218,6 +214,7 @@ impl APIBuilder for weedle::NamespaceDefinition<'_> {
if self.identifier.0 != ci.types.namespace {
bail!("duplicate namespace definition");
}
+ ci.types.namespace_docstring = self.docstring.as_ref().map(|v| convert_docstring(&v.0));
for func in self.members.body.convert(ci)? {
ci.add_definition(func.into())?;
}
@@ -229,6 +226,7 @@ impl APIBuilder for weedle::NamespaceDefinition<'_> {
pub(crate) struct TypeCollector {
/// The unique prefix that we'll use for namespacing when exposing this component's API.
pub namespace: String,
+ pub namespace_docstring: Option<String>,
pub crate_name: String,
diff --git a/third_party/rust/uniffi_udl/src/converters/callables.rs b/third_party/rust/uniffi_udl/src/converters/callables.rs
index 3e15bb8e02..dda3c3a3ce 100644
--- a/third_party/rust/uniffi_udl/src/converters/callables.rs
+++ b/third_party/rust/uniffi_udl/src/converters/callables.rs
@@ -5,6 +5,7 @@
use super::APIConverter;
use crate::attributes::ArgumentAttributes;
use crate::attributes::{ConstructorAttributes, FunctionAttributes, MethodAttributes};
+use crate::converters::convert_docstring;
use crate::literal::convert_default_value;
use crate::InterfaceCollector;
use anyhow::{bail, Result};
@@ -41,6 +42,7 @@ impl APIConverter<FieldMetadata> for weedle::argument::SingleArgument<'_> {
name: self.identifier.0.to_string(),
ty: type_,
default: None,
+ docstring: None,
})
}
}
@@ -89,6 +91,7 @@ impl APIConverter<FnMetadata> for weedle::namespace::OperationNamespaceMember<'_
Some(id) => id.0.to_string(),
};
let attrs = FunctionAttributes::try_from(self.attributes.as_ref())?;
+ let is_async = attrs.is_async();
let throws = match attrs.get_throws_err() {
None => None,
Some(name) => match ci.get_type(name) {
@@ -99,10 +102,11 @@ impl APIConverter<FnMetadata> for weedle::namespace::OperationNamespaceMember<'_
Ok(FnMetadata {
module_path: ci.module_path(),
name,
- is_async: false,
+ is_async,
return_type,
inputs: self.args.body.list.convert(ci)?,
throws,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
checksum: None,
})
}
@@ -122,10 +126,12 @@ impl APIConverter<ConstructorMetadata> for weedle::interface::ConstructorInterfa
name: String::from(attributes.get_name().unwrap_or("new")),
// We don't know the name of the containing `Object` at this point, fill it in later.
self_name: Default::default(),
+ is_async: attributes.is_async(),
// Also fill in checksum_fn_name later, since it depends on object_name
inputs: self.args.body.list.convert(ci)?,
throws,
checksum: None,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
@@ -140,6 +146,7 @@ impl APIConverter<MethodMetadata> for weedle::interface::OperationInterfaceMembe
}
let return_type = ci.resolve_return_type_expression(&self.return_type)?;
let attributes = MethodAttributes::try_from(self.attributes.as_ref())?;
+ let is_async = attributes.is_async();
let throws = match attributes.get_throws_err() {
Some(name) => match ci.get_type(name) {
@@ -164,12 +171,13 @@ impl APIConverter<MethodMetadata> for weedle::interface::OperationInterfaceMembe
},
// We don't know the name of the containing `Object` at this point, fill it in later.
self_name: Default::default(),
- is_async: false, // not supported in UDL
+ is_async,
inputs: self.args.body.list.convert(ci)?,
return_type,
throws,
takes_self_by_arc,
checksum: None,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
@@ -184,6 +192,7 @@ impl APIConverter<TraitMethodMetadata> for weedle::interface::OperationInterface
}
let return_type = ci.resolve_return_type_expression(&self.return_type)?;
let attributes = MethodAttributes::try_from(self.attributes.as_ref())?;
+ let is_async = attributes.is_async();
let throws = match attributes.get_throws_err() {
Some(name) => match ci.get_type(name) {
@@ -208,12 +217,13 @@ impl APIConverter<TraitMethodMetadata> for weedle::interface::OperationInterface
name
}
},
- is_async: false, // not supported in udl
+ is_async,
inputs: self.args.body.list.convert(ci)?,
return_type,
throws,
takes_self_by_arc,
checksum: None,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
diff --git a/third_party/rust/uniffi_udl/src/converters/enum_.rs b/third_party/rust/uniffi_udl/src/converters/enum_.rs
index a3e68fd23e..1615a1a7ca 100644
--- a/third_party/rust/uniffi_udl/src/converters/enum_.rs
+++ b/third_party/rust/uniffi_udl/src/converters/enum_.rs
@@ -3,19 +3,22 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use super::APIConverter;
-use crate::InterfaceCollector;
+use crate::{attributes::EnumAttributes, converters::convert_docstring, InterfaceCollector};
use anyhow::{bail, Result};
-use uniffi_meta::{EnumMetadata, ErrorMetadata, VariantMetadata};
+use uniffi_meta::{EnumMetadata, VariantMetadata};
-// Note that we have four `APIConverter` impls here - one for the `enum` case,
-// one for the `[Error] enum` case, and and one for the `[Enum] interface` case,
-// and one for the `[Error] interface` case.
+// Note that we have 2 `APIConverter` impls here - one for the `enum` case
+// (including an enum with `[Error]`), and one for the `[Error] interface` cas
+// (which is still an enum, but with different "flatness" characteristics.)
impl APIConverter<EnumMetadata> for weedle::EnumDefinition<'_> {
fn convert(&self, ci: &mut InterfaceCollector) -> Result<EnumMetadata> {
+ let attributes = EnumAttributes::try_from(self.attributes.as_ref())?;
Ok(EnumMetadata {
module_path: ci.module_path(),
name: self.identifier.0.to_string(),
+ forced_flatness: None,
+ discr_type: None,
variants: self
.values
.body
@@ -23,35 +26,15 @@ impl APIConverter<EnumMetadata> for weedle::EnumDefinition<'_> {
.iter()
.map::<Result<_>, _>(|v| {
Ok(VariantMetadata {
- name: v.0.to_string(),
+ name: v.value.0.to_string(),
+ discr: None,
fields: vec![],
+ docstring: v.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
})
.collect::<Result<Vec<_>>>()?,
- })
- }
-}
-
-impl APIConverter<ErrorMetadata> for weedle::EnumDefinition<'_> {
- fn convert(&self, ci: &mut InterfaceCollector) -> Result<ErrorMetadata> {
- Ok(ErrorMetadata::Enum {
- enum_: EnumMetadata {
- module_path: ci.module_path(),
- name: self.identifier.0.to_string(),
- variants: self
- .values
- .body
- .list
- .iter()
- .map::<Result<_>, _>(|v| {
- Ok(VariantMetadata {
- name: v.0.to_string(),
- fields: vec![],
- })
- })
- .collect::<Result<Vec<_>>>()?,
- },
- is_flat: true,
+ non_exhaustive: attributes.contains_non_exhaustive_attr(),
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
@@ -61,11 +44,11 @@ impl APIConverter<EnumMetadata> for weedle::InterfaceDefinition<'_> {
if self.inheritance.is_some() {
bail!("interface inheritance is not supported for enum interfaces");
}
- // We don't need to check `self.attributes` here; if calling code has dispatched
- // to this impl then we already know there was an `[Enum]` attribute.
+ let attributes = EnumAttributes::try_from(self.attributes.as_ref())?;
Ok(EnumMetadata {
module_path: ci.module_path(),
name: self.identifier.0.to_string(),
+ forced_flatness: Some(false),
variants: self
.members
.body
@@ -78,41 +61,15 @@ impl APIConverter<EnumMetadata> for weedle::InterfaceDefinition<'_> {
),
})
.collect::<Result<Vec<_>>>()?,
+ discr_type: None,
+ non_exhaustive: attributes.contains_non_exhaustive_attr(),
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
// Enums declared using the `[Enum] interface` syntax might have variants with fields.
//flat: false,
})
}
}
-impl APIConverter<ErrorMetadata> for weedle::InterfaceDefinition<'_> {
- fn convert(&self, ci: &mut InterfaceCollector) -> Result<ErrorMetadata> {
- if self.inheritance.is_some() {
- bail!("interface inheritance is not supported for enum interfaces");
- }
- // We don't need to check `self.attributes` here; callers have already checked them
- // to work out which version to dispatch to.
- Ok(ErrorMetadata::Enum {
- enum_: EnumMetadata {
- module_path: ci.module_path(),
- name: self.identifier.0.to_string(),
- variants: self
- .members
- .body
- .iter()
- .map::<Result<VariantMetadata>, _>(|member| match member {
- weedle::interface::InterfaceMember::Operation(t) => Ok(t.convert(ci)?),
- _ => bail!(
- "interface member type {:?} not supported in enum interface",
- member
- ),
- })
- .collect::<Result<Vec<_>>>()?,
- },
- is_flat: false,
- })
- }
-}
-
#[cfg(test)]
mod test {
use super::*;
diff --git a/third_party/rust/uniffi_udl/src/converters/interface.rs b/third_party/rust/uniffi_udl/src/converters/interface.rs
index 58e6a9c8a0..ef9bdd9540 100644
--- a/third_party/rust/uniffi_udl/src/converters/interface.rs
+++ b/third_party/rust/uniffi_udl/src/converters/interface.rs
@@ -4,7 +4,7 @@
use super::APIConverter;
use crate::attributes::InterfaceAttributes;
-use crate::InterfaceCollector;
+use crate::{converters::convert_docstring, InterfaceCollector};
use anyhow::{bail, Result};
use std::collections::HashSet;
use uniffi_meta::{
@@ -23,7 +23,7 @@ impl APIConverter<ObjectMetadata> for weedle::InterfaceDefinition<'_> {
};
let object_name = self.identifier.0;
- let object_impl = attributes.object_impl();
+ let object_impl = attributes.object_impl()?;
// Convert each member into a constructor or method, guarding against duplicate names.
// They get added to the ci and aren't carried in ObjectMetadata.
let mut member_names = HashSet::new();
@@ -70,6 +70,7 @@ impl APIConverter<ObjectMetadata> for weedle::InterfaceDefinition<'_> {
throws: None,
takes_self_by_arc: false,
checksum: None,
+ docstring: None,
})
};
// Trait methods are in the Metadata.
@@ -130,6 +131,7 @@ impl APIConverter<ObjectMetadata> for weedle::InterfaceDefinition<'_> {
module_path: ci.module_path(),
name: object_name.to_string(),
imp: object_impl,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
diff --git a/third_party/rust/uniffi_udl/src/converters/mod.rs b/third_party/rust/uniffi_udl/src/converters/mod.rs
index 7a2d22ac42..195d9cc0b7 100644
--- a/third_party/rust/uniffi_udl/src/converters/mod.rs
+++ b/third_party/rust/uniffi_udl/src/converters/mod.rs
@@ -29,6 +29,11 @@ pub(crate) trait APIConverter<T> {
fn convert(&self, ci: &mut InterfaceCollector) -> Result<T>;
}
+// Convert UDL docstring into metadata docstring
+pub(crate) fn convert_docstring(docstring: &str) -> String {
+ textwrap::dedent(docstring)
+}
+
/// Convert a list of weedle items into a list of `InterfaceCollector` items,
/// by doing a direct item-by-item mapping.
impl<U, T: APIConverter<U>> APIConverter<Vec<U>> for Vec<T> {
@@ -72,6 +77,7 @@ impl APIConverter<VariantMetadata> for weedle::interface::OperationInterfaceMemb
};
Ok(VariantMetadata {
name,
+ discr: None,
fields: self
.args
.body
@@ -79,6 +85,7 @@ impl APIConverter<VariantMetadata> for weedle::interface::OperationInterfaceMemb
.iter()
.map(|arg| arg.convert(ci))
.collect::<Result<Vec<_>>>()?,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
@@ -95,6 +102,7 @@ impl APIConverter<RecordMetadata> for weedle::DictionaryDefinition<'_> {
module_path: ci.module_path(),
name: self.identifier.0.to_string(),
fields: self.members.body.convert(ci)?,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
@@ -113,6 +121,7 @@ impl APIConverter<FieldMetadata> for weedle::dictionary::DictionaryMember<'_> {
name: self.identifier.0.to_string(),
ty: type_,
default,
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
@@ -150,6 +159,7 @@ impl APIConverter<CallbackInterfaceMetadata> for weedle::CallbackInterfaceDefini
Ok(CallbackInterfaceMetadata {
module_path: ci.module_path(),
name: object_name.to_string(),
+ docstring: self.docstring.as_ref().map(|v| convert_docstring(&v.0)),
})
}
}
diff --git a/third_party/rust/uniffi_udl/src/finder.rs b/third_party/rust/uniffi_udl/src/finder.rs
index 0c4c187dc0..259557ad07 100644
--- a/third_party/rust/uniffi_udl/src/finder.rs
+++ b/third_party/rust/uniffi_udl/src/finder.rs
@@ -22,8 +22,8 @@ use std::convert::TryFrom;
use anyhow::{bail, Result};
use super::TypeCollector;
-use crate::attributes::{InterfaceAttributes, TypedefAttributes};
-use uniffi_meta::Type;
+use crate::attributes::{InterfaceAttributes, RustKind, TypedefAttributes};
+use uniffi_meta::{ObjectImpl, Type};
/// Trait to help with an early "type discovery" phase when processing the UDL.
///
@@ -75,7 +75,7 @@ impl TypeFinder for weedle::InterfaceDefinition<'_> {
Type::Object {
name,
module_path: types.module_path(),
- imp: attrs.object_impl(),
+ imp: attrs.object_impl()?,
},
)
}
@@ -111,7 +111,6 @@ impl TypeFinder for weedle::EnumDefinition<'_> {
impl TypeFinder for weedle::TypedefDefinition<'_> {
fn add_type_definitions_to(&self, types: &mut TypeCollector) -> Result<()> {
- let name = self.identifier.0;
let attrs = TypedefAttributes::try_from(self.attributes.as_ref())?;
// If we wanted simple `typedef`s, it would be as easy as:
// > let t = types.resolve_type_expression(&self.type_)?;
@@ -122,29 +121,52 @@ impl TypeFinder for weedle::TypedefDefinition<'_> {
// `FfiConverter` implementation.
let builtin = types.resolve_type_expression(&self.type_)?;
types.add_type_definition(
- name,
+ self.identifier.0,
Type::Custom {
module_path: types.module_path(),
- name: name.to_string(),
+ name: self.identifier.0.to_string(),
builtin: builtin.into(),
},
)
} else {
- let kind = attrs.external_kind().expect("External missing");
- let tagged = attrs.external_tagged().expect("External missing");
+ let module_path = types.module_path();
+ let name = self.identifier.0.to_string();
+ let ty = match attrs.rust_kind() {
+ Some(RustKind::Object) => Type::Object {
+ module_path,
+ name,
+ imp: ObjectImpl::Struct,
+ },
+ Some(RustKind::Trait) => Type::Object {
+ module_path,
+ name,
+ imp: ObjectImpl::Trait,
+ },
+ Some(RustKind::CallbackTrait) => Type::Object {
+ module_path,
+ name,
+ imp: ObjectImpl::CallbackTrait,
+ },
+ Some(RustKind::Record) => Type::Record { module_path, name },
+ Some(RustKind::Enum) => Type::Enum { module_path, name },
+ Some(RustKind::CallbackInterface) => Type::CallbackInterface { module_path, name },
+ // must be external
+ None => {
+ let kind = attrs.external_kind().expect("External missing kind");
+ let tagged = attrs.external_tagged().expect("External missing tagged");
+ Type::External {
+ name,
+ namespace: "".to_string(), // we don't know this yet
+ module_path: attrs.get_crate_name(),
+ kind,
+ tagged,
+ }
+ }
+ };
// A crate which can supply an `FfiConverter`.
// We don't reference `self._type`, so ideally we could insist on it being
// the literal 'extern' but that's tricky
- types.add_type_definition(
- name,
- Type::External {
- name: name.to_string(),
- namespace: "".to_string(), // we don't know this yet
- module_path: attrs.get_crate_name(),
- kind,
- tagged,
- },
- )
+ types.add_type_definition(self.identifier.0, ty)
}
}
}
@@ -152,7 +174,7 @@ impl TypeFinder for weedle::TypedefDefinition<'_> {
impl TypeFinder for weedle::CallbackInterfaceDefinition<'_> {
fn add_type_definitions_to(&self, types: &mut TypeCollector) -> Result<()> {
if self.attributes.is_some() {
- bail!("no typedef attributes are currently supported");
+ bail!("no callback interface attributes are currently supported");
}
let name = self.identifier.0.to_string();
types.add_type_definition(
diff --git a/third_party/rust/uniffi_udl/src/lib.rs b/third_party/rust/uniffi_udl/src/lib.rs
index 5e6e72a7f7..a9dad5d6c5 100644
--- a/third_party/rust/uniffi_udl/src/lib.rs
+++ b/third_party/rust/uniffi_udl/src/lib.rs
@@ -6,7 +6,7 @@
//!
//! This library is dedicated to parsing a string in a webidl syntax, as described by
//! weedle and with our own custom take on the attributes etc, pushing the boundaries
-//! of that syntax to describe a uniffi `MetatadataGroup`.
+//! of that syntax to describe a uniffi `MetadataGroup`.
//!
//! The output of this module is consumed by uniffi_bindgen to generate stuff.
diff --git a/third_party/rust/uniffi_udl/src/literal.rs b/third_party/rust/uniffi_udl/src/literal.rs
index 78f2544254..5fbf022644 100644
--- a/third_party/rust/uniffi_udl/src/literal.rs
+++ b/third_party/rust/uniffi_udl/src/literal.rs
@@ -84,8 +84,10 @@ pub(super) fn convert_default_value(
(weedle::literal::DefaultValue::String(s), Type::Enum { .. }) => {
Literal::Enum(s.0.to_string(), type_.clone())
}
- (weedle::literal::DefaultValue::Null(_), Type::Optional { .. }) => Literal::Null,
- (_, Type::Optional { inner_type, .. }) => convert_default_value(default_value, inner_type)?,
+ (weedle::literal::DefaultValue::Null(_), Type::Optional { .. }) => Literal::None,
+ (_, Type::Optional { inner_type, .. }) => Literal::Some {
+ inner: Box::new(convert_default_value(default_value, inner_type)?),
+ },
// We'll ensure the type safety in the convert_* number methods.
(weedle::literal::DefaultValue::Integer(i), _) => convert_integer(i, type_)?,
@@ -144,7 +146,7 @@ mod test {
inner_type: Box::new(Type::String)
}
)?,
- Literal::Null
+ Literal::None
));
Ok(())
}
diff --git a/third_party/rust/uniffi_udl/src/resolver.rs b/third_party/rust/uniffi_udl/src/resolver.rs
index 14a7a4c6f1..ea98cd7a99 100644
--- a/third_party/rust/uniffi_udl/src/resolver.rs
+++ b/third_party/rust/uniffi_udl/src/resolver.rs
@@ -209,7 +209,6 @@ pub(crate) fn resolve_builtin_type(name: &str) -> Option<Type> {
"f64" => Some(Type::Float64),
"timestamp" => Some(Type::Timestamp),
"duration" => Some(Type::Duration),
- "ForeignExecutor" => Some(Type::ForeignExecutor),
_ => None,
}
}