-
Notifications
You must be signed in to change notification settings - Fork 235
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added suport for using external types in proc-macros
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix #1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait. Other changes: - Adding `module_path` to the user type metadata - Added an proc-macro -> proc-macro external type test by copying the ext-types fixture into another one that uses proc macros.
- Loading branch information
Showing
35 changed files
with
1,252 additions
and
373 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
This directory contains the tests for external types -- types defined in one crate and used in a | ||
different one. | ||
|
||
- `guid` and `uniffi-one` are dependent crates that define types exported by UniFFI | ||
- `lib` is a library crate that depends on `guid` and `uniffi-one` | ||
- `proc-macro-lib` is another library crate, but this one uses proc-macros rather than UDL files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
[package] | ||
name = "uniffi-fixture-ext-types-proc-macro" | ||
edition = "2021" | ||
version = "0.22.0" | ||
authors = ["Firefox Sync Team <[email protected]>"] | ||
license = "MPL-2.0" | ||
publish = false | ||
|
||
[package.metadata.uniffi.testing] | ||
external-crates = [ | ||
"uniffi-fixture-ext-types-guid", | ||
"uniffi-fixture-ext-types-lib-one", | ||
"uniffi-example-custom-types", | ||
] | ||
|
||
[lib] | ||
crate-type = ["lib", "cdylib"] | ||
name = "uniffi_ext_types_proc_macro_lib" | ||
|
||
[dependencies] | ||
anyhow = "1" | ||
bytes = "1.3" | ||
uniffi = {path = "../../../uniffi"} | ||
|
||
uniffi-fixture-ext-types-lib-one = {path = "../uniffi-one"} | ||
uniffi-fixture-ext-types-guid = {path = "../guid"} | ||
|
||
# Reuse one of our examples. | ||
uniffi-example-custom-types = {path = "../../../examples/custom-types"} | ||
|
||
url = "2.2" | ||
|
||
[build-dependencies] | ||
uniffi = {path = "../../../uniffi", features = ["build"] } | ||
|
||
[dev-dependencies] | ||
uniffi = {path = "../../../uniffi", features = ["bindgen-tests"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/* 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/. */ | ||
|
||
fn main() { | ||
uniffi::generate_scaffolding("src/ext-types-lib.udl").unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
namespace imported_types_lib { }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
use custom_types::Handle; | ||
use ext_types_guid::Guid; | ||
use std::sync::Arc; | ||
use uniffi_one::{UniffiOneEnum, UniffiOneInterface, UniffiOneProcMacroType, UniffiOneType}; | ||
use url::Url; | ||
|
||
uniffi::use_udl_record!(uniffi_one, UniffiOneType); | ||
uniffi::use_udl_enum!(uniffi_one, UniffiOneEnum); | ||
uniffi::use_udl_object!(uniffi_one, UniffiOneInterface); | ||
uniffi::use_udl_record!(ext_types_guid, Guid); | ||
uniffi::use_udl_record!(custom_types, Url); | ||
uniffi::use_udl_record!(custom_types, Handle); | ||
|
||
#[derive(uniffi::Record)] | ||
pub struct CombinedType { | ||
pub uoe: UniffiOneEnum, | ||
pub uot: UniffiOneType, | ||
pub uots: Vec<UniffiOneType>, | ||
pub maybe_uot: Option<UniffiOneType>, | ||
|
||
pub guid: Guid, | ||
pub guids: Vec<Guid>, | ||
pub maybe_guid: Option<Guid>, | ||
|
||
pub url: Url, | ||
pub urls: Vec<Url>, | ||
pub maybe_url: Option<Url>, | ||
|
||
pub handle: Handle, | ||
pub handles: Vec<Handle>, | ||
pub maybe_handle: Option<Handle>, | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_combined_type(value: Option<CombinedType>) -> CombinedType { | ||
value.unwrap_or_else(|| CombinedType { | ||
uoe: UniffiOneEnum::One, | ||
uot: UniffiOneType { | ||
sval: "hello".to_string(), | ||
}, | ||
uots: vec![ | ||
UniffiOneType { | ||
sval: "first of many".to_string(), | ||
}, | ||
UniffiOneType { | ||
sval: "second of many".to_string(), | ||
}, | ||
], | ||
maybe_uot: None, | ||
|
||
guid: Guid("a-guid".into()), | ||
guids: vec![Guid("b-guid".into()), Guid("c-guid".into())], | ||
maybe_guid: None, | ||
|
||
url: Url::parse("http://example.com/").unwrap(), | ||
urls: vec![], | ||
maybe_url: None, | ||
|
||
handle: Handle(123), | ||
handles: vec![Handle(1), Handle(2), Handle(3)], | ||
maybe_handle: Some(Handle(4)), | ||
}) | ||
} | ||
|
||
// A Custom type | ||
#[uniffi::export] | ||
fn get_url(url: Url) -> Url { | ||
url | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_urls(urls: Vec<Url>) -> Vec<Url> { | ||
urls | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_maybe_url(url: Option<Url>) -> Option<Url> { | ||
url | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_maybe_urls(urls: Vec<Option<Url>>) -> Vec<Option<Url>> { | ||
urls | ||
} | ||
|
||
// A struct | ||
#[uniffi::export] | ||
fn get_uniffi_one_type(t: UniffiOneType) -> UniffiOneType { | ||
t | ||
} | ||
|
||
// Test using a type defined in a proc-macro in another crate | ||
#[uniffi::export] | ||
fn get_uniffi_one_proc_macro_type(t: UniffiOneProcMacroType) -> UniffiOneProcMacroType { | ||
t | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_uniffi_one_types(ts: Vec<UniffiOneType>) -> Vec<UniffiOneType> { | ||
ts | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_maybe_uniffi_one_type(t: Option<UniffiOneType>) -> Option<UniffiOneType> { | ||
t | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_maybe_uniffi_one_types(ts: Vec<Option<UniffiOneType>>) -> Vec<Option<UniffiOneType>> { | ||
ts | ||
} | ||
|
||
// An enum | ||
#[uniffi::export] | ||
fn get_uniffi_one_enum(e: UniffiOneEnum) -> UniffiOneEnum { | ||
e | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_uniffi_one_enums(es: Vec<UniffiOneEnum>) -> Vec<UniffiOneEnum> { | ||
es | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_maybe_uniffi_one_enum(e: Option<UniffiOneEnum>) -> Option<UniffiOneEnum> { | ||
e | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_maybe_uniffi_one_enums(es: Vec<Option<UniffiOneEnum>>) -> Vec<Option<UniffiOneEnum>> { | ||
es | ||
} | ||
|
||
#[uniffi::export] | ||
fn get_uniffi_one_interface() -> Arc<UniffiOneInterface> { | ||
Arc::new(UniffiOneInterface::new()) | ||
} | ||
|
||
uniffi::include_scaffolding!("ext-types-lib"); |
38 changes: 38 additions & 0 deletions
38
fixtures/ext-types/proc-macro-lib/tests/bindings/test_imported_types.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* 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/. */ | ||
|
||
import uniffi.imported_types_lib.* | ||
import uniffi.uniffi_one.* | ||
|
||
val ct = getCombinedType(null) | ||
assert(ct.uot.sval == "hello") | ||
assert(ct.guid == "a-guid") | ||
assert(ct.url == java.net.URL("http://example.com/")) | ||
|
||
val ct2 = getCombinedType(ct) | ||
assert(ct == ct2) | ||
|
||
val url = java.net.URL("http://example.com/") | ||
assert(getUrl(url) == url) | ||
assert(getMaybeUrl(url)!! == url) | ||
assert(getMaybeUrl(null) == null) | ||
assert(getUrls(listOf(url)) == listOf(url)) | ||
assert(getMaybeUrls(listOf(url, null)) == listOf(url, null)) | ||
|
||
val uot = UniffiOneType("hello") | ||
assert(getUniffiOneType(uot) == uot) | ||
assert(getMaybeUniffiOneType(uot)!! == uot) | ||
assert(getMaybeUniffiOneType(null) == null) | ||
assert(getUniffiOneTypes(listOf(uot)) == listOf(uot)) | ||
assert(getMaybeUniffiOneTypes(listOf(uot, null)) == listOf(uot, null)) | ||
|
||
val uopmt = UniffiOneProcMacroType("hello from proc-macro world") | ||
assert(getUniffiOneProcMacroType(uopmt) == uopmt) | ||
|
||
val uoe = UniffiOneEnum.ONE | ||
assert(getUniffiOneEnum(uoe) == uoe) | ||
assert(getMaybeUniffiOneEnum(uoe)!! == uoe) | ||
assert(getMaybeUniffiOneEnum(null) == null) | ||
assert(getUniffiOneEnums(listOf(uoe)) == listOf(uoe)) | ||
assert(getMaybeUniffiOneEnums(listOf(uoe, null)) == listOf(uoe, null)) |
52 changes: 52 additions & 0 deletions
52
fixtures/ext-types/proc-macro-lib/tests/bindings/test_imported_types.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# 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/. */ | ||
|
||
import unittest | ||
import urllib | ||
from imported_types_lib import * | ||
from uniffi_one import * | ||
|
||
class TestIt(unittest.TestCase): | ||
def test_it(self): | ||
ct = get_combined_type(None) | ||
self.assertEqual(ct.uot.sval, "hello") | ||
self.assertEqual(ct.guid, "a-guid") | ||
self.assertEqual(ct.url.scheme, 'http') | ||
self.assertEqual(ct.url.netloc, 'example.com') | ||
self.assertEqual(ct.url.path, '/') | ||
|
||
ct2 = get_combined_type(ct) | ||
self.assertEqual(ct, ct2) | ||
|
||
def test_get_url(self): | ||
url = urllib.parse.urlparse("http://example.com/") | ||
self.assertEqual(get_url(url), url) | ||
self.assertEqual(get_urls([url]), [url]) | ||
self.assertEqual(get_maybe_url(url), url) | ||
self.assertEqual(get_maybe_url(None), None) | ||
self.assertEqual(get_maybe_urls([url, None]), [url, None]) | ||
|
||
def test_get_uniffi_one_type(self): | ||
t1 = UniffiOneType("hello") | ||
self.assertEqual(t1, get_uniffi_one_type(t1)) | ||
self.assertEqual(t1, get_maybe_uniffi_one_type(t1)) | ||
self.assertEqual(None, get_maybe_uniffi_one_type(None)) | ||
self.assertEqual([t1], get_uniffi_one_types([t1])) | ||
self.assertEqual([t1, None], get_maybe_uniffi_one_types([t1, None])) | ||
|
||
def test_get_uniffi_one_proc_macro_type(self): | ||
t1 = UniffiOneProcMacroType("hello") | ||
self.assertEqual(t1, get_uniffi_one_proc_macro_type(t1)) | ||
|
||
def test_get_uniffi_one_enum(self): | ||
e = UniffiOneEnum.ONE | ||
self.assertEqual(e, get_uniffi_one_enum(e)) | ||
self.assertEqual(e, get_maybe_uniffi_one_enum(e)) | ||
self.assertEqual(None, get_maybe_uniffi_one_enum(None)) | ||
self.assertEqual([e], get_uniffi_one_enums([e])) | ||
self.assertEqual([e, None], get_maybe_uniffi_one_enums([e, None])) | ||
|
||
|
||
if __name__=='__main__': | ||
unittest.main() |
36 changes: 36 additions & 0 deletions
36
fixtures/ext-types/proc-macro-lib/tests/bindings/test_imported_types.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* 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/. */ | ||
|
||
import imported_types_lib | ||
//import uniffi_one | ||
import Foundation | ||
|
||
let ct = getCombinedType(value: nil) | ||
assert(ct.uot.sval == "hello") | ||
assert(ct.guid == "a-guid") | ||
assert(ct.url == URL(string: "http://example.com/")) | ||
|
||
let ct2 = getCombinedType(value: ct) | ||
assert(ct == ct2) | ||
|
||
let url = URL(string: "http://example.com/")!; | ||
assert(getUrl(url: url) == url) | ||
assert(getMaybeUrl(url: url)! == url) | ||
assert(getMaybeUrl(url: nil) == nil) | ||
assert(getUrls(urls: [url]) == [url]) | ||
assert(getMaybeUrls(urls: [url, nil]) == [url, nil]) | ||
|
||
assert(getUniffiOneType(t: UniffiOneType(sval: "hello")).sval == "hello") | ||
assert(getMaybeUniffiOneType(t: UniffiOneType(sval: "hello"))!.sval == "hello") | ||
assert(getMaybeUniffiOneType(t: nil) == nil) | ||
assert(getUniffiOneTypes(ts: [UniffiOneType(sval: "hello")]) == [UniffiOneType(sval: "hello")]) | ||
assert(getMaybeUniffiOneTypes(ts: [UniffiOneType(sval: "hello"), nil]) == [UniffiOneType(sval: "hello"), nil]) | ||
|
||
assert(getUniffiOneProcMacroType(t: UniffiOneProcMacroType(sval: "hello from proc-macro world")).sval == "hello from proc-macro world") | ||
|
||
assert(getUniffiOneEnum(e: UniffiOneEnum.one) == UniffiOneEnum.one) | ||
assert(getMaybeUniffiOneEnum(e: UniffiOneEnum.one)! == UniffiOneEnum.one) | ||
assert(getMaybeUniffiOneEnum(e: nil) == nil) | ||
assert(getUniffiOneEnums(es: [UniffiOneEnum.one]) == [UniffiOneEnum.one]) | ||
assert(getMaybeUniffiOneEnums(es: [UniffiOneEnum.one, nil]) == [UniffiOneEnum.one, nil]) |
5 changes: 5 additions & 0 deletions
5
fixtures/ext-types/proc-macro-lib/tests/test_generated_bindings.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
uniffi::build_foreign_language_testcases!( | ||
"tests/bindings/test_imported_types.kts", | ||
"tests/bindings/test_imported_types.py", | ||
"tests/bindings/test_imported_types.swift", | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.