зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1914241 - Upgrade UniFFI to 0.28.1, r=glandium,supply-chain-reviewers
- Ran `cargo update -p glean` - Removed build/rust/heck now that everything depends on 0.5. - Ran `mach vendor rust` Differential Revision: https://phabricator.services.mozilla.com/D219800
This commit is contained in:
Родитель
5fe168ff7d
Коммит
415d48c0cb
|
@ -60,9 +60,9 @@ git = "https://github.com/mozilla-spidermonkey/jsparagus"
|
|||
rev = "61f399c53a641ebd3077c1f39f054f6d396a633c"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"]
|
||||
[source."git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16"]
|
||||
git = "https://github.com/mozilla/application-services"
|
||||
rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/audioipc?rev=e6f44a2bd1e57d11dfc737632a9e849077632330"]
|
||||
|
|
|
@ -826,7 +826,7 @@ version = "4.5.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -1708,7 +1708,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "error-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"error-support-macros",
|
||||
"lazy_static",
|
||||
|
@ -1720,7 +1720,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "error-support-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -2411,9 +2411,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean"
|
||||
version = "60.5.0"
|
||||
version = "61.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cc81e8412d413d9f97ab91cce6a7d40bf11b0a03f8dcd3112cd1334a5e61086"
|
||||
checksum = "873a0621989a5eac9c9a23f47c217a74a1b1587fdc0c6c764c06567ba286e027"
|
||||
dependencies = [
|
||||
"glean-core",
|
||||
"inherent",
|
||||
|
@ -2424,9 +2424,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glean-core"
|
||||
version = "60.5.0"
|
||||
version = "61.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de1ecd4c5de0b0ecad949e29f6973bfaa4d53b668ebccdd5bc1a1f2591d0271"
|
||||
checksum = "bfd39741d1790f1022b0bf65d7b4a73fbb7a646158e0c96a0c845b097cce2ba2"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"bincode",
|
||||
|
@ -2664,13 +2664,6 @@ dependencies = [
|
|||
"http",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.999"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
|
@ -3043,7 +3036,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "interrupt-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot",
|
||||
|
@ -4257,7 +4250,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "nss_build_common"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
|
||||
[[package]]
|
||||
name = "nsstring"
|
||||
|
@ -4470,7 +4463,7 @@ checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
|||
[[package]]
|
||||
name = "payload-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
@ -4942,7 +4935,7 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
|||
[[package]]
|
||||
name = "relevancy"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64 0.21.3",
|
||||
|
@ -4965,7 +4958,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "remote_settings"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"log",
|
||||
"parking_lot",
|
||||
|
@ -5523,7 +5516,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sql-support"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"interrupt-support",
|
||||
|
@ -5705,7 +5698,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
|||
[[package]]
|
||||
name = "suggest"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
@ -5757,7 +5750,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sync-guid"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"base64 0.21.3",
|
||||
"rand",
|
||||
|
@ -5768,7 +5761,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "sync15"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
@ -5800,7 +5793,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "tabs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
@ -6125,7 +6118,7 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
|||
[[package]]
|
||||
name = "types"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"rusqlite",
|
||||
"serde",
|
||||
|
@ -6214,11 +6207,12 @@ checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
|
|||
|
||||
[[package]]
|
||||
name = "uniffi"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb3a4c447c50fcda7bc5604a8588b7e1f37ffbfd8838a1516a290398efa7c6f0"
|
||||
checksum = "2db87def739fe4183947f8419d572d1849a4a09355eba4e988a2105cfd0ac6a7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_metadata",
|
||||
"uniffi_bindgen",
|
||||
"uniffi_build",
|
||||
"uniffi_core",
|
||||
|
@ -6234,7 +6228,7 @@ dependencies = [
|
|||
"camino",
|
||||
"clap",
|
||||
"extend",
|
||||
"heck 0.4.999",
|
||||
"heck",
|
||||
"serde",
|
||||
"toml",
|
||||
"uniffi",
|
||||
|
@ -6316,9 +6310,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_bindgen"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0be2bc6bafd82c979b0faca77c7b26630d54017de9f5bd5a686ec6ef038ad5d9"
|
||||
checksum = "7a112599c9556d1581e4a3d72019a74c2c3e122cc27f4af12577a429c4d5e614"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"askama",
|
||||
|
@ -6327,7 +6321,7 @@ dependencies = [
|
|||
"fs-err",
|
||||
"glob",
|
||||
"goblin 0.8.1",
|
||||
"heck 0.4.999",
|
||||
"heck",
|
||||
"once_cell",
|
||||
"paste",
|
||||
"serde",
|
||||
|
@ -6340,9 +6334,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_build"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c59b65d59685ff3a10569287c6419f76487b4052ac52d5a0df38b2253d7f440"
|
||||
checksum = "e2b12684401d2a8508ca9c72a95bbc45906417e42fc80942abaf033bbf01aa33"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
|
@ -6351,9 +6345,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_checksum_derive"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5c400339a9d1d17be34257d0b407e91d64af335e5b4fa49f4bf28467fc8d635"
|
||||
checksum = "a22dbe67c1c957ac6e7611bdf605a6218aa86b0eebeb8be58b70ae85ad7d73dc"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
|
@ -6361,9 +6355,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_core"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a02e67ac9634b10da9e4aa63a29a7920b8f1395eafef1ea659b2dd76dda96906"
|
||||
checksum = "5a0c35aaad30e3a9e6d4fe34e358d64dbc92ee09045b48591b05fc9f12e0905b"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
@ -6376,9 +6370,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_macros"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6f08d5592c669b80a8af5066027098bebec4b4af17a9b8b299bac5f518ab89e"
|
||||
checksum = "db66474c5c61b0f7afc3b4995fecf9b72b340daa5ca0ef3da7778d75eb5482ea"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"camino",
|
||||
|
@ -6394,9 +6388,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_meta"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "583bab49f2bdf5681f9732f8b67a7e555ad920dbb5427be21450217bf1818189"
|
||||
checksum = "d898893f102e0e39b8bcb7e3d2188f4156ba280db32db9e8af1f122d057e9526"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
|
@ -6406,9 +6400,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_testing"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13963044ca9bde9b709d2eee68bc11dafc7acea144ae0fdc0cf29ed4add44481"
|
||||
checksum = "2c6aa4f0cf9d12172d84fc00a35a6c1f3522b526daad05ae739f709f6941b9b6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
|
@ -6419,9 +6413,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "uniffi_udl"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b92f984bb0d9a06778f256aec963e1e9a80714014f7a90fb0e01008821fe5a97"
|
||||
checksum = "6b044e9c519e0bb51e516ab6f6d8f4f4dcf900ce30d5ad07c03f924e2824f28e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"textwrap",
|
||||
|
@ -6492,7 +6486,7 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
|||
[[package]]
|
||||
name = "viaduct"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"ffi-support",
|
||||
"log",
|
||||
|
@ -6640,7 +6634,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webext-storage"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=dbeaef2eb28e9da7cc2f96e26296513cc4e07c07#dbeaef2eb28e9da7cc2f96e26296513cc4e07c07"
|
||||
source = "git+https://github.com/mozilla/application-services?rev=6651984e3b456d99fad0df1deb727b7c2f62ec16#6651984e3b456d99fad0df1deb727b7c2f62ec16"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"error-support",
|
||||
|
|
23
Cargo.toml
23
Cargo.toml
|
@ -55,8 +55,8 @@ resolver = "2"
|
|||
|
||||
[workspace.dependencies]
|
||||
# Shared across multiple UniFFI consumers.
|
||||
uniffi = "0.27.3"
|
||||
uniffi_bindgen = "0.27.3"
|
||||
uniffi = "0.28.1"
|
||||
uniffi_bindgen = "0.28.1"
|
||||
# Shared across multiple application-services consumers.
|
||||
rusqlite = "0.31.0"
|
||||
# Shared across multiple glean consumers.
|
||||
|
@ -172,9 +172,6 @@ hashbrown = { path = "build/rust/hashbrown" }
|
|||
# Patch `socket2` 0.4 to 0.5
|
||||
socket2 = { path = "build/rust/socket2" }
|
||||
|
||||
# Patch heck 0.4 to 0.5
|
||||
heck = { path = "build/rust/heck" }
|
||||
|
||||
# The following overrides point to dummy projects, as a temporary measure until this is resolved:
|
||||
# https://github.com/rust-lang/cargo/issues/6179
|
||||
js-sys = { path = "build/rust/dummy-web/js-sys" }
|
||||
|
@ -213,14 +210,14 @@ midir = { git = "https://github.com/mozilla/midir.git", rev = "85156e360a37d8517
|
|||
malloc_size_of_derive = { path = "xpcom/rust/malloc_size_of_derive" }
|
||||
|
||||
# application-services overrides to make updating them all simpler.
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
relevancy = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
suggest = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" }
|
||||
interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
relevancy = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
sql-support = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
suggest = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
sync15 = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
tabs = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" }
|
||||
|
||||
# Patch `gpu-descriptor` 0.3.0 to remove unnecessary `allocator-api2` dep.:
|
||||
# Still waiting for the now-merged <https://github.com/zakarumych/gpu-descriptor/pull/40> to be released.
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[package]
|
||||
name = "heck"
|
||||
version = "0.4.999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.heck]
|
||||
version = "0.5.0"
|
|
@ -1,5 +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/. */
|
||||
|
||||
pub use heck::*;
|
|
@ -260,6 +260,13 @@ user-id = 48
|
|||
user-login = "badboy"
|
||||
user-name = "Jan-Erik Rediger"
|
||||
|
||||
[[publisher.glean]]
|
||||
version = "61.0.0"
|
||||
when = "2024-08-21"
|
||||
user-id = 48
|
||||
user-login = "badboy"
|
||||
user-name = "Jan-Erik Rediger"
|
||||
|
||||
[[publisher.glean-core]]
|
||||
version = "60.5.0"
|
||||
when = "2024-08-06"
|
||||
|
@ -267,6 +274,13 @@ user-id = 48
|
|||
user-login = "badboy"
|
||||
user-name = "Jan-Erik Rediger"
|
||||
|
||||
[[publisher.glean-core]]
|
||||
version = "61.0.0"
|
||||
when = "2024-08-21"
|
||||
user-id = 48
|
||||
user-login = "badboy"
|
||||
user-name = "Jan-Erik Rediger"
|
||||
|
||||
[[publisher.glslopt]]
|
||||
version = "0.1.11"
|
||||
when = "2024-08-30"
|
||||
|
@ -684,54 +698,108 @@ when = "2024-06-03"
|
|||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_bindgen]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_bindgen]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_build]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_build]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_checksum_derive]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_checksum_derive]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_core]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_core]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_macros]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_macros]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_meta]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_meta]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_testing]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_testing]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_udl]]
|
||||
version = "0.27.3"
|
||||
when = "2024-06-03"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.uniffi_udl]]
|
||||
version = "0.28.1"
|
||||
when = "2024-08-13"
|
||||
user-id = 127697
|
||||
user-login = "bendk"
|
||||
|
||||
[[publisher.utf8_iter]]
|
||||
version = "1.0.4"
|
||||
when = "2023-12-01"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"94e027935f3f804f464831ad7717936e7068517252b1f0e6fd0a025220bc2c35","README.md":"99fb739e79beb2c2d34f38d502cd758a1470b3ecf22c8f7fb05b97f324918cf4","build.rs":"c8d3c38c1208eea36224662b284d8daf3e7ad1b07d22d750524f3da1cc66ccca","src/errorsupport.udl":"e793034d01a2608298528051757f38405e006ee1abc4cf65dc6f18c53590ace8","src/handling.rs":"6e0568b18d426531cb2ae9967c8dd0d51ece5a065f68b15eeb308b995edaa167","src/lib.rs":"96ae3cc2c1077ae45442ace6b5b5311b86267d0b9067f3ff58396af30ccbbc07","src/macros.rs":"0d03f82fab20c96a182f941baf3fcf2a286b00fea871ee7fd8e339abc14f9522","src/redact.rs":"c9a4df1a87be68b15d583587bda941d4c60a1d0449e2d43ff99f3611a290a863","src/reporting.rs":"b8e03402edf3111718fc9c2ec179622307f4a117db05ac220ead631c9de28362","uniffi.toml":"644fe81c12fe3c01ee81e017ca3c00d0e611f014b7eade51aadaf208179a3450"},"package":null}
|
||||
{"files":{"Cargo.toml":"22d7cc070ecb4984a9b1112f737454bf00330efc13d39283859e065e9a12c494","README.md":"99fb739e79beb2c2d34f38d502cd758a1470b3ecf22c8f7fb05b97f324918cf4","build.rs":"c8d3c38c1208eea36224662b284d8daf3e7ad1b07d22d750524f3da1cc66ccca","src/errorsupport.udl":"e793034d01a2608298528051757f38405e006ee1abc4cf65dc6f18c53590ace8","src/handling.rs":"6e0568b18d426531cb2ae9967c8dd0d51ece5a065f68b15eeb308b995edaa167","src/lib.rs":"96ae3cc2c1077ae45442ace6b5b5311b86267d0b9067f3ff58396af30ccbbc07","src/macros.rs":"0d03f82fab20c96a182f941baf3fcf2a286b00fea871ee7fd8e339abc14f9522","src/redact.rs":"c9a4df1a87be68b15d583587bda941d4c60a1d0449e2d43ff99f3611a290a863","src/reporting.rs":"b8e03402edf3111718fc9c2ec179622307f4a117db05ac220ead631c9de28362","uniffi.toml":"644fe81c12fe3c01ee81e017ca3c00d0e611f014b7eade51aadaf208179a3450"},"package":null}
|
|
@ -49,8 +49,8 @@ version = "1.4"
|
|||
version = ">=0.11,<=0.12"
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -11,13 +11,14 @@
|
|||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
rust-version = "1.76"
|
||||
name = "glean-core"
|
||||
version = "60.5.0"
|
||||
version = "61.0.0"
|
||||
authors = [
|
||||
"Jan-Erik Rediger <jrediger@mozilla.com>",
|
||||
"The Glean Team <glean-team@mozilla.com>",
|
||||
]
|
||||
build = "build.rs"
|
||||
include = [
|
||||
"/README.md",
|
||||
"/LICENSE",
|
||||
|
@ -28,6 +29,10 @@ include = [
|
|||
"/uniffi.toml",
|
||||
"/build.rs",
|
||||
]
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "A modern Telemetry library"
|
||||
readme = "README.md"
|
||||
keywords = ["telemetry"]
|
||||
|
@ -35,7 +40,87 @@ license = "MPL-2.0"
|
|||
repository = "https://github.com/mozilla/glean"
|
||||
|
||||
[package.metadata.glean]
|
||||
glean-parser = "14.5.1"
|
||||
glean-parser = "15.0.0"
|
||||
|
||||
[lib]
|
||||
name = "glean_core"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "boolean"
|
||||
path = "tests/boolean.rs"
|
||||
|
||||
[[test]]
|
||||
name = "counter"
|
||||
path = "tests/counter.rs"
|
||||
|
||||
[[test]]
|
||||
name = "custom_distribution"
|
||||
path = "tests/custom_distribution.rs"
|
||||
|
||||
[[test]]
|
||||
name = "datetime"
|
||||
path = "tests/datetime.rs"
|
||||
|
||||
[[test]]
|
||||
name = "event"
|
||||
path = "tests/event.rs"
|
||||
|
||||
[[test]]
|
||||
name = "labeled"
|
||||
path = "tests/labeled.rs"
|
||||
|
||||
[[test]]
|
||||
name = "memory_distribution"
|
||||
path = "tests/memory_distribution.rs"
|
||||
|
||||
[[test]]
|
||||
name = "object"
|
||||
path = "tests/object.rs"
|
||||
|
||||
[[test]]
|
||||
name = "ping"
|
||||
path = "tests/ping.rs"
|
||||
|
||||
[[test]]
|
||||
name = "ping_maker"
|
||||
path = "tests/ping_maker.rs"
|
||||
|
||||
[[test]]
|
||||
name = "quantity"
|
||||
path = "tests/quantity.rs"
|
||||
|
||||
[[test]]
|
||||
name = "rate"
|
||||
path = "tests/rate.rs"
|
||||
|
||||
[[test]]
|
||||
name = "storage"
|
||||
path = "tests/storage.rs"
|
||||
|
||||
[[test]]
|
||||
name = "string"
|
||||
path = "tests/string.rs"
|
||||
|
||||
[[test]]
|
||||
name = "string_list"
|
||||
path = "tests/string_list.rs"
|
||||
|
||||
[[test]]
|
||||
name = "text"
|
||||
path = "tests/text.rs"
|
||||
|
||||
[[test]]
|
||||
name = "timespan"
|
||||
path = "tests/timespan.rs"
|
||||
|
||||
[[test]]
|
||||
name = "timing_distribution"
|
||||
path = "tests/timing_distribution.rs"
|
||||
|
||||
[[test]]
|
||||
name = "uuid"
|
||||
path = "tests/uuid.rs"
|
||||
|
||||
[dependencies.bincode]
|
||||
version = "1.2.1"
|
||||
|
@ -80,7 +165,7 @@ version = "1.0.4"
|
|||
version = "0.1.40"
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.0"
|
||||
version = "0.28.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.uuid]
|
||||
|
@ -105,18 +190,18 @@ version = "0.4"
|
|||
version = "3.8.0"
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.0"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
enable_env_logger = ["env_logger"]
|
||||
|
||||
[target."cfg(target_os = \"android\")".dependencies.android_logger]
|
||||
[target.'cfg(target_os = "android")'.dependencies.android_logger]
|
||||
version = "0.12.0"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_os = \"ios\")".dependencies.oslog]
|
||||
[target.'cfg(target_os = "ios")'.dependencies.oslog]
|
||||
version = "0.1.0"
|
||||
features = ["logger"]
|
||||
default-features = false
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"5b1a36e1b3e8c0c1447c8b5a588cbb517df27d742ce4e99517d909dc815245af","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"de65ab99a26b4547be20803bc195cb50a6ab40b1a3f49a2e6230fed5a9d7a8d8","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"e954d51943bb351ce56cdabe673edc1f39aa7b5e06839432da7329c68f472945","src/net/http_uploader.rs":"01ad5bd91384411a12c74434cd1c5cd585078cb34faba4615c70bdb669a9bccb","src/net/mod.rs":"f47b96bb878f1a6c771cedbaeaeefb270bc87fb1d1bbbed1b282dddca16216ed","src/private/event.rs":"d7c70c02648584c19c73af89e5180d3c6153c911f2c6830f7d1599b18d6150eb","src/private/mod.rs":"3565eb569d2b96f938f130abe0fc3ee3f55e7e03fd6501e309d3ef6af72ef6ee","src/private/object.rs":"0926261074af905c775494b42217f636548e74c3ad798478481bc0cd2fdf5c48","src/private/ping.rs":"31d33d7f661a7a17ccb69351328700b4d7b80024d1e128f406c3534f9d163475","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"d7ad78bd853b2b22e3740fb8d3c15675286d3a050a7bfb586dbbe7003f74c388","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"46d7064bba9386c3065635434e17ac9212c6c2236b3cd12bd985fc3229e659a3","tests/never_init.rs":"7a6e8a011fbd945f2544f204367eeceff3f6039c99d98799477e3b2352ae6227","tests/no_time_to_init.rs":"4a5bdddc2f8226d2ad17038229e8767a6dd195977af49527fbb84a9f6b0154bb","tests/overflowing_preinit.rs":"985e140460a100986fd051ce901b787a3a7a9747a856cd06066b740ac7d2381c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"dde65bce8a715ca3bd9c54b2466d831dd5e0d559e0773fe7657827f22a66bb44","tests/simple.rs":"1835b5df6f76ff894b45805bd54eaab23ca2d9d2b0694ec64af3aa6132baf30e","tests/test-delayed-ping-data.sh":"6d6537216e04dc7a8deaf02e694307e1ed983bfacffab16e8a96e0a94679da33","tests/test-ping-lifetime-flush.sh":"e8f118ea2f6fd973809e38d5e828a03cfccfe0b0f497ccde5ec92d6d1380c071","tests/test-shutdown-blocking.sh":"a44d8d4bbe2ee3ede9e48121150ae7a5386025160c5cef2181ca142232c5fb27","tests/test-thread-crashing.sh":"a342753014bd6e9ac0840a0c7cabcda180a297c8ef532be39570190794b5bfad","tests/timing_distribution_single_sample.rs":"fddf2f13f1620a8808029d250a64e4c822828bf80b4bb4f9e3b645ab70643f9b","tests/upload_timing.rs":"6a97aa355d808123af0914ffecf1da0ecb2cc441c95c63c600b14f97ce0d45a0"},"package":"4cc81e8412d413d9f97ab91cce6a7d40bf11b0a03f8dcd3112cd1334a5e61086"}
|
||||
{"files":{"Cargo.toml":"e7c232a62bcf0588d034687e8f7758a0e4457aca71eba65e6c64de99bfec2891","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"de65ab99a26b4547be20803bc195cb50a6ab40b1a3f49a2e6230fed5a9d7a8d8","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"e954d51943bb351ce56cdabe673edc1f39aa7b5e06839432da7329c68f472945","src/net/http_uploader.rs":"01ad5bd91384411a12c74434cd1c5cd585078cb34faba4615c70bdb669a9bccb","src/net/mod.rs":"f47b96bb878f1a6c771cedbaeaeefb270bc87fb1d1bbbed1b282dddca16216ed","src/private/event.rs":"d7c70c02648584c19c73af89e5180d3c6153c911f2c6830f7d1599b18d6150eb","src/private/mod.rs":"3565eb569d2b96f938f130abe0fc3ee3f55e7e03fd6501e309d3ef6af72ef6ee","src/private/object.rs":"0926261074af905c775494b42217f636548e74c3ad798478481bc0cd2fdf5c48","src/private/ping.rs":"31d33d7f661a7a17ccb69351328700b4d7b80024d1e128f406c3534f9d163475","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"d7ad78bd853b2b22e3740fb8d3c15675286d3a050a7bfb586dbbe7003f74c388","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"46d7064bba9386c3065635434e17ac9212c6c2236b3cd12bd985fc3229e659a3","tests/never_init.rs":"7a6e8a011fbd945f2544f204367eeceff3f6039c99d98799477e3b2352ae6227","tests/no_time_to_init.rs":"4a5bdddc2f8226d2ad17038229e8767a6dd195977af49527fbb84a9f6b0154bb","tests/overflowing_preinit.rs":"985e140460a100986fd051ce901b787a3a7a9747a856cd06066b740ac7d2381c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"dde65bce8a715ca3bd9c54b2466d831dd5e0d559e0773fe7657827f22a66bb44","tests/simple.rs":"1835b5df6f76ff894b45805bd54eaab23ca2d9d2b0694ec64af3aa6132baf30e","tests/test-delayed-ping-data.sh":"6d6537216e04dc7a8deaf02e694307e1ed983bfacffab16e8a96e0a94679da33","tests/test-ping-lifetime-flush.sh":"e8f118ea2f6fd973809e38d5e828a03cfccfe0b0f497ccde5ec92d6d1380c071","tests/test-shutdown-blocking.sh":"a44d8d4bbe2ee3ede9e48121150ae7a5386025160c5cef2181ca142232c5fb27","tests/test-thread-crashing.sh":"a342753014bd6e9ac0840a0c7cabcda180a297c8ef532be39570190794b5bfad","tests/timing_distribution_single_sample.rs":"fddf2f13f1620a8808029d250a64e4c822828bf80b4bb4f9e3b645ab70643f9b","tests/upload_timing.rs":"6a97aa355d808123af0914ffecf1da0ecb2cc441c95c63c600b14f97ce0d45a0"},"package":"873a0621989a5eac9c9a23f47c217a74a1b1587fdc0c6c764c06567ba286e027"}
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.66"
|
||||
rust-version = "1.76"
|
||||
name = "glean"
|
||||
version = "60.5.0"
|
||||
version = "61.0.0"
|
||||
authors = [
|
||||
"Jan-Erik Rediger <jrediger@mozilla.com>",
|
||||
"The Glean Team <glean-team@mozilla.com>",
|
||||
|
@ -80,7 +80,7 @@ name = "upload_timing"
|
|||
path = "tests/upload_timing.rs"
|
||||
|
||||
[dependencies.glean-core]
|
||||
version = "60.5.0"
|
||||
version = "61.0.0"
|
||||
|
||||
[dependencies.inherent]
|
||||
version = "1"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"43f4bde7de7da5eb46d786bb77c57d7d120573c41e41387a3b89b0158810b9e8","README.md":"7f1418b4a7c138ba20bcaea077fe6cf0d6ffbaf6df6b90c80efc52aa0d0e2e9f","build.rs":"49840f26c73c5db19cb4e7f02930e49d7a19648168b83f2313ac1a0303c103df","src/error.rs":"b83cbe8abd22a9d687508d236a2a77e28b3fc6c39673633e5820cc0e3fc86cba","src/interrupt_support.udl":"31181937f89dbc229837484dec47a228955bb1b6c47d3b049d91f23cbe7dc069","src/interruptee.rs":"c56f9ac610d0b24a128a907266432287558c4b73f6c24b82674ca7894181d18f","src/lib.rs":"cf44a84310913be5264e1c4a3e004a9f7a6cd82d01a109bb6ac4d6002b5dd560","src/shutdown.rs":"e4b7a89f1ef319646aee3282a0d60465c3dbf571c52a0295f3b1a8909f345818","src/sql.rs":"db9b93fb2fe813ae0af6313082f07fad0e381691290466a7ac67bec14024722d"},"package":null}
|
||||
{"files":{"Cargo.toml":"397be256cf13b9107c6610189b6d22951110ed120adf06c9354f67b1e6bc3472","README.md":"7f1418b4a7c138ba20bcaea077fe6cf0d6ffbaf6df6b90c80efc52aa0d0e2e9f","build.rs":"49840f26c73c5db19cb4e7f02930e49d7a19648168b83f2313ac1a0303c103df","src/error.rs":"b83cbe8abd22a9d687508d236a2a77e28b3fc6c39673633e5820cc0e3fc86cba","src/interrupt_support.udl":"31181937f89dbc229837484dec47a228955bb1b6c47d3b049d91f23cbe7dc069","src/interruptee.rs":"c56f9ac610d0b24a128a907266432287558c4b73f6c24b82674ca7894181d18f","src/lib.rs":"cf44a84310913be5264e1c4a3e004a9f7a6cd82d01a109bb6ac4d6002b5dd560","src/shutdown.rs":"e4b7a89f1ef319646aee3282a0d60465c3dbf571c52a0295f3b1a8909f345818","src/sql.rs":"db9b93fb2fe813ae0af6313082f07fad0e381691290466a7ac67bec14024722d"},"package":null}
|
|
@ -45,8 +45,8 @@ features = [
|
|||
]
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"836ed62b1d856eb26b77f53d493585c7db861a12ba77eb481591c332cb9e8c18","build.rs":"a562bfe527d21c4e8a1a44b892defa83cdff141ec5dd51ed6f3862330e50ddd7","src/bin/generate-test-data.rs":"7f1c9dc445418c7627f89d1f2aa8e550d0f85b3d1f05edb7c378ab9441714f1f","src/db.rs":"84fa47dc54f113769ce9ec6f827c8813abed61d5e5fc82404816266703a5c668","src/error.rs":"bda332098f9759e4250c725b09d82704ba03c9ad87dc761414fa21f40220acf5","src/ingest.rs":"58bb3ed984aa5a9becb405793832e578586be744d3c4a1c411fdfb7ff48c55dd","src/interest.rs":"73baa578b40b96d13899016b14087c9ac37b754c1311e2798b1d09c719447751","src/lib.rs":"214fdbeb25e0753ef132245e6892d77cad0ddd87c96d9bdd7f3427bc5d11091e","src/relevancy.udl":"9f463bbc2a7ef28358ffbfe832e62ddd6127888c484576466c759b127a55c4b2","src/rs.rs":"cff2351c9e1b45bb67ee945650fd74b45ed48815851e58b8dbf39e66a30c10a3","src/schema.rs":"919f4d1d3654bad966c5ce93ac157dc17cac2f35e7b8c2efc471b9af562555db","src/url_hash.rs":"2e908316fb70923644d1990dbf470d69ce2f5e99b0c5c3d95ec691590be8ffa5","test-data":"1ef2cd092d59e7e126cd4a514af983d449ed9f9c98708702fd237464a76c2b5e"},"package":null}
|
||||
{"files":{"Cargo.toml":"10efb23c7a9d00473bc958f109160368361e4f79dd67967b8c00179c5c126de4","build.rs":"a562bfe527d21c4e8a1a44b892defa83cdff141ec5dd51ed6f3862330e50ddd7","src/bin/generate-test-data.rs":"7f1c9dc445418c7627f89d1f2aa8e550d0f85b3d1f05edb7c378ab9441714f1f","src/db.rs":"84fa47dc54f113769ce9ec6f827c8813abed61d5e5fc82404816266703a5c668","src/error.rs":"bda332098f9759e4250c725b09d82704ba03c9ad87dc761414fa21f40220acf5","src/ingest.rs":"58bb3ed984aa5a9becb405793832e578586be744d3c4a1c411fdfb7ff48c55dd","src/interest.rs":"73baa578b40b96d13899016b14087c9ac37b754c1311e2798b1d09c719447751","src/lib.rs":"214fdbeb25e0753ef132245e6892d77cad0ddd87c96d9bdd7f3427bc5d11091e","src/relevancy.udl":"9f463bbc2a7ef28358ffbfe832e62ddd6127888c484576466c759b127a55c4b2","src/rs.rs":"cff2351c9e1b45bb67ee945650fd74b45ed48815851e58b8dbf39e66a30c10a3","src/schema.rs":"919f4d1d3654bad966c5ce93ac157dc17cac2f35e7b8c2efc471b9af562555db","src/url_hash.rs":"2e908316fb70923644d1990dbf470d69ce2f5e99b0c5c3d95ec691590be8ffa5","test-data":"1ef2cd092d59e7e126cd4a514af983d449ed9f9c98708702fd237464a76c2b5e"},"package":null}
|
|
@ -69,8 +69,8 @@ features = ["derive"]
|
|||
path = "../support/sql"
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"fc7859a498493f1ede9c5c62b857ec76e3e9e8097cfd8c4f3d779f268b250303","build.rs":"4326f03729cf8f1673e4228e6dc111de1ea4d8bcc06351f7ae563efb2613f866","src/cache.rs":"9c16f17353730103d57132a0f055863b085d2d3eb3a78f6a6f8d095f897d0c0d","src/client.rs":"1c589317907d21745e945dfd992c11535aaafcaca9a6ebe33a5a7c2e2cb93997","src/config.rs":"52a209256acd8b1fada2b91e9d9f669df0ee6e9609baad7ec34a2111ed2a6541","src/error.rs":"4bb15cd7f6ebc438119f36291ab0eb951fe2fb05e166445817cb05aa89397000","src/lib.rs":"ff1b9f66ae6069005d36c84b296f22424b4305a5873353e351fbe057f126e140","src/remote_settings.udl":"1ffeb10385e4db63606cda79bb59e77170af1d2ca0028da8ab2c4d7622969734","uniffi.toml":"f8ec8dc593e0d501c2e9e40368ec93ec33b1edd8608e29495e0a54b63144e880"},"package":null}
|
||||
{"files":{"Cargo.toml":"945724993504a7b031f184382d3ced10b55eb6f096000369bb779aa50097ec94","build.rs":"4326f03729cf8f1673e4228e6dc111de1ea4d8bcc06351f7ae563efb2613f866","src/cache.rs":"9c16f17353730103d57132a0f055863b085d2d3eb3a78f6a6f8d095f897d0c0d","src/client.rs":"1c589317907d21745e945dfd992c11535aaafcaca9a6ebe33a5a7c2e2cb93997","src/config.rs":"52a209256acd8b1fada2b91e9d9f669df0ee6e9609baad7ec34a2111ed2a6541","src/error.rs":"4bb15cd7f6ebc438119f36291ab0eb951fe2fb05e166445817cb05aa89397000","src/lib.rs":"ff1b9f66ae6069005d36c84b296f22424b4305a5873353e351fbe057f126e140","src/remote_settings.udl":"1ffeb10385e4db63606cda79bb59e77170af1d2ca0028da8ab2c4d7622969734","uniffi.toml":"f8ec8dc593e0d501c2e9e40368ec93ec33b1edd8608e29495e0a54b63144e880"},"package":null}
|
|
@ -51,7 +51,7 @@ version = "1"
|
|||
features = ["derive"]
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[dependencies.viaduct]
|
||||
path = "../viaduct"
|
||||
|
@ -68,5 +68,5 @@ features = ["preserve_order"]
|
|||
path = "../support/viaduct-reqwest"
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"b6f48d7892872e05decf3ce4e4198f4481c753fbb74384d9cbc18b4fe1affd12","README.md":"5e28baf874b643d756228bdab345e287bf107d3182dfe6a18aafadcc4b9a3fc9","benches/benchmark_all.rs":"3582f21af9758766ff32ed95f90b69984b32091b1e31e0c0bef307c22fd82f18","build.rs":"78780c5cccfe22c3ff4198624b9e188559c437c3e6fa1c8bb66548eee6aa66bf","metrics.yaml":"0540ab2271aeab7f07335c7ceec12acde942995f9dcb3c29070489aa61899d56","src/benchmarks/README.md":"ccee8dbddba8762d0453fa855bd6984137b224b8c019f3dd8e86a3c303f51d71","src/benchmarks/client.rs":"3b92c350ad396b0e0b5438c7b7b94b08b322702f419ca9b815e6732bd174f8a1","src/benchmarks/ingest.rs":"ca368573591519e6b777d659d5615718bedb6eee1734e25242627f8116b10881","src/benchmarks/mod.rs":"2d7c20d47d6c7e17bc738255a31119bd0c4a4e495419a00c7b10b251ace9ef6b","src/benchmarks/query.rs":"ce78057e0ed43a419cc92d2bceb0bbef8aad9b113ef0341cf5f1d8d1578848e0","src/bin/debug_ingestion_sizes.rs":"ce6e810be7b3fc19e826d75b622b82cfab5a1a99397a6d0833c2c4eebff2d364","src/config.rs":"d40c6e83d8b5faa32c66110803ca9e78611d43507e9d3f1e191a93a7773c37b3","src/db.rs":"96156fcb8f8dc9dd98334d77fc53623046529dcf6b57f6282f120ad33cb8bcac","src/error.rs":"183a92511565439915275e0705e6740ff513c2549f2ef78fd3055d8aaaf81021","src/fakespot.rs":"03d3aac07b3a3a9ceb8d2c452d4a122bfebf04579829e62e83487877055312d4","src/keyword.rs":"988d0ab021c0df19cfd3c519df7d37f606bf984cd14d0efca4e5a7aff88344dd","src/lib.rs":"ab7fa1005cc371b15fde5211d7dabae5034f3b236580047655897be30280b2c9","src/metrics.rs":"b3b9816b8eda366f808b56e242ac6aa43a5b141ad01d43420fdfcbfca13e1cfc","src/pocket.rs":"1316668840ec9b4ea886223921dc9d3b5a1731d1a5206c0b1089f2a6c45c1b7b","src/provider.rs":"3ad644f7b3942e4228bdc9ec03e12af5faa55e3f9ab668617bef98e4c61ee1f7","src/query.rs":"6b94eb913908c36798129311bf519fa76478c6d35c2154efd639c4ba26b95a59","src/rs.rs":"16cf7fae7e935ef94beab532537564975addcd35b1a9b4b4a9fa1d34d51fbcfb","src/schema.rs":"5f2449c6ef798addf6b1d9869936edfe0629f6d543f3cb957becdf0595b29a41","src/store.rs":"57d00989eca564ce1497fa813b2f1bdf8acb8cbba1603fe6000c3abef37e5959","src/suggest.udl":"ba5e99a5d8c09ade945d537e0f90276cc6964ebc9ff454e5dbe5c9b3ba58f8eb","src/suggestion.rs":"3a91ecd648183f34b3834f5eaa14e487f29d8b227e7d4755288c3eade6d990e3","src/testing/client.rs":"f8c9bd32d0f4cf364daebe114d580c7e36a83b69c07884d14170969620d9a437","src/testing/data.rs":"d4fc5227996a8b115d93243fdbd83bc57d73a8c2d4c0b20dffa15bbec27925cb","src/testing/mod.rs":"800e5317bc2e13ee2b416bb0eb5c25ad9108a1afe8c73c9d2f6787572aa95c3a","src/yelp.rs":"bc036ff71b438d53ce8811acd8d650d83ef03faeea476f5b659b403c1e64ff2b","uniffi.toml":"f26317442ddb5b3281245bef6e60ffcb78bb95d29fe4a351a56dbb88d4ec8aab"},"package":null}
|
||||
{"files":{"Cargo.toml":"2e38a519b9a49462d301e296d0445f7c44897b963293b6f4ac45b1312f9b36ad","README.md":"5e28baf874b643d756228bdab345e287bf107d3182dfe6a18aafadcc4b9a3fc9","benches/benchmark_all.rs":"3582f21af9758766ff32ed95f90b69984b32091b1e31e0c0bef307c22fd82f18","build.rs":"78780c5cccfe22c3ff4198624b9e188559c437c3e6fa1c8bb66548eee6aa66bf","metrics.yaml":"0540ab2271aeab7f07335c7ceec12acde942995f9dcb3c29070489aa61899d56","src/benchmarks/README.md":"ccee8dbddba8762d0453fa855bd6984137b224b8c019f3dd8e86a3c303f51d71","src/benchmarks/client.rs":"3b92c350ad396b0e0b5438c7b7b94b08b322702f419ca9b815e6732bd174f8a1","src/benchmarks/ingest.rs":"ca368573591519e6b777d659d5615718bedb6eee1734e25242627f8116b10881","src/benchmarks/mod.rs":"2d7c20d47d6c7e17bc738255a31119bd0c4a4e495419a00c7b10b251ace9ef6b","src/benchmarks/query.rs":"ce78057e0ed43a419cc92d2bceb0bbef8aad9b113ef0341cf5f1d8d1578848e0","src/bin/debug_ingestion_sizes.rs":"ce6e810be7b3fc19e826d75b622b82cfab5a1a99397a6d0833c2c4eebff2d364","src/config.rs":"d40c6e83d8b5faa32c66110803ca9e78611d43507e9d3f1e191a93a7773c37b3","src/db.rs":"96156fcb8f8dc9dd98334d77fc53623046529dcf6b57f6282f120ad33cb8bcac","src/error.rs":"183a92511565439915275e0705e6740ff513c2549f2ef78fd3055d8aaaf81021","src/fakespot.rs":"03d3aac07b3a3a9ceb8d2c452d4a122bfebf04579829e62e83487877055312d4","src/keyword.rs":"988d0ab021c0df19cfd3c519df7d37f606bf984cd14d0efca4e5a7aff88344dd","src/lib.rs":"ab7fa1005cc371b15fde5211d7dabae5034f3b236580047655897be30280b2c9","src/metrics.rs":"b3b9816b8eda366f808b56e242ac6aa43a5b141ad01d43420fdfcbfca13e1cfc","src/pocket.rs":"1316668840ec9b4ea886223921dc9d3b5a1731d1a5206c0b1089f2a6c45c1b7b","src/provider.rs":"3ad644f7b3942e4228bdc9ec03e12af5faa55e3f9ab668617bef98e4c61ee1f7","src/query.rs":"6b94eb913908c36798129311bf519fa76478c6d35c2154efd639c4ba26b95a59","src/rs.rs":"16cf7fae7e935ef94beab532537564975addcd35b1a9b4b4a9fa1d34d51fbcfb","src/schema.rs":"5f2449c6ef798addf6b1d9869936edfe0629f6d543f3cb957becdf0595b29a41","src/store.rs":"57d00989eca564ce1497fa813b2f1bdf8acb8cbba1603fe6000c3abef37e5959","src/suggest.udl":"ba5e99a5d8c09ade945d537e0f90276cc6964ebc9ff454e5dbe5c9b3ba58f8eb","src/suggestion.rs":"3a91ecd648183f34b3834f5eaa14e487f29d8b227e7d4755288c3eade6d990e3","src/testing/client.rs":"f8c9bd32d0f4cf364daebe114d580c7e36a83b69c07884d14170969620d9a437","src/testing/data.rs":"d4fc5227996a8b115d93243fdbd83bc57d73a8c2d4c0b20dffa15bbec27925cb","src/testing/mod.rs":"800e5317bc2e13ee2b416bb0eb5c25ad9108a1afe8c73c9d2f6787572aa95c3a","src/yelp.rs":"bc036ff71b438d53ce8811acd8d650d83ef03faeea476f5b659b403c1e64ff2b","uniffi.toml":"f26317442ddb5b3281245bef6e60ffcb78bb95d29fe4a351a56dbb88d4ec8aab"},"package":null}
|
|
@ -86,7 +86,7 @@ version = "3.2.0"
|
|||
optional = true
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[dependencies.url]
|
||||
version = "2.1"
|
||||
|
@ -112,7 +112,7 @@ default-features = false
|
|||
path = "../support/rc_crypto"
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"3cacaf0a05825c2bc79d3ea3b12580301ef056d40d2bc5b2546de99d306ef242","README.md":"6d4ff5b079ac5340d18fa127f583e7ad793c5a2328b8ecd12c3fc723939804f2","build.rs":"aa971160d67ce8626b26e15c04c34b730f594c45c817aae34cfc9f3ea14ae284","src/bso/content.rs":"92935258745bdf0c3915a555cb6884a7fa69faa1290ec2c1815f6e2f3c0f0562","src/bso/crypto.rs":"27602dcccb37d3a55620ee4e16b705da455d49af575de115c7c79c0178eb1d6d","src/bso/mod.rs":"09e723dc7e99295ecafdcadffaf604d66ea27cf2b7f1fd9ab3cac4f4698ff6a7","src/bso/test_utils.rs":"4ec5a2df5e1c0ec14dc770681e959bdcef6ef04f6fde435999197f46a8ae4831","src/client/coll_state.rs":"13e6ef55273baf5536acc369be522e34a803a32cabf19cce43e426aea9b6223e","src/client/coll_update.rs":"dac04a90c29dd969f8b4250414609c9b6d61daf2dfa4ae77d1c4a165ba970b05","src/client/collection_keys.rs":"c27b2277a3a52033b58ab01490fc2ea7007494195dd5e6dc2c6931a4ca96795a","src/client/mod.rs":"8f588d4a035cf79d96f2500f06d5651c1a7c566127c456ffa5429811ddce3fd6","src/client/request.rs":"e878c5b43298b6eb682748474963f9fb8d053b4dc690bbb27107f5fa0ee74e01","src/client/state.rs":"4e31193ef2471c1dfabf1c6a391bcb95e14ddb45855786a4194ff187d5c9347c","src/client/status.rs":"f445a8765dac9789444e23b5145148413407bb1d18a15ef56682243997f591bf","src/client/storage_client.rs":"cc4a3219f342f8665399734902f68a2ddf12ed7e3726033ed10084bcefb66ffd","src/client/sync.rs":"b29abb512ec9d163f7883b71f78c9202802dcb17cad1fc5dc08087fb0bb66704","src/client/sync_multiple.rs":"6e92571132f89744b553190c596be8aff9b2d031d8f79d82c94cdf78b1683f4a","src/client/token.rs":"13729c693c8be72bcafc816c97e2a35932d008b4f2ccda6a5f8cdb8b2c99a293","src/client/util.rs":"71cc70ee41f821f53078675e636e9fad9c6046fa1a989e37f5487e340a2277d6","src/client_types.rs":"3c3cac1540b92482f43660d9e43bdde8481c4cc1a98253a68c80e791231f5976","src/clients_engine/engine.rs":"9e11b47be81fc63214f31879af74075674aa50a8f8989afe20fefa7990fa99b9","src/clients_engine/mod.rs":"461729e6f89b66b2cbd89b041a03d4d6a8ba582284ed4f3015cb13e1a0c6da97","src/clients_engine/record.rs":"b0d84bf420743d7638a45e4836633a45e50257d5548fe7ecd04bff4d724439b8","src/clients_engine/ser.rs":"be6a19c45eb8002ff8e7cf746d2f97d9cecd1740f9817a8f1d624825475fd777","src/device_type.rs":"dc2d4296d25e31471c8e68488f1043ff239b902036cd6aea8a686cf79b4ed335","src/enc_payload.rs":"aa3eea7df49b24cd59831680a47c417b73a3e36e6b0f3f4baf14ca66bd68be6b","src/engine/bridged_engine.rs":"b4e3071a0259ac55303364e57f9cd685916b80dc302030bba07790e55ceecb66","src/engine/mod.rs":"90f1f9760f5f712a337aebb04e59c736e4b6fbd89d6a188d969210c7f3f321ae","src/engine/request.rs":"5923025fb9550178339f880a1bf8526d8e853e7a0b2bce6d9d687cc808ac0085","src/engine/sync_engine.rs":"531b35d72ce9e04c3e543c0468c1e450fba2c0dc3d33d68d9b1c0a5c1ad7dd34","src/error.rs":"a45cfe02e6301f473c34678b694943c1a04308b8c292c6e0448bf495194c3b5e","src/key_bundle.rs":"abd0781f3be8c8e7c691f18bb71f3433b633803c48da9794e15ac6301ed60d6c","src/lib.rs":"f59f8817978d943518dfa03ab31fc0f6b1fc72ee9943a97aef1537e2769649f5","src/record_types.rs":"02bb3d352fb808131d298f9b90d9c95b7e9e0138b97c5401f3b9fdacc5562f44","src/server_timestamp.rs":"63916817796e83fe31fbd598bac025dfa71ec9e1808d09073db258c78a3331cd","src/sync15.udl":"005b2b056b93c959a04670f6f489afecb8e17093d8e4be34765a3a4cc0faeb8c","src/telemetry.rs":"1d06433aafe05b8d0c403ff6cb3bb35eec292f2cd6273d321eaa196fb6584dd6","uniffi.toml":"34488f947497a9b05007445dd816024ef02e6b1696f1056ee868f039722828ee"},"package":null}
|
||||
{"files":{"Cargo.toml":"85552fcfea769f22b10acf08d2f2345dbc8cd683de2c7a88ed7280863407a62e","README.md":"6d4ff5b079ac5340d18fa127f583e7ad793c5a2328b8ecd12c3fc723939804f2","build.rs":"aa971160d67ce8626b26e15c04c34b730f594c45c817aae34cfc9f3ea14ae284","src/bso/content.rs":"92935258745bdf0c3915a555cb6884a7fa69faa1290ec2c1815f6e2f3c0f0562","src/bso/crypto.rs":"27602dcccb37d3a55620ee4e16b705da455d49af575de115c7c79c0178eb1d6d","src/bso/mod.rs":"09e723dc7e99295ecafdcadffaf604d66ea27cf2b7f1fd9ab3cac4f4698ff6a7","src/bso/test_utils.rs":"4ec5a2df5e1c0ec14dc770681e959bdcef6ef04f6fde435999197f46a8ae4831","src/client/coll_state.rs":"13e6ef55273baf5536acc369be522e34a803a32cabf19cce43e426aea9b6223e","src/client/coll_update.rs":"dac04a90c29dd969f8b4250414609c9b6d61daf2dfa4ae77d1c4a165ba970b05","src/client/collection_keys.rs":"c27b2277a3a52033b58ab01490fc2ea7007494195dd5e6dc2c6931a4ca96795a","src/client/mod.rs":"8f588d4a035cf79d96f2500f06d5651c1a7c566127c456ffa5429811ddce3fd6","src/client/request.rs":"e878c5b43298b6eb682748474963f9fb8d053b4dc690bbb27107f5fa0ee74e01","src/client/state.rs":"4e31193ef2471c1dfabf1c6a391bcb95e14ddb45855786a4194ff187d5c9347c","src/client/status.rs":"f445a8765dac9789444e23b5145148413407bb1d18a15ef56682243997f591bf","src/client/storage_client.rs":"cc4a3219f342f8665399734902f68a2ddf12ed7e3726033ed10084bcefb66ffd","src/client/sync.rs":"b29abb512ec9d163f7883b71f78c9202802dcb17cad1fc5dc08087fb0bb66704","src/client/sync_multiple.rs":"6e92571132f89744b553190c596be8aff9b2d031d8f79d82c94cdf78b1683f4a","src/client/token.rs":"13729c693c8be72bcafc816c97e2a35932d008b4f2ccda6a5f8cdb8b2c99a293","src/client/util.rs":"71cc70ee41f821f53078675e636e9fad9c6046fa1a989e37f5487e340a2277d6","src/client_types.rs":"3c3cac1540b92482f43660d9e43bdde8481c4cc1a98253a68c80e791231f5976","src/clients_engine/engine.rs":"9e11b47be81fc63214f31879af74075674aa50a8f8989afe20fefa7990fa99b9","src/clients_engine/mod.rs":"461729e6f89b66b2cbd89b041a03d4d6a8ba582284ed4f3015cb13e1a0c6da97","src/clients_engine/record.rs":"b0d84bf420743d7638a45e4836633a45e50257d5548fe7ecd04bff4d724439b8","src/clients_engine/ser.rs":"be6a19c45eb8002ff8e7cf746d2f97d9cecd1740f9817a8f1d624825475fd777","src/device_type.rs":"dc2d4296d25e31471c8e68488f1043ff239b902036cd6aea8a686cf79b4ed335","src/enc_payload.rs":"aa3eea7df49b24cd59831680a47c417b73a3e36e6b0f3f4baf14ca66bd68be6b","src/engine/bridged_engine.rs":"b4e3071a0259ac55303364e57f9cd685916b80dc302030bba07790e55ceecb66","src/engine/mod.rs":"90f1f9760f5f712a337aebb04e59c736e4b6fbd89d6a188d969210c7f3f321ae","src/engine/request.rs":"5923025fb9550178339f880a1bf8526d8e853e7a0b2bce6d9d687cc808ac0085","src/engine/sync_engine.rs":"531b35d72ce9e04c3e543c0468c1e450fba2c0dc3d33d68d9b1c0a5c1ad7dd34","src/error.rs":"a45cfe02e6301f473c34678b694943c1a04308b8c292c6e0448bf495194c3b5e","src/key_bundle.rs":"abd0781f3be8c8e7c691f18bb71f3433b633803c48da9794e15ac6301ed60d6c","src/lib.rs":"f59f8817978d943518dfa03ab31fc0f6b1fc72ee9943a97aef1537e2769649f5","src/record_types.rs":"02bb3d352fb808131d298f9b90d9c95b7e9e0138b97c5401f3b9fdacc5562f44","src/server_timestamp.rs":"63916817796e83fe31fbd598bac025dfa71ec9e1808d09073db258c78a3331cd","src/sync15.udl":"005b2b056b93c959a04670f6f489afecb8e17093d8e4be34765a3a4cc0faeb8c","src/telemetry.rs":"1d06433aafe05b8d0c403ff6cb3bb35eec292f2cd6273d321eaa196fb6584dd6","uniffi.toml":"34488f947497a9b05007445dd816024ef02e6b1696f1056ee868f039722828ee"},"package":null}
|
|
@ -76,7 +76,7 @@ path = "../support/guid"
|
|||
features = ["random"]
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[dependencies.url]
|
||||
version = "2.1"
|
||||
|
@ -91,7 +91,7 @@ version = "0.10"
|
|||
default-features = false
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"916ac811a7f5fab127228d1d8b5bf2b5eee6884a3f5b7ef87e1e2d6008ad8e4a","README.md":"c48b8f391ef822c4f3971b5f453a1e7b43bea232752d520460d2f04803aead1a","build.rs":"33e61b811b19ed2b58e319cc65d5988bed258d2c4fea2d706301184c59847a0f","src/error.rs":"2694657aeb12f99c4b2fe102ad2b08b79955d209201831b3e071129f0b7d7eda","src/lib.rs":"5789fc7107c76168c331c175aff4f0b2ac2ba3d65cfa0df0e1d4f8ef0c6eb80c","src/schema.rs":"510218d465c7d26d6b9f342cc33c14ab83044a67561ef924c33dadb060761972","src/storage.rs":"99f14f989a04a73bf794863786370fe7fdc89061eddc381ff82ae067297fd92b","src/store.rs":"95ed09a93bc72327811f9c5826779ef4fe96d7f2c04a2382a96557746bf7b2f9","src/sync/bridge.rs":"18d3a7913a030b598d4b6cbd5b7e2ab4cef4cc7ea964f5bc84d7fb2f28787529","src/sync/engine.rs":"73007423f2a22314a034ac660aa65bd9c50e8aa850c445a66604486280067843","src/sync/mod.rs":"09ba3c87f1174a243bf5aaa481effd18929d54359ceb9b23ccb2c32ee3482f34","src/sync/record.rs":"eef6751c209d039958afbe245ddb006cfdf6b8b6b47f925f69c552b832b87922","src/tabs.udl":"b2918b26c982c3420346bad4c8de83fa039afcee5ab838c71048eae27240af8f","uniffi.toml":"f9125e8d55b109e86076ee88bfd640372f06b142b7db557e41816c7227dd445c"},"package":null}
|
||||
{"files":{"Cargo.toml":"4e3cdde3168af54cac1a9e6fa84c5ff0a99252b67d32ce5d177b057f7a70e0f9","README.md":"c48b8f391ef822c4f3971b5f453a1e7b43bea232752d520460d2f04803aead1a","build.rs":"33e61b811b19ed2b58e319cc65d5988bed258d2c4fea2d706301184c59847a0f","src/error.rs":"2694657aeb12f99c4b2fe102ad2b08b79955d209201831b3e071129f0b7d7eda","src/lib.rs":"5789fc7107c76168c331c175aff4f0b2ac2ba3d65cfa0df0e1d4f8ef0c6eb80c","src/schema.rs":"510218d465c7d26d6b9f342cc33c14ab83044a67561ef924c33dadb060761972","src/storage.rs":"99f14f989a04a73bf794863786370fe7fdc89061eddc381ff82ae067297fd92b","src/store.rs":"95ed09a93bc72327811f9c5826779ef4fe96d7f2c04a2382a96557746bf7b2f9","src/sync/bridge.rs":"18d3a7913a030b598d4b6cbd5b7e2ab4cef4cc7ea964f5bc84d7fb2f28787529","src/sync/engine.rs":"73007423f2a22314a034ac660aa65bd9c50e8aa850c445a66604486280067843","src/sync/mod.rs":"09ba3c87f1174a243bf5aaa481effd18929d54359ceb9b23ccb2c32ee3482f34","src/sync/record.rs":"eef6751c209d039958afbe245ddb006cfdf6b8b6b47f925f69c552b832b87922","src/tabs.udl":"b2918b26c982c3420346bad4c8de83fa039afcee5ab838c71048eae27240af8f","uniffi.toml":"f9125e8d55b109e86076ee88bfd640372f06b142b7db557e41816c7227dd445c"},"package":null}
|
|
@ -76,7 +76,7 @@ features = ["sync-engine"]
|
|||
path = "../support/types"
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.1"
|
||||
|
@ -87,5 +87,5 @@ features = ["humantime"]
|
|||
default-features = false
|
||||
|
||||
[build-dependencies.uniffi]
|
||||
version = "0.27.1"
|
||||
version = "0.28.0"
|
||||
features = ["build"]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"7c45cfa5f95f1db4ec3cb139f8f5166281f7893b21a4313ee4a4f4070bef1816","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","release.toml":"1aa1b131d4cc93b5eba8758a4401c70bc0d7fe5861e2ec147e9259fe7c0da472","src/cli.rs":"5c0b9bb93665f2f49f7e90335e65206887e26e96f2a533eb1203be27c9380c84","src/lib.rs":"422503d7cbac1360852287b1810c99663669625b9abf080a5fec22058bb73d8c","tests/ui/proc_macro_arc.rs":"fedc429603753e8ef953642a7295323ccb3f76fd3ae1ab181ad90c5eb88212bb","tests/ui/proc_macro_arc.stderr":"a24af227b907328c9cac6317ec9f43dbc45d7f7c77c603e5d72db7fa050e8b01","tests/ui/version_mismatch.rs":"16ea359e5853517ee0d0704c015ae8c825533109fbefd715130d0f4a51f15898","tests/ui/version_mismatch.stderr":"21dcb836253312ba8e3a0502cce6ff279818aaaadcea9628a41b196e0c8c94b6"},"package":"cb3a4c447c50fcda7bc5604a8588b7e1f37ffbfd8838a1516a290398efa7c6f0"}
|
||||
{"files":{"Cargo.toml":"87b3072b1ffd4a1b018953792ccca5f98d6863131aea7a27563fc8077a42e998","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","release.toml":"1aa1b131d4cc93b5eba8758a4401c70bc0d7fe5861e2ec147e9259fe7c0da472","src/cli.rs":"648a1c05015ce4e8c63f00321f02eddd4b42c0cdefb734b569c1761c2b1bc436","src/lib.rs":"ecabaf300a549d9d8ff046d43465358f03a76c8b941e2a1511c6e3d2884285f9","tests/ui/proc_macro_arc.rs":"fedc429603753e8ef953642a7295323ccb3f76fd3ae1ab181ad90c5eb88212bb","tests/ui/proc_macro_arc.stderr":"3d5b53f50dc2b8ac89b331efb349cf52bd5820cd8f86c5fc504f7ed757155ea6","tests/ui/version_mismatch.rs":"16ea359e5853517ee0d0704c015ae8c825533109fbefd715130d0f4a51f15898","tests/ui/version_mismatch.stderr":"21dcb836253312ba8e3a0502cce6ff279818aaaadcea9628a41b196e0c8c94b6"},"package":"2db87def739fe4183947f8419d572d1849a4a09355eba4e988a2105cfd0ac6a7"}
|
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "uniffi"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
description = "a multi-language bindings generator for rust"
|
||||
homepage = "https://mozilla.github.io/uniffi-rs"
|
||||
|
@ -32,6 +32,10 @@ version = "1"
|
|||
version = "1.0.8"
|
||||
optional = true
|
||||
|
||||
[dependencies.cargo_metadata]
|
||||
version = "0.15"
|
||||
optional = true
|
||||
|
||||
[dependencies.clap]
|
||||
version = "4"
|
||||
features = [
|
||||
|
@ -42,33 +46,39 @@ features = [
|
|||
optional = true
|
||||
|
||||
[dependencies.uniffi_bindgen]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.uniffi_build]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.uniffi_core]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
|
||||
[dependencies.uniffi_macros]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
|
||||
[dev-dependencies.trybuild]
|
||||
version = "1"
|
||||
|
||||
[features]
|
||||
bindgen = ["dep:uniffi_bindgen"]
|
||||
bindgen-tests = ["dep:uniffi_bindgen"]
|
||||
bindgen-tests = [
|
||||
"dep:uniffi_bindgen",
|
||||
"uniffi_bindgen/bindgen-tests",
|
||||
]
|
||||
build = ["dep:uniffi_build"]
|
||||
cargo-metadata = [
|
||||
"dep:cargo_metadata",
|
||||
"uniffi_bindgen?/cargo-metadata",
|
||||
]
|
||||
cli = [
|
||||
"bindgen",
|
||||
"uniffi_bindgen?/clap",
|
||||
"dep:clap",
|
||||
"dep:camino",
|
||||
]
|
||||
default = []
|
||||
default = ["cargo-metadata"]
|
||||
scaffolding-ffi-buffer-fns = [
|
||||
"uniffi_core/scaffolding-ffi-buffer-fns",
|
||||
"uniffi_macros/scaffolding-ffi-buffer-fns",
|
||||
|
|
|
@ -2,10 +2,62 @@
|
|||
* 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 anyhow::{bail, Context, Result};
|
||||
use camino::Utf8PathBuf;
|
||||
use clap::{Parser, Subcommand};
|
||||
use uniffi_bindgen::bindings::TargetLanguage;
|
||||
use uniffi_bindgen::BindingGeneratorDefault;
|
||||
use std::fmt;
|
||||
use uniffi_bindgen::bindings::*;
|
||||
|
||||
/// Enumeration of all foreign language targets currently supported by our CLI.
|
||||
///
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, clap::ValueEnum)]
|
||||
enum TargetLanguage {
|
||||
Kotlin,
|
||||
Swift,
|
||||
Python,
|
||||
Ruby,
|
||||
}
|
||||
|
||||
impl fmt::Display for TargetLanguage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Kotlin => write!(f, "kotlin"),
|
||||
Self::Swift => write!(f, "swift"),
|
||||
Self::Python => write!(f, "python"),
|
||||
Self::Ruby => write!(f, "ruby"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for TargetLanguage {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(value: &str) -> Result<Self> {
|
||||
Ok(match value.to_ascii_lowercase().as_str() {
|
||||
"kotlin" | "kt" | "kts" => TargetLanguage::Kotlin,
|
||||
"swift" => TargetLanguage::Swift,
|
||||
"python" | "py" => TargetLanguage::Python,
|
||||
"ruby" | "rb" => TargetLanguage::Ruby,
|
||||
_ => bail!("Unknown or unsupported target language: \"{value}\""),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&std::ffi::OsStr> for TargetLanguage {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(value: &std::ffi::OsStr) -> Result<Self> {
|
||||
match value.to_str() {
|
||||
None => bail!("Unreadable target language"),
|
||||
Some(s) => s.try_into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for TargetLanguage {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(value: String) -> Result<Self> {
|
||||
TryFrom::try_from(value.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
// Structs to help our cmdline parsing. Note that docstrings below form part
|
||||
// of the "help" output.
|
||||
|
@ -56,6 +108,14 @@ enum Commands {
|
|||
|
||||
/// Path to the UDL file, or cdylib if `library-mode` is specified
|
||||
source: Utf8PathBuf,
|
||||
|
||||
/// Whether we should exclude dependencies when running "cargo metadata".
|
||||
/// This will mean external types may not be resolved if they are implemented in crates
|
||||
/// outside of this workspace.
|
||||
/// This can be used in environments when all types are in the namespace and fetching
|
||||
/// all sub-dependencies causes obscure platform specific problems.
|
||||
#[clap(long)]
|
||||
metadata_no_deps: bool,
|
||||
},
|
||||
|
||||
/// Generate Rust scaffolding code
|
||||
|
@ -79,6 +139,139 @@ enum Commands {
|
|||
},
|
||||
}
|
||||
|
||||
fn gen_library_mode(
|
||||
library_path: &camino::Utf8Path,
|
||||
crate_name: Option<String>,
|
||||
languages: Vec<TargetLanguage>,
|
||||
cfo: Option<&camino::Utf8Path>,
|
||||
out_dir: &camino::Utf8Path,
|
||||
fmt: bool,
|
||||
metadata_no_deps: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
use uniffi_bindgen::library_mode::generate_bindings;
|
||||
|
||||
#[cfg(feature = "cargo-metadata")]
|
||||
let config_supplier = {
|
||||
use uniffi_bindgen::cargo_metadata::CrateConfigSupplier;
|
||||
let mut cmd = cargo_metadata::MetadataCommand::new();
|
||||
if metadata_no_deps {
|
||||
cmd.no_deps();
|
||||
}
|
||||
let metadata = cmd.exec().context("error running cargo metadata")?;
|
||||
CrateConfigSupplier::from(metadata)
|
||||
};
|
||||
#[cfg(not(feature = "cargo-metadata"))]
|
||||
let config_supplier = uniffi_bindgen::EmptyCrateConfigSupplier;
|
||||
|
||||
for language in languages {
|
||||
// to help avoid mistakes we check the library is actually a cdylib, except
|
||||
// for swift where static libs are often used to extract the metadata.
|
||||
if !matches!(language, TargetLanguage::Swift) && !uniffi_bindgen::is_cdylib(library_path) {
|
||||
anyhow::bail!(
|
||||
"Generate bindings for {language} requires a cdylib, but {library_path} was given"
|
||||
);
|
||||
}
|
||||
|
||||
// Type-bounds on trait implementations makes selecting between languages a bit tedious.
|
||||
match language {
|
||||
TargetLanguage::Kotlin => generate_bindings(
|
||||
library_path,
|
||||
crate_name.clone(),
|
||||
&KotlinBindingGenerator,
|
||||
&config_supplier,
|
||||
cfo,
|
||||
out_dir,
|
||||
fmt,
|
||||
)?
|
||||
.len(),
|
||||
TargetLanguage::Python => generate_bindings(
|
||||
library_path,
|
||||
crate_name.clone(),
|
||||
&PythonBindingGenerator,
|
||||
&config_supplier,
|
||||
cfo,
|
||||
out_dir,
|
||||
fmt,
|
||||
)?
|
||||
.len(),
|
||||
TargetLanguage::Ruby => generate_bindings(
|
||||
library_path,
|
||||
crate_name.clone(),
|
||||
&RubyBindingGenerator,
|
||||
&config_supplier,
|
||||
cfo,
|
||||
out_dir,
|
||||
fmt,
|
||||
)?
|
||||
.len(),
|
||||
TargetLanguage::Swift => generate_bindings(
|
||||
library_path,
|
||||
crate_name.clone(),
|
||||
&SwiftBindingGenerator,
|
||||
&config_supplier,
|
||||
cfo,
|
||||
out_dir,
|
||||
fmt,
|
||||
)?
|
||||
.len(),
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gen_bindings(
|
||||
udl_file: &camino::Utf8Path,
|
||||
cfo: Option<&camino::Utf8Path>,
|
||||
languages: Vec<TargetLanguage>,
|
||||
odo: Option<&camino::Utf8Path>,
|
||||
library_file: Option<&camino::Utf8Path>,
|
||||
crate_name: Option<&str>,
|
||||
fmt: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
use uniffi_bindgen::generate_bindings;
|
||||
for language in languages {
|
||||
match language {
|
||||
TargetLanguage::Kotlin => generate_bindings(
|
||||
udl_file,
|
||||
cfo,
|
||||
KotlinBindingGenerator,
|
||||
odo,
|
||||
library_file,
|
||||
crate_name,
|
||||
fmt,
|
||||
)?,
|
||||
TargetLanguage::Python => generate_bindings(
|
||||
udl_file,
|
||||
cfo,
|
||||
PythonBindingGenerator,
|
||||
odo,
|
||||
library_file,
|
||||
crate_name,
|
||||
fmt,
|
||||
)?,
|
||||
TargetLanguage::Ruby => generate_bindings(
|
||||
udl_file,
|
||||
cfo,
|
||||
RubyBindingGenerator,
|
||||
odo,
|
||||
library_file,
|
||||
crate_name,
|
||||
fmt,
|
||||
)?,
|
||||
TargetLanguage::Swift => generate_bindings(
|
||||
udl_file,
|
||||
cfo,
|
||||
SwiftBindingGenerator,
|
||||
odo,
|
||||
library_file,
|
||||
crate_name,
|
||||
fmt,
|
||||
)?,
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
match cli.command {
|
||||
|
@ -91,6 +284,7 @@ pub fn run_main() -> anyhow::Result<()> {
|
|||
source,
|
||||
crate_name,
|
||||
library_mode,
|
||||
metadata_no_deps,
|
||||
} => {
|
||||
if library_mode {
|
||||
if lib_file.is_some() {
|
||||
|
@ -100,25 +294,23 @@ pub fn run_main() -> anyhow::Result<()> {
|
|||
if language.is_empty() {
|
||||
panic!("please specify at least one language with --language")
|
||||
}
|
||||
uniffi_bindgen::library_mode::generate_bindings(
|
||||
gen_library_mode(
|
||||
&source,
|
||||
crate_name,
|
||||
&BindingGeneratorDefault {
|
||||
target_languages: language,
|
||||
try_format_code: !no_format,
|
||||
},
|
||||
language,
|
||||
config.as_deref(),
|
||||
&out_dir,
|
||||
!no_format,
|
||||
metadata_no_deps,
|
||||
)?;
|
||||
} else {
|
||||
uniffi_bindgen::generate_bindings(
|
||||
if metadata_no_deps {
|
||||
panic!("--metadata-no-deps makes no sense when not in library mode")
|
||||
}
|
||||
gen_bindings(
|
||||
&source,
|
||||
config.as_deref(),
|
||||
BindingGeneratorDefault {
|
||||
target_languages: language,
|
||||
try_format_code: !no_format,
|
||||
},
|
||||
language,
|
||||
out_dir.as_deref(),
|
||||
lib_file.as_deref(),
|
||||
crate_name.as_deref(),
|
||||
|
|
|
@ -8,20 +8,15 @@ pub use uniffi_macros::*;
|
|||
#[cfg(feature = "cli")]
|
||||
mod cli;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub use uniffi_bindgen::bindings::kotlin::run_test as kotlin_run_test;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub use uniffi_bindgen::bindings::python::run_test as python_run_test;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub use uniffi_bindgen::bindings::ruby::run_test as ruby_run_test;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub use uniffi_bindgen::bindings::swift::run_test as swift_run_test;
|
||||
pub use uniffi_bindgen::bindings::{kotlin_test, python_test, ruby_test, swift_test};
|
||||
|
||||
#[cfg(feature = "bindgen")]
|
||||
pub use uniffi_bindgen::{
|
||||
bindings::kotlin::gen_kotlin::KotlinBindingGenerator,
|
||||
bindings::python::gen_python::PythonBindingGenerator,
|
||||
bindings::ruby::gen_ruby::RubyBindingGenerator,
|
||||
bindings::swift::gen_swift::SwiftBindingGenerator, bindings::TargetLanguage, generate_bindings,
|
||||
generate_component_scaffolding, generate_component_scaffolding_for_crate, print_repr,
|
||||
bindings::{
|
||||
KotlinBindingGenerator, PythonBindingGenerator, RubyBindingGenerator, SwiftBindingGenerator,
|
||||
},
|
||||
generate_bindings, generate_component_scaffolding, generate_component_scaffolding_for_crate,
|
||||
print_repr,
|
||||
};
|
||||
#[cfg(feature = "build")]
|
||||
pub use uniffi_build::{generate_scaffolding, generate_scaffolding_for_crate};
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0277]: the trait bound `Foo: FfiConverterArc<UniFfiTag>` is not satisfied
|
|||
--> tests/ui/proc_macro_arc.rs:10:1
|
||||
|
|
||||
10 | #[uniffi::export]
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc<UniFfiTag>` is not implemented for `Foo`
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc<UniFfiTag>` is not implemented for `Foo`, which is required by `Arc<Foo>: LowerReturn<UniFfiTag>`
|
||||
|
|
||||
= help: the trait `LowerReturn<UT>` is implemented for `Arc<T>`
|
||||
= note: required for `Arc<Foo>` to implement `FfiConverter<UniFfiTag>`
|
||||
|
@ -10,13 +10,33 @@ error[E0277]: the trait bound `Foo: FfiConverterArc<UniFfiTag>` is not satisfied
|
|||
= note: required for `Arc<Foo>` to implement `LowerReturn<UniFfiTag>`
|
||||
= note: this error originates in the attribute macro `uniffi::export` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0277]: the trait bound `Foo: FfiConverterArc<UniFfiTag>` is not satisfied
|
||||
--> tests/ui/proc_macro_arc.rs:11:18
|
||||
|
|
||||
11 | fn make_foo() -> Arc<Foo> {
|
||||
| ^^^^^^^^ the trait `FfiConverterArc<UniFfiTag>` is not implemented for `Foo`, which is required by `Arc<Foo>: uniffi::TypeId<UniFfiTag>`
|
||||
|
|
||||
= help: the trait `uniffi::TypeId<UT>` is implemented for `Arc<T>`
|
||||
= note: required for `Arc<Foo>` to implement `FfiConverter<UniFfiTag>`
|
||||
= note: required for `Arc<Foo>` to implement `uniffi::TypeId<UniFfiTag>`
|
||||
|
||||
error[E0277]: the trait bound `child::Foo: FfiConverterArc<UniFfiTag>` is not satisfied
|
||||
--> tests/ui/proc_macro_arc.rs:20:5
|
||||
|
|
||||
20 | #[uniffi::export]
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc<UniFfiTag>` is not implemented for `child::Foo`
|
||||
| ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc<UniFfiTag>` is not implemented for `child::Foo`, which is required by `Arc<child::Foo>: Lift<UniFfiTag>`
|
||||
|
|
||||
= help: the trait `Lift<UT>` is implemented for `Arc<T>`
|
||||
= note: required for `Arc<child::Foo>` to implement `FfiConverter<UniFfiTag>`
|
||||
= note: required for `Arc<child::Foo>` to implement `Lift<UniFfiTag>`
|
||||
= note: this error originates in the attribute macro `uniffi::export` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0277]: the trait bound `child::Foo: FfiConverterArc<UniFfiTag>` is not satisfied
|
||||
--> tests/ui/proc_macro_arc.rs:21:22
|
||||
|
|
||||
21 | fn take_foo(foo: Arc<Foo>) {
|
||||
| ^^^^^^^^ the trait `FfiConverterArc<UniFfiTag>` is not implemented for `child::Foo`, which is required by `Arc<child::Foo>: uniffi::TypeId<UniFfiTag>`
|
||||
|
|
||||
= help: the trait `uniffi::TypeId<UT>` is implemented for `Arc<T>`
|
||||
= note: required for `Arc<child::Foo>` to implement `FfiConverter<UniFfiTag>`
|
||||
= note: required for `Arc<child::Foo>` to implement `uniffi::TypeId<UniFfiTag>`
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "uniffi_bindgen"
|
||||
version = "0.27.3"
|
||||
version = "0.28.1"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
description = "a multi-language bindings generator for rust (codegen and cli tooling)"
|
||||
homepage = "https://mozilla.github.io/uniffi-rs"
|
||||
|
@ -38,15 +38,7 @@ version = "1.0.8"
|
|||
|
||||
[dependencies.cargo_metadata]
|
||||
version = "0.15"
|
||||
|
||||
[dependencies.clap]
|
||||
version = "4"
|
||||
features = [
|
||||
"std",
|
||||
"derive",
|
||||
]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.fs-err]
|
||||
version = "2.7.0"
|
||||
|
@ -58,7 +50,7 @@ version = "0.3"
|
|||
version = "0.8"
|
||||
|
||||
[dependencies.heck]
|
||||
version = "0.4"
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.12"
|
||||
|
@ -79,10 +71,19 @@ default-features = false
|
|||
version = "0.5"
|
||||
|
||||
[dependencies.uniffi_meta]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
|
||||
[dependencies.uniffi_testing]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.uniffi_udl]
|
||||
version = "=0.27.3"
|
||||
version = "=0.28.1"
|
||||
|
||||
[features]
|
||||
bindgen-tests = [
|
||||
"cargo-metadata",
|
||||
"dep:uniffi_testing",
|
||||
]
|
||||
cargo-metadata = ["dep:cargo_metadata"]
|
||||
default = ["cargo-metadata"]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
[See the section in the manual for into about the bindings](../../../docs/manual/src/internals/rendering_foreign_bindings.md)
|
|
@ -17,8 +17,8 @@ impl CustomCodeType {
|
|||
}
|
||||
|
||||
impl CodeType for CustomCodeType {
|
||||
fn type_label(&self, _ci: &ComponentInterface) -> String {
|
||||
self.name.clone()
|
||||
fn type_label(&self, ci: &ComponentInterface) -> String {
|
||||
super::KotlinCodeOracle.class_name(ci, &self.name)
|
||||
}
|
||||
|
||||
fn canonical_name(&self) -> String {
|
||||
|
|
|
@ -7,16 +7,14 @@ use std::cell::RefCell;
|
|||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::fmt::Debug;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use askama::Template;
|
||||
use camino::Utf8Path;
|
||||
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::backend::TemplateExpression;
|
||||
use crate::bindings::kotlin;
|
||||
|
||||
use crate::interface::*;
|
||||
use crate::{BindingGenerator, BindingsConfig};
|
||||
|
||||
mod callback_interface;
|
||||
mod compounds;
|
||||
|
@ -29,28 +27,6 @@ mod primitives;
|
|||
mod record;
|
||||
mod variant;
|
||||
|
||||
pub struct KotlinBindingGenerator;
|
||||
impl BindingGenerator for KotlinBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
ci: &ComponentInterface,
|
||||
config: &Config,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
kotlin::write_bindings(config, ci, out_dir, try_format_code)
|
||||
}
|
||||
|
||||
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
|
||||
if cdylib_name.is_none() {
|
||||
bail!("Generate bindings for Kotlin requires a cdylib, but {library_path} was given");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
trait CodeType: Debug {
|
||||
/// The language specific label used to reference this type. This will be used in
|
||||
/// method signatures and property declarations.
|
||||
|
@ -94,23 +70,71 @@ trait CodeType: Debug {
|
|||
// config options to customize the generated Kotlin.
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
package_name: Option<String>,
|
||||
cdylib_name: Option<String>,
|
||||
pub(super) package_name: Option<String>,
|
||||
pub(super) cdylib_name: Option<String>,
|
||||
generate_immutable_records: Option<bool>,
|
||||
#[serde(default)]
|
||||
custom_types: HashMap<String, CustomTypeConfig>,
|
||||
#[serde(default)]
|
||||
external_packages: HashMap<String, String>,
|
||||
pub(super) external_packages: HashMap<String, String>,
|
||||
#[serde(default)]
|
||||
android: bool,
|
||||
#[serde(default)]
|
||||
android_cleaner: Option<bool>,
|
||||
#[serde(default)]
|
||||
kotlin_target_version: Option<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub(crate) fn android_cleaner(&self) -> bool {
|
||||
self.android_cleaner.unwrap_or(self.android)
|
||||
}
|
||||
|
||||
pub(crate) fn use_enum_entries(&self) -> bool {
|
||||
self.get_kotlin_version() >= KotlinVersion::new(1, 9, 0)
|
||||
}
|
||||
|
||||
/// Returns a `Version` with the contents of `kotlin_target_version`.
|
||||
/// If `kotlin_target_version` is not defined, version `0.0.0` will be used as a fallback.
|
||||
/// If it's not valid, this function will panic.
|
||||
fn get_kotlin_version(&self) -> KotlinVersion {
|
||||
self.kotlin_target_version
|
||||
.clone()
|
||||
.map(|v| {
|
||||
KotlinVersion::parse(&v).unwrap_or_else(|_| {
|
||||
panic!("Provided Kotlin target version is not valid: {}", v)
|
||||
})
|
||||
})
|
||||
.unwrap_or(KotlinVersion::new(0, 0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct KotlinVersion((u16, u16, u16));
|
||||
|
||||
impl KotlinVersion {
|
||||
fn new(major: u16, minor: u16, patch: u16) -> Self {
|
||||
Self((major, minor, patch))
|
||||
}
|
||||
|
||||
fn parse(version: &str) -> Result<Self> {
|
||||
let components = version
|
||||
.split('.')
|
||||
.map(|n| {
|
||||
n.parse::<u16>()
|
||||
.map_err(|_| anyhow!("Invalid version string ({n} is not an integer)"))
|
||||
})
|
||||
.collect::<Result<Vec<u16>>>()?;
|
||||
|
||||
match components.as_slice() {
|
||||
[major, minor, patch] => Ok(Self((*major, *minor, *patch))),
|
||||
[major, minor] => Ok(Self((*major, *minor, 0))),
|
||||
[major] => Ok(Self((*major, 0, 0))),
|
||||
_ => Err(anyhow!(
|
||||
"Invalid version string (expected 1-3 components): {version}"
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
|
@ -122,20 +146,19 @@ pub struct CustomTypeConfig {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
// We insist someone has already configured us - any defaults we supply would be wrong.
|
||||
pub fn package_name(&self) -> String {
|
||||
if let Some(package_name) = &self.package_name {
|
||||
package_name.clone()
|
||||
} else {
|
||||
"uniffi".into()
|
||||
}
|
||||
self.package_name
|
||||
.as_ref()
|
||||
.expect("package name should have been set in update_component_configs")
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn cdylib_name(&self) -> String {
|
||||
if let Some(cdylib_name) = &self.cdylib_name {
|
||||
cdylib_name.clone()
|
||||
} else {
|
||||
"uniffi".into()
|
||||
}
|
||||
self.cdylib_name
|
||||
.as_ref()
|
||||
.expect("cdylib name should have been set in update_component_configs")
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Whether to generate immutable records (`val` instead of `var`)
|
||||
|
@ -144,29 +167,6 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
impl BindingsConfig for Config {
|
||||
fn update_from_ci(&mut self, ci: &ComponentInterface) {
|
||||
self.package_name
|
||||
.get_or_insert_with(|| format!("uniffi.{}", ci.namespace()));
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| format!("uniffi_{}", ci.namespace()));
|
||||
}
|
||||
|
||||
fn update_from_cdylib_name(&mut self, cdylib_name: &str) {
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| cdylib_name.to_string());
|
||||
}
|
||||
|
||||
fn update_from_dependency_configs(&mut self, config_map: HashMap<&str, &Self>) {
|
||||
for (crate_name, config) in config_map {
|
||||
if !self.external_packages.contains_key(crate_name) {
|
||||
self.external_packages
|
||||
.insert(crate_name.to_string(), config.package_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate kotlin bindings for the given ComponentInterface, as a string.
|
||||
pub fn generate_bindings(config: &Config, ci: &ComponentInterface) -> Result<String> {
|
||||
KotlinWrapper::new(config.clone(), ci)
|
||||
|
@ -431,9 +431,10 @@ impl KotlinCodeOracle {
|
|||
FfiType::Float64 => "Double".to_string(),
|
||||
FfiType::Handle => "Long".to_string(),
|
||||
FfiType::RustArcPtr(_) => "Pointer".to_string(),
|
||||
FfiType::RustBuffer(maybe_suffix) => {
|
||||
format!("RustBuffer{}", maybe_suffix.as_deref().unwrap_or_default())
|
||||
}
|
||||
FfiType::RustBuffer(maybe_external) => match maybe_external {
|
||||
Some(external_meta) => format!("RustBuffer{}", external_meta.name),
|
||||
None => "RustBuffer".to_string(),
|
||||
},
|
||||
FfiType::RustCallStatus => "UniffiRustCallStatus.ByValue".to_string(),
|
||||
FfiType::ForeignBytes => "ForeignBytes.ByValue".to_string(),
|
||||
FfiType::Callback(name) => self.ffi_callback_name(name),
|
||||
|
@ -721,3 +722,30 @@ mod filters {
|
|||
Ok(textwrap::indent(&wrapped, &" ".repeat(spaces)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_kotlin_version() {
|
||||
assert_eq!(
|
||||
KotlinVersion::parse("1.2.3").unwrap(),
|
||||
KotlinVersion::new(1, 2, 3)
|
||||
);
|
||||
assert_eq!(
|
||||
KotlinVersion::parse("2.3").unwrap(),
|
||||
KotlinVersion::new(2, 3, 0),
|
||||
);
|
||||
assert_eq!(
|
||||
KotlinVersion::parse("2").unwrap(),
|
||||
KotlinVersion::new(2, 0, 0),
|
||||
);
|
||||
assert!(KotlinVersion::parse("2.").is_err());
|
||||
assert!(KotlinVersion::parse("").is_err());
|
||||
assert!(KotlinVersion::parse("A.B.C").is_err());
|
||||
assert!(KotlinVersion::new(1, 2, 3) > KotlinVersion::new(0, 1, 2));
|
||||
assert!(KotlinVersion::new(1, 2, 3) > KotlinVersion::new(0, 100, 0));
|
||||
assert!(KotlinVersion::new(10, 0, 0) > KotlinVersion::new(1, 10, 0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,37 +2,88 @@
|
|||
* 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 crate::{BindingGenerator, Component, GenerationSettings};
|
||||
use anyhow::Result;
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use fs_err as fs;
|
||||
use std::collections::HashMap;
|
||||
use std::process::Command;
|
||||
|
||||
pub mod gen_kotlin;
|
||||
pub use gen_kotlin::{generate_bindings, Config};
|
||||
mod test;
|
||||
mod gen_kotlin;
|
||||
use gen_kotlin::{generate_bindings, Config};
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub mod test;
|
||||
|
||||
use super::super::interface::ComponentInterface;
|
||||
pub use test::{run_script, run_test};
|
||||
pub struct KotlinBindingGenerator;
|
||||
impl BindingGenerator for KotlinBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let mut kt_file = full_bindings_path(config, out_dir);
|
||||
fs::create_dir_all(&kt_file)?;
|
||||
kt_file.push(format!("{}.kt", ci.namespace()));
|
||||
fs::write(&kt_file, generate_bindings(config, ci)?)?;
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("ktlint").arg("-F").arg(&kt_file).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using ktlint: {e:?}",
|
||||
kt_file.file_name().unwrap(),
|
||||
);
|
||||
}
|
||||
fn new_config(&self, root_toml: &toml::Value) -> Result<Self::Config> {
|
||||
Ok(
|
||||
match root_toml.get("bindings").and_then(|b| b.get("kotlin")) {
|
||||
Some(v) => v.clone().try_into()?,
|
||||
None => Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn update_component_configs(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &mut Vec<Component<Self::Config>>,
|
||||
) -> Result<()> {
|
||||
for c in &mut *components {
|
||||
c.config
|
||||
.package_name
|
||||
.get_or_insert_with(|| format!("uniffi.{}", c.ci.namespace()));
|
||||
c.config.cdylib_name.get_or_insert_with(|| {
|
||||
settings
|
||||
.cdylib
|
||||
.clone()
|
||||
.unwrap_or_else(|| format!("uniffi_{}", c.ci.namespace()))
|
||||
});
|
||||
}
|
||||
// We need to update package names
|
||||
let packages = HashMap::<String, String>::from_iter(
|
||||
components
|
||||
.iter()
|
||||
.map(|c| (c.ci.crate_name().to_string(), c.config.package_name())),
|
||||
);
|
||||
for c in components {
|
||||
for (ext_crate, ext_package) in &packages {
|
||||
if ext_crate != c.ci.crate_name()
|
||||
&& !c.config.external_packages.contains_key(ext_crate)
|
||||
{
|
||||
c.config
|
||||
.external_packages
|
||||
.insert(ext_crate.to_string(), ext_package.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &[Component<Self::Config>],
|
||||
) -> Result<()> {
|
||||
for Component { ci, config, .. } in components {
|
||||
let mut kt_file = full_bindings_path(config, &settings.out_dir);
|
||||
fs::create_dir_all(&kt_file)?;
|
||||
kt_file.push(format!("{}.kt", ci.namespace()));
|
||||
fs::write(&kt_file, generate_bindings(config, ci)?)?;
|
||||
if settings.try_format_code {
|
||||
if let Err(e) = Command::new("ktlint").arg("-F").arg(&kt_file).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using ktlint: {e:?}",
|
||||
kt_file.file_name().unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn full_bindings_path(config: &Config, out_dir: &Utf8Path) -> Utf8PathBuf {
|
||||
|
|
|
@ -12,7 +12,7 @@ internal object uniffiRustFutureContinuationCallbackImpl: UniffiRustFutureContin
|
|||
}
|
||||
}
|
||||
|
||||
internal suspend fun<T, F, E: Exception> uniffiRustCallAsync(
|
||||
internal suspend fun<T, F, E: kotlin.Exception> uniffiRustCallAsync(
|
||||
rustFuture: Long,
|
||||
pollFunc: (Long, UniffiRustFutureContinuationCallback, Long) -> Unit,
|
||||
completeFunc: (Long, UniffiRustCallStatus) -> F,
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* is needed because the UDL type name is used in function/method signatures.
|
||||
* It's also what we have an external type that references a custom type.
|
||||
*/
|
||||
public typealias {{ name }} = {{ builtin|type_name(ci) }}
|
||||
public typealias {{ type_name }} = {{ builtin|type_name(ci) }}
|
||||
public typealias {{ ffi_converter_name }} = {{ builtin|ffi_converter_name }}
|
||||
|
||||
{%- when Some with (config) %}
|
||||
|
@ -21,7 +21,7 @@ public typealias {{ ffi_converter_name }} = {{ builtin|ffi_converter_name }}
|
|||
* is needed because the UDL type name is used in function/method signatures.
|
||||
* It's also what we have an external type that references a custom type.
|
||||
*/
|
||||
public typealias {{ name }} = {{ concrete_type_name }}
|
||||
public typealias {{ type_name }} = {{ concrete_type_name }}
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
|
@ -33,28 +33,28 @@ public typealias {{ name }} = {{ concrete_type_name }}
|
|||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
public object {{ ffi_converter_name }}: FfiConverter<{{ name }}, {{ ffi_type_name }}> {
|
||||
override fun lift(value: {{ ffi_type_name }}): {{ name }} {
|
||||
public object {{ ffi_converter_name }}: FfiConverter<{{ type_name }}, {{ ffi_type_name }}> {
|
||||
override fun lift(value: {{ ffi_type_name }}): {{ type_name }} {
|
||||
val builtinValue = {{ builtin|lift_fn }}(value)
|
||||
return {{ config.into_custom.render("builtinValue") }}
|
||||
}
|
||||
|
||||
override fun lower(value: {{ name }}): {{ ffi_type_name }} {
|
||||
override fun lower(value: {{ type_name }}): {{ ffi_type_name }} {
|
||||
val builtinValue = {{ config.from_custom.render("value") }}
|
||||
return {{ builtin|lower_fn }}(builtinValue)
|
||||
}
|
||||
|
||||
override fun read(buf: ByteBuffer): {{ name }} {
|
||||
override fun read(buf: ByteBuffer): {{ type_name }} {
|
||||
val builtinValue = {{ builtin|read_fn }}(buf)
|
||||
return {{ config.into_custom.render("builtinValue") }}
|
||||
}
|
||||
|
||||
override fun allocationSize(value: {{ name }}): ULong {
|
||||
override fun allocationSize(value: {{ type_name }}): ULong {
|
||||
val builtinValue = {{ config.from_custom.render("value") }}
|
||||
return {{ builtin|allocation_size_fn }}(builtinValue)
|
||||
}
|
||||
|
||||
override fun write(value: {{ name }}, buf: ByteBuffer) {
|
||||
override fun write(value: {{ type_name }}, buf: ByteBuffer) {
|
||||
val builtinValue = {{ config.from_custom.render("value") }}
|
||||
{{ builtin|write_fn }}(builtinValue, buf)
|
||||
}
|
||||
|
|
|
@ -29,7 +29,11 @@ enum class {{ type_name }}(val value: {{ variant_discr_type|type_name(ci) }}) {
|
|||
|
||||
public object {{ e|ffi_converter_name }}: FfiConverterRustBuffer<{{ type_name }}> {
|
||||
override fun read(buf: ByteBuffer) = try {
|
||||
{% if config.use_enum_entries() %}
|
||||
{{ type_name }}.entries[buf.getInt() - 1]
|
||||
{% else -%}
|
||||
{{ type_name }}.values()[buf.getInt() - 1]
|
||||
{%- endif %}
|
||||
} catch (e: IndexOutOfBoundsException) {
|
||||
throw RuntimeException("invalid enum value, something is very wrong!!", e)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{% if e.is_flat() %}
|
||||
{%- call kt::docstring(e, 0) %}
|
||||
sealed class {{ type_name }}(message: String): Exception(message){% if contains_object_references %}, Disposable {% endif %} {
|
||||
sealed class {{ type_name }}(message: String): kotlin.Exception(message){% if contains_object_references %}, Disposable {% endif %} {
|
||||
{% for variant in e.variants() -%}
|
||||
{%- call kt::docstring(variant, 4) %}
|
||||
class {{ variant|error_variant_name }}(message: String) : {{ type_name }}(message)
|
||||
|
@ -16,18 +16,18 @@ sealed class {{ type_name }}(message: String): Exception(message){% if contains_
|
|||
}
|
||||
{%- else %}
|
||||
{%- call kt::docstring(e, 0) %}
|
||||
sealed class {{ type_name }}: Exception(){% if contains_object_references %}, Disposable {% endif %} {
|
||||
sealed class {{ type_name }}: kotlin.Exception(){% if contains_object_references %}, Disposable {% endif %} {
|
||||
{% for variant in e.variants() -%}
|
||||
{%- call kt::docstring(variant, 4) %}
|
||||
{%- let variant_name = variant|error_variant_name %}
|
||||
class {{ variant_name }}(
|
||||
{% for field in variant.fields() -%}
|
||||
{%- call kt::docstring(field, 8) %}
|
||||
val {{ field.name()|var_name }}: {{ field|type_name(ci) }}{% if loop.last %}{% else %}, {% endif %}
|
||||
val {% call kt::field_name(field, loop.index) %}: {{ field|type_name(ci) }}{% if loop.last %}{% else %}, {% endif %}
|
||||
{% endfor -%}
|
||||
) : {{ type_name }}() {
|
||||
override val message
|
||||
get() = "{%- for field in variant.fields() %}{{ field.name()|var_name|unquote }}=${ {{field.name()|var_name }} }{% if !loop.last %}, {% endif %}{% endfor %}"
|
||||
get() = "{%- for field in variant.fields() %}{% call kt::field_name_unquoted(field, loop.index) %}=${ {% call kt::field_name(field, loop.index) %} }{% if !loop.last %}, {% endif %}{% endfor %}"
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
|
@ -88,7 +88,7 @@ public object {{ e|ffi_converter_name }} : FfiConverterRustBuffer<{{ type_name }
|
|||
// Add the size for the Int that specifies the variant plus the size needed for all fields
|
||||
4UL
|
||||
{%- for field in variant.fields() %}
|
||||
+ {{ field|allocation_size_fn }}(value.{{ field.name()|var_name }})
|
||||
+ {{ field|allocation_size_fn }}(value.{% call kt::field_name(field, loop.index) %})
|
||||
{%- endfor %}
|
||||
)
|
||||
{%- endfor %}
|
||||
|
@ -102,7 +102,7 @@ public object {{ e|ffi_converter_name }} : FfiConverterRustBuffer<{{ type_name }
|
|||
is {{ type_name }}.{{ variant|error_variant_name }} -> {
|
||||
buf.putInt({{ loop.index }})
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, buf)
|
||||
{{ field|write_fn }}(value.{% call kt::field_name(field, loop.index) %}, buf)
|
||||
{%- endfor %}
|
||||
Unit
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ internal open class UniffiRustCallStatus : Structure() {
|
|||
}
|
||||
}
|
||||
|
||||
class InternalException(message: String) : Exception(message)
|
||||
class InternalException(message: String) : kotlin.Exception(message)
|
||||
|
||||
// Each top-level error class has a companion object that can lift the error from the call status's rust buffer
|
||||
interface UniffiRustCallStatusErrorHandler<E> {
|
||||
|
@ -46,15 +46,15 @@ interface UniffiRustCallStatusErrorHandler<E> {
|
|||
// synchronize itself
|
||||
|
||||
// Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err
|
||||
private inline fun <U, E: Exception> uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler<E>, callback: (UniffiRustCallStatus) -> U): U {
|
||||
var status = UniffiRustCallStatus();
|
||||
private inline fun <U, E: kotlin.Exception> uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler<E>, callback: (UniffiRustCallStatus) -> U): U {
|
||||
var status = UniffiRustCallStatus()
|
||||
val return_value = callback(status)
|
||||
uniffiCheckCallStatus(errorHandler, status)
|
||||
return return_value
|
||||
}
|
||||
|
||||
// Check UniffiRustCallStatus and throw an error if the call wasn't successful
|
||||
private fun<E: Exception> uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler<E>, status: UniffiRustCallStatus) {
|
||||
private fun<E: kotlin.Exception> uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler<E>, status: UniffiRustCallStatus) {
|
||||
if (status.isSuccess()) {
|
||||
return
|
||||
} else if (status.isError()) {
|
||||
|
@ -83,7 +83,7 @@ object UniffiNullRustCallStatusErrorHandler: UniffiRustCallStatusErrorHandler<In
|
|||
|
||||
// Call a rust function that returns a plain value
|
||||
private inline fun <U> uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U {
|
||||
return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback);
|
||||
return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback)
|
||||
}
|
||||
|
||||
internal inline fun<T> uniffiTraitInterfaceCall(
|
||||
|
@ -93,7 +93,7 @@ internal inline fun<T> uniffiTraitInterfaceCall(
|
|||
) {
|
||||
try {
|
||||
writeReturn(makeCall())
|
||||
} catch(e: Exception) {
|
||||
} catch(e: kotlin.Exception) {
|
||||
callStatus.code = UNIFFI_CALL_UNEXPECTED_ERROR
|
||||
callStatus.error_buf = {{ Type::String.borrow()|lower_fn }}(e.toString())
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ internal inline fun<T, reified E: Throwable> uniffiTraitInterfaceCallWithError(
|
|||
) {
|
||||
try {
|
||||
writeReturn(makeCall())
|
||||
} catch(e: Exception) {
|
||||
} catch(e: kotlin.Exception) {
|
||||
if (e is E) {
|
||||
callStatus.code = UNIFFI_CALL_ERROR
|
||||
callStatus.error_buf = lowerError(e)
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
|
||||
{%- call kt::docstring(obj, 0) %}
|
||||
{% if (is_error) %}
|
||||
open class {{ impl_class_name }} : Exception, Disposable, AutoCloseable, {{ interface_name }} {
|
||||
open class {{ impl_class_name }} : kotlin.Exception, Disposable, AutoCloseable, {{ interface_name }} {
|
||||
{% else -%}
|
||||
open class {{ impl_class_name }}: Disposable, AutoCloseable, {{ interface_name }} {
|
||||
{%- endif %}
|
||||
|
|
|
@ -132,12 +132,19 @@ v{{- field_num -}}
|
|||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
// Macro for destroying fields
|
||||
{% macro field_name_unquoted(field, field_num) %}
|
||||
{%- if field.name().is_empty() -%}
|
||||
v{{- field_num -}}
|
||||
{%- else -%}
|
||||
{{ field.name()|var_name|unquote }}
|
||||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
// Macro for destroying fields
|
||||
{%- macro destroy_fields(member) %}
|
||||
Disposable.destroy(
|
||||
{%- for field in member.fields() %}
|
||||
this.{{ field.name()|var_name }}{%- if !loop.last %}, {% endif -%}
|
||||
{% endfor -%})
|
||||
Disposable.destroy(this.{%- call field_name(field, loop.index) -%})
|
||||
{% endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro docstring_value(maybe_docstring, indent_spaces) %}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
@file:Suppress("NAME_SHADOWING")
|
||||
|
||||
package {{ config.package_name() }};
|
||||
package {{ config.package_name() }}
|
||||
|
||||
// Common helper code.
|
||||
//
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
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 crate::bindings::TargetLanguage;
|
||||
use crate::{bindings::RunScriptOptions, library_mode::generate_bindings, BindingGeneratorDefault};
|
||||
use crate::bindings::RunScriptOptions;
|
||||
use crate::cargo_metadata::CrateConfigSupplier;
|
||||
use crate::library_mode::generate_bindings;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use std::env;
|
||||
|
@ -35,13 +36,12 @@ pub fn run_script(
|
|||
let test_helper = UniFFITestHelper::new(crate_name)?;
|
||||
let out_dir = test_helper.create_out_dir(tmp_dir, script_path)?;
|
||||
let cdylib_path = test_helper.copy_cdylib_to_out_dir(&out_dir)?;
|
||||
|
||||
generate_bindings(
|
||||
&cdylib_path,
|
||||
None,
|
||||
&BindingGeneratorDefault {
|
||||
target_languages: vec![TargetLanguage::Kotlin],
|
||||
try_format_code: false,
|
||||
},
|
||||
&super::KotlinBindingGenerator,
|
||||
&CrateConfigSupplier::from(test_helper.cargo_metadata()),
|
||||
None,
|
||||
&out_dir,
|
||||
false,
|
||||
|
|
|
@ -7,50 +7,29 @@
|
|||
//! This module contains all the code for generating foreign language bindings,
|
||||
//! along with some helpers for executing foreign language scripts or tests.
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use camino::Utf8Path;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
mod kotlin;
|
||||
pub use kotlin::KotlinBindingGenerator;
|
||||
mod python;
|
||||
pub use python::PythonBindingGenerator;
|
||||
mod ruby;
|
||||
pub use ruby::RubyBindingGenerator;
|
||||
mod swift;
|
||||
pub use swift::SwiftBindingGenerator;
|
||||
|
||||
use crate::interface::ComponentInterface;
|
||||
|
||||
pub mod kotlin;
|
||||
pub mod python;
|
||||
pub mod ruby;
|
||||
pub mod swift;
|
||||
|
||||
/// Enumeration of all foreign language targets currently supported by this crate.
|
||||
///
|
||||
/// The functions in this module will delegate to a language-specific backend based
|
||||
/// on the provided `TargetLanguage`. For convenience of calling code we also provide
|
||||
/// a few `TryFrom` implementations to help guess the correct target language from
|
||||
/// e.g. a file extension of command-line argument.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
|
||||
pub enum TargetLanguage {
|
||||
Kotlin,
|
||||
Swift,
|
||||
Python,
|
||||
Ruby,
|
||||
}
|
||||
|
||||
impl fmt::Display for TargetLanguage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Kotlin => write!(f, "kotlin"),
|
||||
Self::Swift => write!(f, "swift"),
|
||||
Self::Python => write!(f, "python"),
|
||||
Self::Ruby => write!(f, "ruby"),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub use self::{
|
||||
kotlin::test as kotlin_test, python::test as python_test, ruby::test as ruby_test,
|
||||
swift::test as swift_test,
|
||||
};
|
||||
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
/// Mode for the `run_script` function defined for each language
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RunScriptOptions {
|
||||
pub show_compiler_messages: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
impl Default for RunScriptOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
@ -58,68 +37,3 @@ impl Default for RunScriptOptions {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for TargetLanguage {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(value: &str) -> Result<Self> {
|
||||
Ok(match value.to_ascii_lowercase().as_str() {
|
||||
"kotlin" | "kt" | "kts" => TargetLanguage::Kotlin,
|
||||
"swift" => TargetLanguage::Swift,
|
||||
"python" | "py" => TargetLanguage::Python,
|
||||
"ruby" | "rb" => TargetLanguage::Ruby,
|
||||
_ => bail!("Unknown or unsupported target language: \"{value}\""),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&std::ffi::OsStr> for TargetLanguage {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(value: &std::ffi::OsStr) -> Result<Self> {
|
||||
match value.to_str() {
|
||||
None => bail!("Unreadable target language"),
|
||||
Some(s) => s.try_into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for TargetLanguage {
|
||||
type Error = anyhow::Error;
|
||||
fn try_from(value: String) -> Result<Self> {
|
||||
TryFrom::try_from(value.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
#[serde(default)]
|
||||
pub(crate) kotlin: kotlin::Config,
|
||||
#[serde(default)]
|
||||
pub(crate) swift: swift::Config,
|
||||
#[serde(default)]
|
||||
pub(crate) python: python::Config,
|
||||
#[serde(default)]
|
||||
pub(crate) ruby: ruby::Config,
|
||||
}
|
||||
|
||||
/// Generate foreign language bindings from a compiled `uniffi` library.
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
language: TargetLanguage,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
match language {
|
||||
TargetLanguage::Kotlin => {
|
||||
kotlin::write_bindings(&config.kotlin, ci, out_dir, try_format_code)?
|
||||
}
|
||||
TargetLanguage::Swift => {
|
||||
swift::write_bindings(&config.swift, ci, out_dir, try_format_code)?
|
||||
}
|
||||
TargetLanguage::Python => {
|
||||
python::write_bindings(&config.python, ci, out_dir, try_format_code)?
|
||||
}
|
||||
TargetLanguage::Ruby => ruby::write_bindings(&config.ruby, ci, out_dir, try_format_code)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ impl CustomCodeType {
|
|||
|
||||
impl CodeType for CustomCodeType {
|
||||
fn type_label(&self) -> String {
|
||||
self.name.clone()
|
||||
super::PythonCodeOracle.class_name(&self.name)
|
||||
}
|
||||
|
||||
fn canonical_name(&self) -> String {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
* 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 anyhow::{bail, Context, Result};
|
||||
use anyhow::{Context, Result};
|
||||
use askama::Template;
|
||||
use camino::Utf8Path;
|
||||
|
||||
use heck::{ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
|
||||
use once_cell::sync::Lazy;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -14,9 +14,9 @@ use std::collections::{BTreeSet, HashMap, HashSet};
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::backend::TemplateExpression;
|
||||
use crate::bindings::python;
|
||||
|
||||
use crate::interface::*;
|
||||
use crate::{BindingGenerator, BindingsConfig};
|
||||
use crate::VisitMut;
|
||||
|
||||
mod callback_interface;
|
||||
mod compounds;
|
||||
|
@ -28,29 +28,6 @@ mod object;
|
|||
mod primitives;
|
||||
mod record;
|
||||
|
||||
pub struct PythonBindingGenerator;
|
||||
|
||||
impl BindingGenerator for PythonBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
ci: &ComponentInterface,
|
||||
config: &Config,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
python::write_bindings(config, ci, out_dir, try_format_code)
|
||||
}
|
||||
|
||||
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
|
||||
if cdylib_name.is_none() {
|
||||
bail!("Generate bindings for Python requires a cdylib, but {library_path} was given");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait tor the implementation.
|
||||
trait CodeType: Debug {
|
||||
/// The language specific label used to reference this type. This will be used in
|
||||
|
@ -135,7 +112,7 @@ static KEYWORDS: Lazy<HashSet<String>> = Lazy::new(|| {
|
|||
// Config options to customize the generated python.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
cdylib_name: Option<String>,
|
||||
pub(super) cdylib_name: Option<String>,
|
||||
#[serde(default)]
|
||||
custom_types: HashMap<String, CustomTypeConfig>,
|
||||
#[serde(default)]
|
||||
|
@ -171,22 +148,8 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
impl BindingsConfig for Config {
|
||||
fn update_from_ci(&mut self, ci: &ComponentInterface) {
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| format!("uniffi_{}", ci.namespace()));
|
||||
}
|
||||
|
||||
fn update_from_cdylib_name(&mut self, cdylib_name: &str) {
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| cdylib_name.to_string());
|
||||
}
|
||||
|
||||
fn update_from_dependency_configs(&mut self, _config_map: HashMap<&str, &Self>) {}
|
||||
}
|
||||
|
||||
// Generate python bindings for the given ComponentInterface, as a string.
|
||||
pub fn generate_python_bindings(config: &Config, ci: &ComponentInterface) -> Result<String> {
|
||||
pub fn generate_python_bindings(config: &Config, ci: &mut ComponentInterface) -> Result<String> {
|
||||
PythonWrapper::new(config.clone(), ci)
|
||||
.render()
|
||||
.context("failed to render python bindings")
|
||||
|
@ -298,6 +261,33 @@ impl<'a> TypeRenderer<'a> {
|
|||
});
|
||||
""
|
||||
}
|
||||
|
||||
// An inefficient algo to return type aliases needed for custom types
|
||||
// in an order such that dependencies are in the correct order.
|
||||
// Eg, if there's a custom type `Guid` -> `str` and another `GuidWrapper` -> `Guid`,
|
||||
// it's important the type alias for `Guid` appears first. Fails to handle
|
||||
// another level of indirection (eg, `A { builtin: C}, B { }, C { builtin: B })`)
|
||||
// but that's pathological :)
|
||||
fn get_custom_type_aliases(&self) -> Vec<(String, &Type)> {
|
||||
let mut ordered = vec![];
|
||||
for type_ in self.ci.iter_types() {
|
||||
if let Type::Custom { name, builtin, .. } = type_ {
|
||||
match ordered.iter().position(|x: &(&str, &Type)| {
|
||||
x.1.iter_types()
|
||||
.any(|nested_type| *name == nested_type.as_codetype().type_label())
|
||||
}) {
|
||||
// This 'name' appears as a builtin, so we must insert our type first.
|
||||
Some(pos) => ordered.insert(pos, (name, builtin)),
|
||||
// Otherwise at the end.
|
||||
None => ordered.push((name, builtin)),
|
||||
}
|
||||
}
|
||||
}
|
||||
ordered
|
||||
.into_iter()
|
||||
.map(|(n, t)| (PythonCodeOracle.class_name(n), t))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
|
@ -309,10 +299,13 @@ pub struct PythonWrapper<'a> {
|
|||
type_imports: BTreeSet<ImportRequirement>,
|
||||
}
|
||||
impl<'a> PythonWrapper<'a> {
|
||||
pub fn new(config: Config, ci: &'a ComponentInterface) -> Self {
|
||||
pub fn new(config: Config, ci: &'a mut ComponentInterface) -> Self {
|
||||
ci.visit_mut(&PythonCodeOracle);
|
||||
|
||||
let type_renderer = TypeRenderer::new(&config, ci);
|
||||
let type_helper_code = type_renderer.render().unwrap();
|
||||
let type_imports = type_renderer.imports.into_inner();
|
||||
|
||||
Self {
|
||||
config,
|
||||
ci,
|
||||
|
@ -364,14 +357,14 @@ impl PythonCodeOracle {
|
|||
|
||||
/// Get the idiomatic Python rendering of an FFI callback function name
|
||||
fn ffi_callback_name(&self, nm: &str) -> String {
|
||||
format!("UNIFFI_{}", nm.to_shouty_snake_case())
|
||||
format!("_UNIFFI_{}", nm.to_shouty_snake_case())
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of an FFI struct name
|
||||
fn ffi_struct_name(&self, nm: &str) -> String {
|
||||
// The ctypes docs use both SHOUTY_SNAKE_CASE AND UpperCamelCase for structs. Let's use
|
||||
// UpperCamelCase and reserve shouting for global variables
|
||||
format!("Uniffi{}", nm.to_upper_camel_case())
|
||||
format!("_Uniffi{}", nm.to_upper_camel_case())
|
||||
}
|
||||
|
||||
fn ffi_type_label(&self, ffi_type: &FfiType) -> String {
|
||||
|
@ -388,8 +381,8 @@ impl PythonCodeOracle {
|
|||
FfiType::Float64 => "ctypes.c_double".to_string(),
|
||||
FfiType::Handle => "ctypes.c_uint64".to_string(),
|
||||
FfiType::RustArcPtr(_) => "ctypes.c_void_p".to_string(),
|
||||
FfiType::RustBuffer(maybe_suffix) => match maybe_suffix {
|
||||
Some(suffix) => format!("_UniffiRustBuffer{suffix}"),
|
||||
FfiType::RustBuffer(maybe_external) => match maybe_external {
|
||||
Some(external_meta) => format!("_UniffiRustBuffer{}", external_meta.name),
|
||||
None => "_UniffiRustBuffer".to_string(),
|
||||
},
|
||||
FfiType::RustCallStatus => "_UniffiRustCallStatus".to_string(),
|
||||
|
@ -418,8 +411,10 @@ impl PythonCodeOracle {
|
|||
| FfiType::Int64 => "0".to_owned(),
|
||||
FfiType::Float32 | FfiType::Float64 => "0.0".to_owned(),
|
||||
FfiType::RustArcPtr(_) => "ctypes.c_void_p()".to_owned(),
|
||||
FfiType::RustBuffer(maybe_suffix) => match maybe_suffix {
|
||||
Some(suffix) => format!("_UniffiRustBuffer{suffix}.default()"),
|
||||
FfiType::RustBuffer(maybe_external) => match maybe_external {
|
||||
Some(external_meta) => {
|
||||
format!("_UniffiRustBuffer{}.default()", external_meta.name)
|
||||
}
|
||||
None => "_UniffiRustBuffer.default()".to_owned(),
|
||||
},
|
||||
_ => unimplemented!("FFI return type: {t:?}"),
|
||||
|
@ -448,6 +443,84 @@ impl PythonCodeOracle {
|
|||
}
|
||||
}
|
||||
|
||||
impl VisitMut for PythonCodeOracle {
|
||||
fn visit_record(&self, record: &mut Record) {
|
||||
record.rename(self.class_name(record.name()));
|
||||
}
|
||||
|
||||
fn visit_object(&self, object: &mut Object) {
|
||||
object.rename(self.class_name(object.name()));
|
||||
}
|
||||
|
||||
fn visit_field(&self, field: &mut Field) {
|
||||
field.rename(self.var_name(field.name()));
|
||||
}
|
||||
|
||||
fn visit_ffi_field(&self, ffi_field: &mut FfiField) {
|
||||
ffi_field.rename(self.var_name(ffi_field.name()));
|
||||
}
|
||||
|
||||
fn visit_ffi_argument(&self, ffi_argument: &mut FfiArgument) {
|
||||
ffi_argument.rename(self.class_name(ffi_argument.name()));
|
||||
}
|
||||
|
||||
fn visit_enum(&self, is_error: bool, enum_: &mut Enum) {
|
||||
if is_error {
|
||||
enum_.rename(self.class_name(enum_.name()));
|
||||
} else {
|
||||
enum_.rename(self.enum_variant_name(enum_.name()));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_enum_key(&self, key: &mut String) -> String {
|
||||
self.class_name(key)
|
||||
}
|
||||
|
||||
fn visit_variant(&self, is_error: bool, variant: &mut Variant) {
|
||||
//TODO: If we want to remove the last var_name filter
|
||||
// in the template, this is it. We need an additional
|
||||
// attribute for the `Variant` so we can
|
||||
// display Python is_NAME functions
|
||||
// variant.set_is_name(self.var_name(variant.name()));
|
||||
|
||||
if is_error {
|
||||
variant.rename(self.class_name(variant.name()));
|
||||
} else {
|
||||
variant.rename(self.enum_variant_name(variant.name()));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_type(&self, type_: &mut Type) {
|
||||
// Renaming Types is a special case. We have simple types with names like
|
||||
// an Object, but we also have types which have inner_types and builtin types.
|
||||
// Which in turn have a different name. Therefore we pass the patterns as a
|
||||
// function down to the renaming operation of the type itself, which can apply it
|
||||
// to all its nested names if needed.
|
||||
let name_transformer = |name: &str| self.class_name(name);
|
||||
type_.rename_recursive(&name_transformer);
|
||||
}
|
||||
|
||||
fn visit_method(&self, method: &mut Method) {
|
||||
method.rename(self.fn_name(method.name()));
|
||||
}
|
||||
|
||||
fn visit_argument(&self, argument: &mut Argument) {
|
||||
argument.rename(self.var_name(argument.name()));
|
||||
}
|
||||
|
||||
fn visit_constructor(&self, constructor: &mut Constructor) {
|
||||
if !constructor.is_primary_constructor() {
|
||||
constructor.rename(self.fn_name(constructor.name()));
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_function(&self, function: &mut Function) {
|
||||
// Conversions for wrapper.py
|
||||
//TODO: Renaming the function name in wrapper.py is not currently tested
|
||||
function.rename(self.fn_name(function.name()));
|
||||
}
|
||||
}
|
||||
|
||||
trait AsCodeType {
|
||||
fn as_codetype(&self) -> Box<dyn CodeType>;
|
||||
}
|
||||
|
@ -509,6 +582,20 @@ pub mod filters {
|
|||
Ok(as_ct.as_codetype().type_label())
|
||||
}
|
||||
|
||||
//TODO: Remove. Currently just being used by EnumTemplate.py to
|
||||
// display is_NAME_OF_ENUM.
|
||||
/// Get the idiomatic Python rendering of a variable name.
|
||||
pub fn var_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.var_name(nm))
|
||||
}
|
||||
|
||||
//TODO: Remove. Currently just being used by wrapper.py to display the
|
||||
// callback_interface function names.
|
||||
/// Get the idiomatic Python rendering of a class name (for enums, records, errors, etc).
|
||||
pub fn class_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.class_name(nm))
|
||||
}
|
||||
|
||||
pub(super) fn ffi_converter_name(as_ct: &impl AsCodeType) -> Result<String, askama::Error> {
|
||||
Ok(String::from("_Uniffi") + &as_ct.as_codetype().ffi_converter_name()[3..])
|
||||
}
|
||||
|
@ -558,26 +645,6 @@ pub mod filters {
|
|||
Ok(PythonCodeOracle.ffi_default_value(return_type.as_ref()))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of a class name (for enums, records, errors, etc).
|
||||
pub fn class_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.class_name(nm))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of a function name.
|
||||
pub fn fn_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.fn_name(nm))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of a variable name.
|
||||
pub fn var_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.var_name(nm))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of an individual enum variant.
|
||||
pub fn enum_variant_py(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.enum_variant_name(nm))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of an FFI callback function name
|
||||
pub fn ffi_callback_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(PythonCodeOracle.ffi_callback_name(nm))
|
||||
|
|
|
@ -5,33 +5,64 @@
|
|||
use std::process::Command;
|
||||
|
||||
use anyhow::Result;
|
||||
use camino::Utf8Path;
|
||||
use fs_err as fs;
|
||||
|
||||
pub mod gen_python;
|
||||
mod test;
|
||||
use super::super::interface::ComponentInterface;
|
||||
pub use gen_python::{generate_python_bindings, Config};
|
||||
pub use test::{run_script, run_test};
|
||||
mod gen_python;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub mod test;
|
||||
use crate::{BindingGenerator, Component, GenerationSettings};
|
||||
|
||||
// Generate python bindings for the given ComponentInterface, in the given output directory.
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let py_file = out_dir.join(format!("{}.py", ci.namespace()));
|
||||
fs::write(&py_file, generate_python_bindings(config, ci)?)?;
|
||||
use gen_python::{generate_python_bindings, Config};
|
||||
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("yapf").arg(&py_file).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using yapf: {e:?}",
|
||||
py_file.file_name().unwrap(),
|
||||
)
|
||||
}
|
||||
pub struct PythonBindingGenerator;
|
||||
|
||||
impl BindingGenerator for PythonBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
fn new_config(&self, root_toml: &toml::Value) -> Result<Self::Config> {
|
||||
Ok(
|
||||
match root_toml.get("bindings").and_then(|b| b.get("python")) {
|
||||
Some(v) => v.clone().try_into()?,
|
||||
None => Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fn update_component_configs(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &mut Vec<Component<Self::Config>>,
|
||||
) -> Result<()> {
|
||||
for c in &mut *components {
|
||||
c.config.cdylib_name.get_or_insert_with(|| {
|
||||
settings
|
||||
.cdylib
|
||||
.clone()
|
||||
.unwrap_or_else(|| format!("uniffi_{}", c.ci.namespace()))
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &[Component<Self::Config>],
|
||||
) -> Result<()> {
|
||||
for Component { ci, config, .. } in components {
|
||||
let py_file = settings.out_dir.join(format!("{}.py", ci.namespace()));
|
||||
fs::write(&py_file, generate_python_bindings(config, &mut ci.clone())?)?;
|
||||
|
||||
if settings.try_format_code {
|
||||
if let Err(e) = Command::new("yapf").arg(&py_file).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using yapf: {e:?}",
|
||||
py_file.file_name().unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ _UNIFFI_RUST_FUTURE_POLL_MAYBE_READY = 1
|
|||
# Stores futures for _uniffi_continuation_callback
|
||||
_UniffiContinuationHandleMap = _UniffiHandleMap()
|
||||
|
||||
UNIFFI_GLOBAL_EVENT_LOOP = None
|
||||
_UNIFFI_GLOBAL_EVENT_LOOP = None
|
||||
|
||||
"""
|
||||
Set the event loop to use for async functions
|
||||
|
@ -20,18 +20,18 @@ In this case, we need an event loop to run the Python async function, but there'
|
|||
for the thread. Use `uniffi_set_event_loop` to force an eventloop to be used in this case.
|
||||
"""
|
||||
def uniffi_set_event_loop(eventloop: asyncio.BaseEventLoop):
|
||||
global UNIFFI_GLOBAL_EVENT_LOOP
|
||||
UNIFFI_GLOBAL_EVENT_LOOP = eventloop
|
||||
global _UNIFFI_GLOBAL_EVENT_LOOP
|
||||
_UNIFFI_GLOBAL_EVENT_LOOP = eventloop
|
||||
|
||||
def _uniffi_get_event_loop():
|
||||
if UNIFFI_GLOBAL_EVENT_LOOP is not None:
|
||||
return UNIFFI_GLOBAL_EVENT_LOOP
|
||||
if _UNIFFI_GLOBAL_EVENT_LOOP is not None:
|
||||
return _UNIFFI_GLOBAL_EVENT_LOOP
|
||||
else:
|
||||
return asyncio.get_running_loop()
|
||||
|
||||
# Continuation callback for async functions
|
||||
# lift the return value or error and resolve the future, causing the async function to resume.
|
||||
@UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK
|
||||
@_UNIFFI_RUST_FUTURE_CONTINUATION_CALLBACK
|
||||
def _uniffi_continuation_callback(future_ptr, poll_code):
|
||||
(eventloop, future) = _UniffiContinuationHandleMap.remove(future_ptr)
|
||||
eventloop.call_soon_threadsafe(_uniffi_set_future_result, future, poll_code)
|
||||
|
@ -57,13 +57,13 @@ async def _uniffi_rust_call_async(rust_future, ffi_poll, ffi_complete, ffi_free,
|
|||
break
|
||||
|
||||
return lift_func(
|
||||
_rust_call_with_error(error_ffi_converter, ffi_complete, rust_future)
|
||||
_uniffi_rust_call_with_error(error_ffi_converter, ffi_complete, rust_future)
|
||||
)
|
||||
finally:
|
||||
ffi_free(rust_future)
|
||||
|
||||
{%- if ci.has_async_callback_interface_definition() %}
|
||||
def uniffi_trait_interface_call_async(make_call, handle_success, handle_error):
|
||||
def _uniffi_trait_interface_call_async(make_call, handle_success, handle_error):
|
||||
async def make_call_and_call_callback():
|
||||
try:
|
||||
handle_success(await make_call())
|
||||
|
@ -76,10 +76,10 @@ def uniffi_trait_interface_call_async(make_call, handle_success, handle_error):
|
|||
)
|
||||
eventloop = _uniffi_get_event_loop()
|
||||
task = asyncio.run_coroutine_threadsafe(make_call_and_call_callback(), eventloop)
|
||||
handle = UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.insert((eventloop, task))
|
||||
return UniffiForeignFuture(handle, uniffi_foreign_future_free)
|
||||
handle = _UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.insert((eventloop, task))
|
||||
return _UniffiForeignFuture(handle, _uniffi_foreign_future_free)
|
||||
|
||||
def uniffi_trait_interface_call_async_with_error(make_call, handle_success, handle_error, error_type, lower_error):
|
||||
def _uniffi_trait_interface_call_async_with_error(make_call, handle_success, handle_error, error_type, lower_error):
|
||||
async def make_call_and_call_callback():
|
||||
try:
|
||||
try:
|
||||
|
@ -98,17 +98,17 @@ def uniffi_trait_interface_call_async_with_error(make_call, handle_success, hand
|
|||
)
|
||||
eventloop = _uniffi_get_event_loop()
|
||||
task = asyncio.run_coroutine_threadsafe(make_call_and_call_callback(), eventloop)
|
||||
handle = UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.insert((eventloop, task))
|
||||
return UniffiForeignFuture(handle, uniffi_foreign_future_free)
|
||||
handle = _UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.insert((eventloop, task))
|
||||
return _UniffiForeignFuture(handle, _uniffi_foreign_future_free)
|
||||
|
||||
UNIFFI_FOREIGN_FUTURE_HANDLE_MAP = _UniffiHandleMap()
|
||||
_UNIFFI_FOREIGN_FUTURE_HANDLE_MAP = _UniffiHandleMap()
|
||||
|
||||
@UNIFFI_FOREIGN_FUTURE_FREE
|
||||
def uniffi_foreign_future_free(handle):
|
||||
(eventloop, task) = UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.remove(handle)
|
||||
eventloop.call_soon(uniffi_foreign_future_do_free, task)
|
||||
@_UNIFFI_FOREIGN_FUTURE_FREE
|
||||
def _uniffi_foreign_future_free(handle):
|
||||
(eventloop, task) = _UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.remove(handle)
|
||||
eventloop.call_soon(_uniffi_foreign_future_do_free, task)
|
||||
|
||||
def uniffi_foreign_future_do_free(task):
|
||||
def _uniffi_foreign_future_do_free(task):
|
||||
if not task.done():
|
||||
task.cancel()
|
||||
{%- endif %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% if self.include_once_check("CallbackInterfaceRuntime.py") %}{% include "CallbackInterfaceRuntime.py" %}{% endif %}
|
||||
{%- let trait_impl=format!("UniffiTraitImpl{}", name) %}
|
||||
{%- let trait_impl=format!("_UniffiTraitImpl{}", name) %}
|
||||
|
||||
# Put all the bits inside a class to keep the top-level namespace clean
|
||||
class {{ trait_impl }}:
|
||||
|
@ -7,9 +7,9 @@ class {{ trait_impl }}:
|
|||
{%- for (ffi_callback, meth) in vtable_methods.iter() %}
|
||||
|
||||
@{{ ffi_callback.name()|ffi_callback_name }}
|
||||
def {{ meth.name()|fn_name }}(
|
||||
def {{ meth.name() }}(
|
||||
{%- for arg in ffi_callback.arguments() %}
|
||||
{{ arg.name()|var_name }},
|
||||
{{ arg.name() }},
|
||||
{%- endfor -%}
|
||||
{%- if ffi_callback.has_rust_call_status_arg() %}
|
||||
uniffi_call_status_ptr,
|
||||
|
@ -17,8 +17,8 @@ class {{ trait_impl }}:
|
|||
):
|
||||
uniffi_obj = {{ ffi_converter_name }}._handle_map.get(uniffi_handle)
|
||||
def make_call():
|
||||
args = ({% for arg in meth.arguments() %}{{ arg|lift_fn }}({{ arg.name()|var_name }}), {% endfor %})
|
||||
method = uniffi_obj.{{ meth.name()|fn_name }}
|
||||
args = ({% for arg in meth.arguments() %}{{ arg|lift_fn }}({{ arg.name() }}), {% endfor %})
|
||||
method = uniffi_obj.{{ meth.name() }}
|
||||
return method(*args)
|
||||
|
||||
{% if !meth.is_async() %}
|
||||
|
@ -75,24 +75,24 @@ class {{ trait_impl }}:
|
|||
|
||||
{%- match meth.throws_type() %}
|
||||
{%- when None %}
|
||||
uniffi_out_return[0] = uniffi_trait_interface_call_async(make_call, handle_success, handle_error)
|
||||
uniffi_out_return[0] = _uniffi_trait_interface_call_async(make_call, handle_success, handle_error)
|
||||
{%- when Some(error) %}
|
||||
uniffi_out_return[0] = uniffi_trait_interface_call_async_with_error(make_call, handle_success, handle_error, {{ error|type_name }}, {{ error|lower_fn }})
|
||||
uniffi_out_return[0] = _uniffi_trait_interface_call_async_with_error(make_call, handle_success, handle_error, {{ error|type_name }}, {{ error|lower_fn }})
|
||||
{%- endmatch %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
||||
@{{ "CallbackInterfaceFree"|ffi_callback_name }}
|
||||
def uniffi_free(uniffi_handle):
|
||||
def _uniffi_free(uniffi_handle):
|
||||
{{ ffi_converter_name }}._handle_map.remove(uniffi_handle)
|
||||
|
||||
# Generate the FFI VTable. This has a field for each callback interface method.
|
||||
uniffi_vtable = {{ vtable|ffi_type_name }}(
|
||||
_uniffi_vtable = {{ vtable|ffi_type_name }}(
|
||||
{%- for (_, meth) in vtable_methods.iter() %}
|
||||
{{ meth.name()|fn_name }},
|
||||
{{ meth.name() }},
|
||||
{%- endfor %}
|
||||
uniffi_free
|
||||
_uniffi_free
|
||||
)
|
||||
# Send Rust a pointer to the VTable. Note: this means we need to keep the struct alive forever,
|
||||
# or else bad things will happen when Rust tries to access it.
|
||||
_UniffiLib.{{ ffi_init_callback.name() }}(ctypes.byref(uniffi_vtable))
|
||||
_UniffiLib.{{ ffi_init_callback.name() }}(ctypes.byref(_uniffi_vtable))
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Magic number for the Rust proxy to call using the same mechanism as every other method,
|
||||
# to free the callback once it's dropped by Rust.
|
||||
IDX_CALLBACK_FREE = 0
|
||||
_UNIFFI_IDX_CALLBACK_FREE = 0
|
||||
# Return codes for callback calls
|
||||
_UNIFFI_CALLBACK_SUCCESS = 0
|
||||
_UNIFFI_CALLBACK_ERROR = 1
|
||||
_UNIFFI_CALLBACK_UNEXPECTED_ERROR = 2
|
||||
|
||||
class UniffiCallbackInterfaceFfiConverter:
|
||||
class _UniffiCallbackInterfaceFfiConverter:
|
||||
_handle_map = _UniffiHandleMap()
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
{% include "CallbackInterfaceImpl.py" %}
|
||||
|
||||
# The _UniffiConverter which transforms the Callbacks in to Handles to pass to Rust.
|
||||
{{ ffi_converter_name }} = UniffiCallbackInterfaceFfiConverter()
|
||||
{{ ffi_converter_name }} = _UniffiCallbackInterfaceFfiConverter()
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
{%- match python_config.custom_types.get(name.as_str()) %}
|
||||
{% when None %}
|
||||
{#- No custom type config, just forward all methods to our builtin type #}
|
||||
# Type alias
|
||||
{{ name }} = {{ builtin|type_name }}
|
||||
|
||||
class _UniffiConverterType{{ name }}:
|
||||
@staticmethod
|
||||
def write(value, buf):
|
||||
|
@ -35,9 +32,6 @@ class _UniffiConverterType{{ name }}:
|
|||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
# Type alias
|
||||
{{ name }} = {{ builtin|type_name }}
|
||||
|
||||
{#- Custom type config supplied, use it to convert the builtin type #}
|
||||
class _UniffiConverterType{{ name }}:
|
||||
@staticmethod
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
class {{ type_name }}(enum.Enum):
|
||||
{%- call py::docstring(e, 4) %}
|
||||
{%- for variant in e.variants() %}
|
||||
{{ variant.name()|enum_variant_py }} = {{ e|variant_discr_literal(loop.index0) }}
|
||||
{{ variant.name() }} = {{ e|variant_discr_literal(loop.index0) }}
|
||||
{%- call py::docstring(variant, 4) %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
|
@ -21,13 +21,13 @@ class {{ type_name }}:
|
|||
|
||||
# Each enum variant is a nested class of the enum itself.
|
||||
{% for variant in e.variants() -%}
|
||||
class {{ variant.name()|enum_variant_py }}:
|
||||
class {{ variant.name() }}:
|
||||
{%- call py::docstring(variant, 8) %}
|
||||
|
||||
{%- if variant.has_nameless_fields() %}
|
||||
def __init__(self, *values):
|
||||
if len(values) != {{ variant.fields().len() }}:
|
||||
raise TypeError(f"Expected a tuple of len {{ variant.fields().len() }}, found len {len(values)}")
|
||||
raise TypeError(f"Expected {{ variant.fields().len() }} arguments, found {len(values)}")
|
||||
{%- for field in variant.fields() %}
|
||||
if not isinstance(values[{{ loop.index0 }}], {{ field|type_name }}):
|
||||
raise TypeError(f"unexpected type for tuple element {{ loop.index0 }} - expected '{{ field|type_name }}', got '{type(values[{{ loop.index0 }}])}'")
|
||||
|
@ -38,7 +38,7 @@ class {{ type_name }}:
|
|||
return self._values[index]
|
||||
|
||||
def __str__(self):
|
||||
return f"{{ type_name }}.{{ variant.name()|enum_variant_py }}{self._values!r}"
|
||||
return f"{{ type_name }}.{{ variant.name() }}{self._values!r}"
|
||||
|
||||
def __eq__(self, other):
|
||||
if not other.is_{{ variant.name()|var_name }}():
|
||||
|
@ -47,28 +47,27 @@ class {{ type_name }}:
|
|||
|
||||
{%- else -%}
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field.name()|var_name }}: "{{ field|type_name }}"
|
||||
{{ field.name() }}: "{{ field|type_name }}"
|
||||
{%- call py::docstring(field, 8) %}
|
||||
{%- endfor %}
|
||||
|
||||
@typing.no_type_check
|
||||
def __init__(self,{% for field in variant.fields() %}{{ field.name()|var_name }}: "{{- field|type_name }}"{% if loop.last %}{% else %}, {% endif %}{% endfor %}):
|
||||
def __init__(self,{% for field in variant.fields() %}{{ field.name() }}: "{{- field|type_name }}"{% if loop.last %}{% else %}, {% endif %}{% endfor %}):
|
||||
{%- if variant.has_fields() %}
|
||||
{%- for field in variant.fields() %}
|
||||
self.{{ field.name()|var_name }} = {{ field.name()|var_name }}
|
||||
self.{{ field.name() }} = {{ field.name() }}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
pass
|
||||
{%- endif %}
|
||||
|
||||
def __str__(self):
|
||||
return "{{ type_name }}.{{ variant.name()|enum_variant_py }}({% for field in variant.fields() %}{{ field.name()|var_name }}={}{% if loop.last %}{% else %}, {% endif %}{% endfor %})".format({% for field in variant.fields() %}self.{{ field.name()|var_name }}{% if loop.last %}{% else %}, {% endif %}{% endfor %})
|
||||
return "{{ type_name }}.{{ variant.name() }}({% for field in variant.fields() %}{{ field.name() }}={}{% if loop.last %}{% else %}, {% endif %}{% endfor %})".format({% for field in variant.fields() %}self.{{ field.name() }}{% if loop.last %}{% else %}, {% endif %}{% endfor %})
|
||||
|
||||
def __eq__(self, other):
|
||||
if not other.is_{{ variant.name()|var_name }}():
|
||||
return False
|
||||
{%- for field in variant.fields() %}
|
||||
if self.{{ field.name()|var_name }} != other.{{ field.name()|var_name }}:
|
||||
if self.{{ field.name() }} != other.{{ field.name() }}:
|
||||
return False
|
||||
{%- endfor %}
|
||||
return True
|
||||
|
@ -79,14 +78,14 @@ class {{ type_name }}:
|
|||
# whether an instance is that variant.
|
||||
{% for variant in e.variants() -%}
|
||||
def is_{{ variant.name()|var_name }}(self) -> bool:
|
||||
return isinstance(self, {{ type_name }}.{{ variant.name()|enum_variant_py }})
|
||||
return isinstance(self, {{ type_name }}.{{ variant.name() }})
|
||||
{% endfor %}
|
||||
|
||||
# Now, a little trick - we make each nested variant class be a subclass of the main
|
||||
# enum class, so that method calls and instance checks etc will work intuitively.
|
||||
# We might be able to do this a little more neatly with a metaclass, but this'll do.
|
||||
{% for variant in e.variants() -%}
|
||||
{{ type_name }}.{{ variant.name()|enum_variant_py }} = type("{{ type_name }}.{{ variant.name()|enum_variant_py }}", ({{ type_name }}.{{variant.name()|enum_variant_py}}, {{ type_name }},), {}) # type: ignore
|
||||
{{ type_name }}.{{ variant.name() }} = type("{{ type_name }}.{{ variant.name() }}", ({{ type_name }}.{{variant.name()}}, {{ type_name }},), {}) # type: ignore
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
@ -99,9 +98,9 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
{%- for variant in e.variants() %}
|
||||
if variant == {{ loop.index }}:
|
||||
{%- if e.is_flat() %}
|
||||
return {{ type_name }}.{{variant.name()|enum_variant_py}}
|
||||
return {{ type_name }}.{{variant.name()}}
|
||||
{%- else %}
|
||||
return {{ type_name }}.{{variant.name()|enum_variant_py}}(
|
||||
return {{ type_name }}.{{variant.name()}}(
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field|read_fn }}(buf),
|
||||
{%- endfor %}
|
||||
|
@ -117,7 +116,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
{%- else %}
|
||||
{%- for variant in e.variants() %}
|
||||
{%- if e.is_flat() %}
|
||||
if value == {{ type_name }}.{{ variant.name()|enum_variant_py }}:
|
||||
if value == {{ type_name }}.{{ variant.name() }}:
|
||||
{%- else %}
|
||||
if value.is_{{ variant.name()|var_name }}():
|
||||
{%- endif %}
|
||||
|
@ -125,7 +124,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
{%- if variant.has_nameless_fields() %}
|
||||
{{ field|check_lower_fn }}(value._values[{{ loop.index0 }}])
|
||||
{%- else %}
|
||||
{{ field|check_lower_fn }}(value.{{ field.name()|var_name }})
|
||||
{{ field|check_lower_fn }}(value.{{ field.name() }})
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
return
|
||||
|
@ -137,7 +136,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
def write(value, buf):
|
||||
{%- for variant in e.variants() %}
|
||||
{%- if e.is_flat() %}
|
||||
if value == {{ type_name }}.{{ variant.name()|enum_variant_py }}:
|
||||
if value == {{ type_name }}.{{ variant.name() }}:
|
||||
buf.write_i32({{ loop.index }})
|
||||
{%- else %}
|
||||
if value.is_{{ variant.name()|var_name }}():
|
||||
|
@ -146,7 +145,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
{%- if variant.has_nameless_fields() %}
|
||||
{{ field|write_fn }}(value._values[{{ loop.index0 }}], buf)
|
||||
{%- else %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, buf)
|
||||
{{ field|write_fn }}(value.{{ field.name() }}, buf)
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
|
|
|
@ -11,8 +11,9 @@ class {{ type_name }}(Exception):
|
|||
_UniffiTemp{{ type_name }} = {{ type_name }}
|
||||
|
||||
class {{ type_name }}: # type: ignore
|
||||
{%- call py::docstring(e, 4) %}
|
||||
{%- for variant in e.variants() -%}
|
||||
{%- let variant_type_name = variant.name()|class_name -%}
|
||||
{%- let variant_type_name = variant.name() -%}
|
||||
{%- if e.is_flat() %}
|
||||
class {{ variant_type_name }}(_UniffiTemp{{ type_name }}):
|
||||
{%- call py::docstring(variant, 8) %}
|
||||
|
@ -23,19 +24,36 @@ class {{ type_name }}: # type: ignore
|
|||
class {{ variant_type_name }}(_UniffiTemp{{ type_name }}):
|
||||
{%- call py::docstring(variant, 8) %}
|
||||
|
||||
def __init__(self{% for field in variant.fields() %}, {{ field.name()|var_name }}{% endfor %}):
|
||||
{%- if variant.has_nameless_fields() %}
|
||||
def __init__(self, *values):
|
||||
if len(values) != {{ variant.fields().len() }}:
|
||||
raise TypeError(f"Expected {{ variant.fields().len() }} arguments, found {len(values)}")
|
||||
{%- for field in variant.fields() %}
|
||||
if not isinstance(values[{{ loop.index0 }}], {{ field|type_name }}):
|
||||
raise TypeError(f"unexpected type for tuple element {{ loop.index0 }} - expected '{{ field|type_name }}', got '{type(values[{{ loop.index0 }}])}'")
|
||||
{%- endfor %}
|
||||
super().__init__(", ".join(map(repr, values)))
|
||||
self._values = values
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self._values[index]
|
||||
|
||||
{%- else %}
|
||||
def __init__(self{% for field in variant.fields() %}, {{ field.name() }}{% endfor %}):
|
||||
{%- if variant.has_fields() %}
|
||||
super().__init__(", ".join([
|
||||
{%- for field in variant.fields() %}
|
||||
"{{ field.name()|var_name }}={!r}".format({{ field.name()|var_name }}),
|
||||
"{{ field.name() }}={!r}".format({{ field.name() }}),
|
||||
{%- endfor %}
|
||||
]))
|
||||
{%- for field in variant.fields() %}
|
||||
self.{{ field.name()|var_name }} = {{ field.name()|var_name }}
|
||||
self.{{ field.name() }} = {{ field.name() }}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
pass
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
||||
def __repr__(self):
|
||||
return "{{ type_name }}.{{ variant_type_name }}({})".format(str(self))
|
||||
{%- endif %}
|
||||
|
@ -52,12 +70,12 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
variant = buf.read_i32()
|
||||
{%- for variant in e.variants() %}
|
||||
if variant == {{ loop.index }}:
|
||||
return {{ type_name }}.{{ variant.name()|class_name }}(
|
||||
return {{ type_name }}.{{ variant.name() }}(
|
||||
{%- if e.is_flat() %}
|
||||
{{ Type::String.borrow()|read_fn }}(buf),
|
||||
{%- else %}
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field.name()|var_name }}={{ field|read_fn }}(buf),
|
||||
{{ field|read_fn }}(buf),
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
)
|
||||
|
@ -70,9 +88,13 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
pass
|
||||
{%- else %}
|
||||
{%- for variant in e.variants() %}
|
||||
if isinstance(value, {{ type_name }}.{{ variant.name()|class_name }}):
|
||||
if isinstance(value, {{ type_name }}.{{ variant.name() }}):
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field|check_lower_fn }}(value.{{ field.name()|var_name }})
|
||||
{%- if variant.has_nameless_fields() %}
|
||||
{{ field|check_lower_fn }}(value._values[{{ loop.index0 }}])
|
||||
{%- else %}
|
||||
{{ field|check_lower_fn }}(value.{{ field.name() }})
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
return
|
||||
{%- endfor %}
|
||||
|
@ -81,9 +103,13 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
@staticmethod
|
||||
def write(value, buf):
|
||||
{%- for variant in e.variants() %}
|
||||
if isinstance(value, {{ type_name }}.{{ variant.name()|class_name }}):
|
||||
if isinstance(value, {{ type_name }}.{{ variant.name() }}):
|
||||
buf.write_i32({{ loop.index }})
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, buf)
|
||||
{%- if variant.has_nameless_fields() %}
|
||||
{{ field|write_fn }}(value._values[{{ loop.index0 }}], buf)
|
||||
{%- else %}
|
||||
{{ field|write_fn }}(value.{{ field.name() }}, buf)
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{%- endfor %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# External type {{name}} is in namespace "{{namespace}}", crate {{module_path}}
|
||||
{%- let ffi_converter_name = "_UniffiConverterType{}"|format(name) %}
|
||||
{{ self.add_import_of(module, ffi_converter_name) }}
|
||||
{{ self.add_import_of(module, name|class_name) }} {#- import the type alias itself -#}
|
||||
{{ self.add_import_of(module, name) }} {#- import the type alias itself -#}
|
||||
|
||||
{%- let rustbuffer_local_name = "_UniffiRustBuffer{}"|format(name) %}
|
||||
{{ self.add_import_of_as(module, "_UniffiRustBuffer", rustbuffer_local_name) }}
|
||||
|
|
|
@ -20,14 +20,14 @@ class _UniffiHandleMap:
|
|||
with self._lock:
|
||||
return self._map[handle]
|
||||
except KeyError:
|
||||
raise InternalError("UniffiHandleMap.get: Invalid handle")
|
||||
raise InternalError("_UniffiHandleMap.get: Invalid handle")
|
||||
|
||||
def remove(self, handle):
|
||||
try:
|
||||
with self._lock:
|
||||
return self._map.pop(handle)
|
||||
except KeyError:
|
||||
raise InternalError("UniffiHandleMap.remove: Invalid handle")
|
||||
raise InternalError("_UniffiHandleMap.remove: Invalid handle")
|
||||
|
||||
def __len__(self):
|
||||
return len(self._map)
|
||||
|
|
|
@ -32,11 +32,11 @@ class _UniffiRustCallStatus(ctypes.Structure):
|
|||
else:
|
||||
return "_UniffiRustCallStatus(<invalid code>)"
|
||||
|
||||
def _rust_call(fn, *args):
|
||||
def _uniffi_rust_call(fn, *args):
|
||||
# Call a rust function
|
||||
return _rust_call_with_error(None, fn, *args)
|
||||
return _uniffi_rust_call_with_error(None, fn, *args)
|
||||
|
||||
def _rust_call_with_error(error_ffi_converter, fn, *args):
|
||||
def _uniffi_rust_call_with_error(error_ffi_converter, fn, *args):
|
||||
# Call a rust function and handle any errors
|
||||
#
|
||||
# This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code.
|
||||
|
@ -54,7 +54,7 @@ def _uniffi_check_call_status(error_ffi_converter, call_status):
|
|||
elif call_status.code == _UniffiRustCallStatus.CALL_ERROR:
|
||||
if error_ffi_converter is None:
|
||||
call_status.error_buf.free()
|
||||
raise InternalError("_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None")
|
||||
raise InternalError("_uniffi_rust_call_with_error: CALL_ERROR, but error_ffi_converter is None")
|
||||
else:
|
||||
raise error_ffi_converter.lift(call_status.error_buf)
|
||||
elif call_status.code == _UniffiRustCallStatus.CALL_UNEXPECTED_ERROR:
|
||||
|
|
|
@ -76,7 +76,7 @@ _UniffiLib = _uniffi_load_indirect()
|
|||
class {{ ffi_struct.name()|ffi_struct_name }}(ctypes.Structure):
|
||||
_fields_ = [
|
||||
{%- for field in ffi_struct.fields() %}
|
||||
("{{ field.name()|var_name }}", {{ field.type_().borrow()|ffi_type_name }}),
|
||||
("{{ field.name() }}", {{ field.type_().borrow()|ffi_type_name }}),
|
||||
{%- endfor %}
|
||||
]
|
||||
{%- when FfiDefinition::Function(func) %}
|
||||
|
@ -89,4 +89,4 @@ _UniffiLib.{{ func.name() }}.restype = {% match func.return_type() %}{% when Som
|
|||
|
||||
{# Ensure to call the contract verification only after we defined all functions. -#}
|
||||
_uniffi_check_contract_api_version(_UniffiLib)
|
||||
_uniffi_check_api_checksums(_UniffiLib)
|
||||
# _uniffi_check_api_checksums(_UniffiLib)
|
||||
|
|
|
@ -34,10 +34,10 @@ class {{ impl_name }}:
|
|||
# In case of partial initialization of instances.
|
||||
pointer = getattr(self, "_pointer", None)
|
||||
if pointer is not None:
|
||||
_rust_call(_UniffiLib.{{ obj.ffi_object_free().name() }}, pointer)
|
||||
_uniffi_rust_call(_UniffiLib.{{ obj.ffi_object_free().name() }}, pointer)
|
||||
|
||||
def _uniffi_clone_pointer(self):
|
||||
return _rust_call(_UniffiLib.{{ obj.ffi_object_clone().name() }}, self._pointer)
|
||||
return _uniffi_rust_call(_UniffiLib.{{ obj.ffi_object_clone().name() }}, self._pointer)
|
||||
|
||||
# Used by alternative constructors or any methods which return this type.
|
||||
@classmethod
|
||||
|
@ -49,10 +49,9 @@ class {{ impl_name }}:
|
|||
return inst
|
||||
|
||||
{%- for cons in obj.alternate_constructors() %}
|
||||
|
||||
@classmethod
|
||||
{%- if cons.is_async() %}
|
||||
async def {{ cons.name()|fn_name }}(cls, {% call py::arg_list_decl(cons) %}):
|
||||
async def {{ cons.name() }}(cls, {% call py::arg_list_decl(cons) %}):
|
||||
{%- call py::docstring(cons, 8) %}
|
||||
{%- call py::setup_args_extra_indent(cons) %}
|
||||
|
||||
|
@ -65,7 +64,7 @@ class {{ impl_name }}:
|
|||
{% call py::error_ffi_converter(cons) %}
|
||||
)
|
||||
{%- else %}
|
||||
def {{ cons.name()|fn_name }}(cls, {% call py::arg_list_decl(cons) %}):
|
||||
def {{ cons.name() }}(cls, {% call py::arg_list_decl(cons) %}):
|
||||
{%- call py::docstring(cons, 8) %}
|
||||
{%- call py::setup_args_extra_indent(cons) %}
|
||||
# Call the (fallible) function before creating any half-baked object instances.
|
||||
|
@ -75,7 +74,7 @@ class {{ impl_name }}:
|
|||
{% endfor %}
|
||||
|
||||
{%- for meth in obj.methods() -%}
|
||||
{%- call py::method_decl(meth.name()|fn_name, meth) %}
|
||||
{%- call py::method_decl(meth.name(), meth) %}
|
||||
{%- endfor %}
|
||||
{%- for tm in obj.uniffi_traits() -%}
|
||||
{%- match tm %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class {{ protocol_name }}(typing.Protocol):
|
||||
{%- call py::docstring_value(protocol_docstring, 4) %}
|
||||
{%- for meth in methods.iter() %}
|
||||
def {{ meth.name()|fn_name }}(self, {% call py::arg_list_decl(meth) %}):
|
||||
def {{ meth.name() }}(self, {% call py::arg_list_decl(meth) %}):
|
||||
{%- call py::docstring(meth, 8) %}
|
||||
raise NotImplementedError
|
||||
{%- else %}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# Rules for the Python template code
|
||||
|
||||
## Naming
|
||||
|
||||
Private variables, classes, functions, etc. should be prefixed with `_uniffi`, `_Uniffi`, or `_UNIFFI`.
|
||||
The `_` indicates the variable is private and removes it from the autocomplete list.
|
||||
The `uniffi` part avoids naming collisions with user-defined items.
|
||||
Users can use leading underscores in their names if they want, but "uniffi" is reserved for our purposes.
|
||||
|
||||
In particular, make sure to use the `_uniffi` prefix for any variable names in generated functions.
|
||||
If you name a variable something like `result` the code will probably work initially.
|
||||
Then it will break later on when a user decides to define a function with a parameter named `result`.
|
||||
|
||||
Note: this doesn't apply to items that we want to expose, for example users may want to catch `InternalError` so doesn't get the `Uniffi` prefix.
|
|
@ -2,19 +2,18 @@
|
|||
class {{ type_name }}:
|
||||
{%- call py::docstring(rec, 4) %}
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field.name()|var_name }}: "{{ field|type_name }}"
|
||||
{{ field.name() }}: "{{ field|type_name }}"
|
||||
{%- call py::docstring(field, 4) %}
|
||||
{%- endfor %}
|
||||
|
||||
{%- if rec.has_fields() %}
|
||||
@typing.no_type_check
|
||||
def __init__(self, *, {% for field in rec.fields() %}
|
||||
{{- field.name()|var_name }}: "{{- field|type_name }}"
|
||||
{{- field.name() }}: "{{- field|type_name }}"
|
||||
{%- if field.default_value().is_some() %} = _DEFAULT{% endif %}
|
||||
{%- if !loop.last %}, {% endif %}
|
||||
{%- endfor %}):
|
||||
{%- for field in rec.fields() %}
|
||||
{%- let field_name = field.name()|var_name %}
|
||||
{%- let field_name = field.name() %}
|
||||
{%- match field.default_value() %}
|
||||
{%- when None %}
|
||||
self.{{ field_name }} = {{ field_name }}
|
||||
|
@ -28,11 +27,11 @@ class {{ type_name }}:
|
|||
{%- endif %}
|
||||
|
||||
def __str__(self):
|
||||
return "{{ type_name }}({% for field in rec.fields() %}{{ field.name()|var_name }}={}{% if loop.last %}{% else %}, {% endif %}{% endfor %})".format({% for field in rec.fields() %}self.{{ field.name()|var_name }}{% if loop.last %}{% else %}, {% endif %}{% endfor %})
|
||||
return "{{ type_name }}({% for field in rec.fields() %}{{ field.name() }}={}{% if loop.last %}{% else %}, {% endif %}{% endfor %})".format({% for field in rec.fields() %}self.{{ field.name() }}{% if loop.last %}{% else %}, {% endif %}{% endfor %})
|
||||
|
||||
def __eq__(self, other):
|
||||
{%- for field in rec.fields() %}
|
||||
if self.{{ field.name()|var_name }} != other.{{ field.name()|var_name }}:
|
||||
if self.{{ field.name() }} != other.{{ field.name() }}:
|
||||
return False
|
||||
{%- endfor %}
|
||||
return True
|
||||
|
@ -42,7 +41,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
def read(buf):
|
||||
return {{ type_name }}(
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field.name()|var_name }}={{ field|read_fn }}(buf),
|
||||
{{ field.name() }}={{ field|read_fn }}(buf),
|
||||
{%- endfor %}
|
||||
)
|
||||
|
||||
|
@ -52,7 +51,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
pass
|
||||
{%- else %}
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field|check_lower_fn }}(value.{{ field.name()|var_name }})
|
||||
{{ field|check_lower_fn }}(value.{{ field.name() }})
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
|
||||
|
@ -60,7 +59,7 @@ class {{ ffi_converter_name }}(_UniffiConverterRustBuffer):
|
|||
def write(value, buf):
|
||||
{%- if rec.has_fields() %}
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, buf)
|
||||
{{ field|write_fn }}(value.{{ field.name() }}, buf)
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
pass
|
||||
|
|
|
@ -12,14 +12,14 @@ class _UniffiRustBuffer(ctypes.Structure):
|
|||
|
||||
@staticmethod
|
||||
def alloc(size):
|
||||
return _rust_call(_UniffiLib.{{ ci.ffi_rustbuffer_alloc().name() }}, size)
|
||||
return _uniffi_rust_call(_UniffiLib.{{ ci.ffi_rustbuffer_alloc().name() }}, size)
|
||||
|
||||
@staticmethod
|
||||
def reserve(rbuf, additional):
|
||||
return _rust_call(_UniffiLib.{{ ci.ffi_rustbuffer_reserve().name() }}, rbuf, additional)
|
||||
return _uniffi_rust_call(_UniffiLib.{{ ci.ffi_rustbuffer_reserve().name() }}, rbuf, additional)
|
||||
|
||||
def free(self):
|
||||
return _rust_call(_UniffiLib.{{ ci.ffi_rustbuffer_free().name() }}, self)
|
||||
return _uniffi_rust_call(_UniffiLib.{{ ci.ffi_rustbuffer_free().name() }}, self)
|
||||
|
||||
def __str__(self):
|
||||
return "_UniffiRustBuffer(capacity={}, len={}, data={})".format(
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
{%- match func.return_type() -%}
|
||||
{%- when Some with (return_type) %}
|
||||
async def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}) -> "{{ return_type|type_name }}":
|
||||
async def {{ func.name() }}({%- call py::arg_list_decl(func) -%}) -> "{{ return_type|type_name }}":
|
||||
{% when None %}
|
||||
async def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}) -> None:
|
||||
async def {{ func.name() }}({%- call py::arg_list_decl(func) -%}) -> None:
|
||||
{% endmatch %}
|
||||
|
||||
{%- call py::docstring(func, 4) %}
|
||||
|
@ -28,13 +28,13 @@ async def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}) -> Non
|
|||
{%- match func.return_type() -%}
|
||||
{%- when Some with (return_type) %}
|
||||
|
||||
def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}) -> "{{ return_type|type_name }}":
|
||||
def {{ func.name() }}({%- call py::arg_list_decl(func) -%}) -> "{{ return_type|type_name }}":
|
||||
{%- call py::docstring(func, 4) %}
|
||||
{%- call py::setup_args(func) %}
|
||||
return {{ return_type|lift_fn }}({% call py::to_ffi_call(func) %})
|
||||
{% when None %}
|
||||
|
||||
def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}) -> None:
|
||||
def {{ func.name() }}({%- call py::arg_list_decl(func) -%}) -> None:
|
||||
{%- call py::docstring(func, 4) %}
|
||||
{%- call py::setup_args(func) %}
|
||||
{% call py::to_ffi_call(func) %}
|
||||
|
|
|
@ -97,3 +97,11 @@
|
|||
{%- else %}
|
||||
{%- endmatch %}
|
||||
{%- endfor %}
|
||||
|
||||
{#-
|
||||
Setup type aliases for our custom types, has complications due to
|
||||
forward type references, #2067
|
||||
-#}
|
||||
{%- for (name, ty) in self.get_custom_type_aliases() %}
|
||||
{{ name }} = {{ ty|type_name }}
|
||||
{%- endfor %}
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
{%- when Some with (e) -%}
|
||||
{%- match e -%}
|
||||
{%- when Type::Enum { name, module_path } -%}
|
||||
_rust_call_with_error({{ e|ffi_converter_name }},
|
||||
_uniffi_rust_call_with_error({{ e|ffi_converter_name }},
|
||||
{%- when Type::Object { name, module_path, imp } -%}
|
||||
_rust_call_with_error({{ e|ffi_converter_name }}__as_error,
|
||||
_uniffi_rust_call_with_error({{ e|ffi_converter_name }}__as_error,
|
||||
{%- else %}
|
||||
# unsupported error type!
|
||||
{%- endmatch %}
|
||||
{%- else -%}
|
||||
_rust_call(
|
||||
_uniffi_rust_call(
|
||||
{%- endmatch -%}
|
||||
_UniffiLib.{{ func.ffi_func().name() }},
|
||||
{{- prefix }}
|
||||
|
@ -34,7 +34,7 @@ _rust_call(
|
|||
|
||||
{%- macro arg_list_lowered(func) %}
|
||||
{%- for arg in func.arguments() %}
|
||||
{{ arg|lower_fn }}({{ arg.name()|var_name }})
|
||||
{{ arg|lower_fn }}({{ arg.name() }})
|
||||
{%- if !loop.last %},{% endif %}
|
||||
{%- endfor %}
|
||||
{%- endmacro -%}
|
||||
|
@ -54,12 +54,12 @@ _rust_call(
|
|||
|
||||
{#-
|
||||
// Arglist as used in Python declarations of methods, functions and constructors.
|
||||
// Note the var_name and type_name filters.
|
||||
// Note the type_name filters.
|
||||
-#}
|
||||
|
||||
{% macro arg_list_decl(func) %}
|
||||
{%- for arg in func.arguments() -%}
|
||||
{{ arg.name()|var_name }}
|
||||
{{ arg.name() }}
|
||||
{%- match arg.default_value() %}
|
||||
{%- when Some with(literal) %}: "typing.Union[object, {{ arg|type_name -}}]" = _DEFAULT
|
||||
{%- else %}: "{{ arg|type_name -}}"
|
||||
|
@ -88,10 +88,10 @@ _rust_call(
|
|||
{%- match arg.default_value() %}
|
||||
{%- when None %}
|
||||
{%- when Some with(literal) %}
|
||||
if {{ arg.name()|var_name }} is _DEFAULT:
|
||||
{{ arg.name()|var_name }} = {{ literal|literal_py(arg.as_type().borrow()) }}
|
||||
if {{ arg.name() }} is _DEFAULT:
|
||||
{{ arg.name() }} = {{ literal|literal_py(arg.as_type().borrow()) }}
|
||||
{%- endmatch %}
|
||||
{{ arg|check_lower_fn }}({{ arg.name()|var_name }})
|
||||
{{ arg|check_lower_fn }}({{ arg.name() }})
|
||||
{% endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
@ -104,10 +104,10 @@ _rust_call(
|
|||
{%- match arg.default_value() %}
|
||||
{%- when None %}
|
||||
{%- when Some with(literal) %}
|
||||
if {{ arg.name()|var_name }} is _DEFAULT:
|
||||
{{ arg.name()|var_name }} = {{ literal|literal_py(arg.as_type().borrow()) }}
|
||||
if {{ arg.name() }} is _DEFAULT:
|
||||
{{ arg.name() }} = {{ literal|literal_py(arg.as_type().borrow()) }}
|
||||
{%- endmatch %}
|
||||
{{ arg|check_lower_fn }}({{ arg.name()|var_name }})
|
||||
{{ arg|check_lower_fn }}({{ arg.name() }})
|
||||
{% endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import platform
|
|||
{%- endfor %}
|
||||
|
||||
# Used for default argument values
|
||||
_DEFAULT = object()
|
||||
_DEFAULT = object() # type: typing.Any
|
||||
|
||||
{% include "RustBufferTemplate.py" %}
|
||||
{% include "Helpers.py" %}
|
||||
|
@ -67,7 +67,7 @@ __all__ = [
|
|||
"{{ record|type_name }}",
|
||||
{%- endfor %}
|
||||
{%- for func in ci.function_definitions() %}
|
||||
"{{ func.name()|fn_name }}",
|
||||
"{{ func.name() }}",
|
||||
{%- endfor %}
|
||||
{%- for obj in ci.object_definitions() %}
|
||||
"{{ obj|type_name }}",
|
||||
|
@ -75,9 +75,6 @@ __all__ = [
|
|||
{%- for c in ci.callback_interface_definitions() %}
|
||||
"{{ c.name()|class_name }}",
|
||||
{%- endfor %}
|
||||
{%- if ci.has_async_fns() %}
|
||||
"uniffi_set_event_loop",
|
||||
{%- endif %}
|
||||
]
|
||||
|
||||
{% import "macros.py" as py %}
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
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 crate::bindings::TargetLanguage;
|
||||
use crate::{bindings::RunScriptOptions, library_mode::generate_bindings, BindingGeneratorDefault};
|
||||
use crate::bindings::RunScriptOptions;
|
||||
use crate::cargo_metadata::CrateConfigSupplier;
|
||||
use crate::library_mode::generate_bindings;
|
||||
use anyhow::{Context, Result};
|
||||
use camino::Utf8Path;
|
||||
use std::env;
|
||||
|
@ -39,10 +40,8 @@ pub fn run_script(
|
|||
generate_bindings(
|
||||
&cdylib_path,
|
||||
None,
|
||||
&BindingGeneratorDefault {
|
||||
target_languages: vec![TargetLanguage::Python],
|
||||
try_format_code: false,
|
||||
},
|
||||
&super::PythonBindingGenerator,
|
||||
&CrateConfigSupplier::from(test_helper.cargo_metadata()),
|
||||
None,
|
||||
&out_dir,
|
||||
false,
|
||||
|
|
|
@ -2,39 +2,14 @@
|
|||
* 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 anyhow::{bail, Result};
|
||||
use anyhow::Result;
|
||||
use askama::Template;
|
||||
use camino::Utf8Path;
|
||||
|
||||
use heck::{ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Borrow;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::bindings::ruby;
|
||||
use crate::interface::*;
|
||||
use crate::{BindingGenerator, BindingsConfig};
|
||||
|
||||
pub struct RubyBindingGenerator;
|
||||
impl BindingGenerator for RubyBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
ci: &ComponentInterface,
|
||||
config: &Config,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
ruby::write_bindings(config, ci, out_dir, try_format_code)
|
||||
}
|
||||
|
||||
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
|
||||
if cdylib_name.is_none() {
|
||||
bail!("Generate bindings for Ruby requires a cdylib, but {library_path} was given");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const RESERVED_WORDS: &[&str] = &[
|
||||
"alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
|
||||
|
@ -106,7 +81,7 @@ pub fn canonical_name(t: &Type) -> String {
|
|||
// since the details of the underlying component are entirely determined by the `ComponentInterface`.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
cdylib_name: Option<String>,
|
||||
pub(super) cdylib_name: Option<String>,
|
||||
cdylib_path: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -126,20 +101,6 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
impl BindingsConfig for Config {
|
||||
fn update_from_ci(&mut self, ci: &ComponentInterface) {
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| format!("uniffi_{}", ci.namespace()));
|
||||
}
|
||||
|
||||
fn update_from_cdylib_name(&mut self, cdylib_name: &str) {
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| cdylib_name.to_string());
|
||||
}
|
||||
|
||||
fn update_from_dependency_configs(&mut self, _config_map: HashMap<&str, &Self>) {}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "rb", escape = "none", path = "wrapper.rb")]
|
||||
pub struct RubyWrapper<'a> {
|
||||
|
|
|
@ -4,42 +4,67 @@
|
|||
|
||||
use std::process::Command;
|
||||
|
||||
use crate::{BindingGenerator, Component, ComponentInterface, GenerationSettings};
|
||||
use anyhow::{Context, Result};
|
||||
use camino::Utf8Path;
|
||||
use fs_err as fs;
|
||||
|
||||
pub mod gen_ruby;
|
||||
mod test;
|
||||
pub use gen_ruby::{Config, RubyWrapper};
|
||||
pub use test::{run_test, test_script_command};
|
||||
mod gen_ruby;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub mod test;
|
||||
use gen_ruby::{Config, RubyWrapper};
|
||||
|
||||
use super::super::interface::ComponentInterface;
|
||||
pub struct RubyBindingGenerator;
|
||||
impl BindingGenerator for RubyBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
// Generate ruby bindings for the given ComponentInterface, in the given output directory.
|
||||
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let rb_file = out_dir.join(format!("{}.rb", ci.namespace()));
|
||||
fs::write(&rb_file, generate_ruby_bindings(config, ci)?)?;
|
||||
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("rubocop").arg("-A").arg(&rb_file).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using rubocop: {e:?}",
|
||||
rb_file.file_name().unwrap(),
|
||||
)
|
||||
}
|
||||
fn new_config(&self, root_toml: &toml::Value) -> Result<Self::Config> {
|
||||
Ok(
|
||||
match root_toml.get("bindings").and_then(|b| b.get("ruby")) {
|
||||
Some(v) => v.clone().try_into()?,
|
||||
None => Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fn update_component_configs(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &mut Vec<Component<Self::Config>>,
|
||||
) -> Result<()> {
|
||||
for c in &mut *components {
|
||||
c.config.cdylib_name.get_or_insert_with(|| {
|
||||
settings
|
||||
.cdylib
|
||||
.clone()
|
||||
.unwrap_or_else(|| format!("uniffi_{}", c.ci.namespace()))
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &[Component<Self::Config>],
|
||||
) -> Result<()> {
|
||||
for Component { ci, config, .. } in components {
|
||||
let rb_file = settings.out_dir.join(format!("{}.rb", ci.namespace()));
|
||||
fs::write(&rb_file, generate_ruby_bindings(config, ci)?)?;
|
||||
|
||||
if settings.try_format_code {
|
||||
if let Err(e) = Command::new("rubocop").arg("-A").arg(&rb_file).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using rubocop: {e:?}",
|
||||
rb_file.file_name().unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Generate ruby bindings for the given ComponentInterface, as a string.
|
||||
|
||||
pub fn generate_ruby_bindings(config: &Config, ci: &ComponentInterface) -> Result<String> {
|
||||
use askama::Template;
|
||||
RubyWrapper::new(config.clone(), ci)
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
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 crate::bindings::TargetLanguage;
|
||||
use crate::cargo_metadata::CrateConfigSupplier;
|
||||
use crate::library_mode::generate_bindings;
|
||||
use crate::BindingGeneratorDefault;
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::Utf8Path;
|
||||
use std::env;
|
||||
|
@ -38,10 +37,8 @@ pub fn test_script_command(
|
|||
generate_bindings(
|
||||
&cdylib_path,
|
||||
None,
|
||||
&BindingGeneratorDefault {
|
||||
target_languages: vec![TargetLanguage::Ruby],
|
||||
try_format_code: false,
|
||||
},
|
||||
&super::RubyBindingGenerator,
|
||||
&CrateConfigSupplier::from(test_helper.cargo_metadata()),
|
||||
None,
|
||||
&out_dir,
|
||||
false,
|
||||
|
|
|
@ -17,7 +17,7 @@ impl CustomCodeType {
|
|||
|
||||
impl CodeType for CustomCodeType {
|
||||
fn type_label(&self) -> String {
|
||||
self.name.clone()
|
||||
super::SwiftCodeOracle.class_name(&self.name)
|
||||
}
|
||||
|
||||
fn canonical_name(&self) -> String {
|
||||
|
|
|
@ -10,15 +10,14 @@ use std::fmt::Debug;
|
|||
|
||||
use anyhow::{Context, Result};
|
||||
use askama::Template;
|
||||
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::{BindingGenerator, BindingsConfig};
|
||||
|
||||
mod callback_interface;
|
||||
mod compounds;
|
||||
|
@ -30,29 +29,6 @@ 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
|
||||
|
@ -214,8 +190,7 @@ pub fn quote_arg_keyword(nm: String) -> String {
|
|||
/// since the details of the underlying component are entirely determined by the `ComponentInterface`.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
cdylib_name: Option<String>,
|
||||
module_name: Option<String>,
|
||||
pub(super) module_name: Option<String>,
|
||||
ffi_module_name: Option<String>,
|
||||
ffi_module_filename: Option<String>,
|
||||
generate_module_map: Option<bool>,
|
||||
|
@ -236,11 +211,12 @@ pub struct CustomTypeConfig {
|
|||
|
||||
impl Config {
|
||||
/// The name of the Swift module containing the high-level foreign-language bindings.
|
||||
/// Panics if the module name hasn't been configured.
|
||||
pub fn module_name(&self) -> String {
|
||||
match self.module_name.as_ref() {
|
||||
Some(name) => name.clone(),
|
||||
None => "uniffi".into(),
|
||||
}
|
||||
self.module_name
|
||||
.as_ref()
|
||||
.expect("module name should have been set in update_component_configs")
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// The name of the lower-level C module containing the FFI declarations.
|
||||
|
@ -269,15 +245,6 @@ impl Config {
|
|||
format!("{}.h", self.ffi_module_filename())
|
||||
}
|
||||
|
||||
/// The name of the compiled Rust library containing the FFI implementation.
|
||||
pub fn cdylib_name(&self) -> String {
|
||||
if let Some(cdylib_name) = &self.cdylib_name {
|
||||
cdylib_name.clone()
|
||||
} else {
|
||||
"uniffi".into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to generate a `.modulemap` file for the lower-level C module with FFI declarations.
|
||||
pub fn generate_module_map(&self) -> bool {
|
||||
self.generate_module_map.unwrap_or(true)
|
||||
|
@ -299,22 +266,6 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
impl BindingsConfig for Config {
|
||||
fn update_from_ci(&mut self, ci: &ComponentInterface) {
|
||||
self.module_name
|
||||
.get_or_insert_with(|| ci.namespace().into());
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| format!("uniffi_{}", ci.namespace()));
|
||||
}
|
||||
|
||||
fn update_from_cdylib_name(&mut self, cdylib_name: &str) {
|
||||
self.cdylib_name
|
||||
.get_or_insert_with(|| cdylib_name.to_string());
|
||||
}
|
||||
|
||||
fn update_from_dependency_configs(&mut self, _config_map: HashMap<&str, &Self>) {}
|
||||
}
|
||||
|
||||
/// Generate UniFFI component bindings for Swift, as strings in memory.
|
||||
///
|
||||
pub fn generate_bindings(config: &Config, ci: &ComponentInterface) -> Result<Bindings> {
|
||||
|
@ -606,10 +557,6 @@ impl SwiftCodeOracle {
|
|||
}
|
||||
}
|
||||
|
||||
fn ffi_canonical_name(&self, ffi_type: &FfiType) -> String {
|
||||
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.
|
||||
|
@ -704,10 +651,6 @@ pub mod filters {
|
|||
Ok(oracle().ffi_type_label(ffi_type))
|
||||
}
|
||||
|
||||
pub fn ffi_canonical_name(ffi_type: &FfiType) -> Result<String, askama::Error> {
|
||||
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()))
|
||||
}
|
||||
|
@ -766,9 +709,9 @@ pub mod filters {
|
|||
Ok(quote_general_keyword(oracle().enum_variant_name(nm)))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Swift rendering of an individual enum variant, for contexts (for use in non-declaration contexts where quoting is not needed)
|
||||
pub fn enum_variant_swift(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(oracle().enum_variant_name(nm))
|
||||
/// Like enum_variant_swift_quoted, but a class name.
|
||||
pub fn error_variant_swift_quoted(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(quote_general_keyword(oracle().class_name(nm)))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Swift rendering of an FFI callback function name
|
||||
|
@ -795,28 +738,6 @@ pub mod filters {
|
|||
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)?),
|
||||
None => "nil".into(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Name of the callback function to handle an async result
|
||||
pub fn future_callback(result: &ResultType) -> Result<String, askama::Error> {
|
||||
Ok(format!(
|
||||
"uniffiFutureCallbackHandler{}{}",
|
||||
match &result.return_type {
|
||||
Some(t) => SwiftCodeOracle.find(t).canonical_name(),
|
||||
None => "Void".into(),
|
||||
},
|
||||
match &result.throws_type {
|
||||
Some(t) => SwiftCodeOracle.find(t).canonical_name(),
|
||||
None => "".into(),
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
pub fn object_names(obj: &Object) -> Result<(String, String), askama::Error> {
|
||||
Ok(SwiftCodeOracle.object_names(obj))
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! # Swift bindings backend for UniFFI
|
||||
//!
|
||||
//! This module generates Swift bindings from a [`ComponentInterface`] definition,
|
||||
//! This module generates Swift bindings from a [`crate::ComponentInterface`] definition,
|
||||
//! using Swift's builtin support for loading C header files.
|
||||
//!
|
||||
//! Conceptually, the generated bindings are split into two Swift modules, one for the low-level
|
||||
|
@ -17,7 +17,7 @@
|
|||
//! * A Swift source file `example.swift` that imports the `exampleFFI` module and wraps it
|
||||
//! to provide the higher-level Swift API.
|
||||
//!
|
||||
//! Most of the concepts in a [`ComponentInterface`] have an obvious counterpart in Swift,
|
||||
//! Most of the concepts in a [`crate::ComponentInterface`] have an obvious counterpart in Swift,
|
||||
//! with the details documented in inline comments where appropriate.
|
||||
//!
|
||||
//! To handle lifting/lowering/serializing types across the FFI boundary, the Swift code
|
||||
|
@ -29,22 +29,20 @@
|
|||
//! * How to read from and write into a byte buffer.
|
||||
//!
|
||||
|
||||
use crate::{BindingGenerator, Component, GenerationSettings};
|
||||
use anyhow::Result;
|
||||
use fs_err as fs;
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow::Result;
|
||||
use camino::Utf8Path;
|
||||
use fs_err as fs;
|
||||
mod gen_swift;
|
||||
use gen_swift::{generate_bindings, Config};
|
||||
|
||||
pub mod gen_swift;
|
||||
pub use gen_swift::{generate_bindings, Config};
|
||||
mod test;
|
||||
#[cfg(feature = "bindgen-tests")]
|
||||
pub mod test;
|
||||
|
||||
use super::super::interface::ComponentInterface;
|
||||
pub use test::{run_script, run_test};
|
||||
|
||||
/// The Swift bindings generated from a [`ComponentInterface`].
|
||||
/// The Swift bindings generated from a [`crate::ComponentInterface`].
|
||||
///
|
||||
pub struct Bindings {
|
||||
struct Bindings {
|
||||
/// The contents of the generated `.swift` file, as a string.
|
||||
library: String,
|
||||
/// The contents of the generated `.h` file, as a string.
|
||||
|
@ -53,45 +51,73 @@ pub struct Bindings {
|
|||
modulemap: Option<String>,
|
||||
}
|
||||
|
||||
/// Write UniFFI component bindings for Swift as files on disk.
|
||||
///
|
||||
/// Unlike other target languages, binding to Rust code from Swift involves more than just
|
||||
/// generating a `.swift` file. We also need to produce a `.h` file with the C-level API
|
||||
/// declarations, and a `.modulemap` file to tell Swift how to use it.
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let Bindings {
|
||||
header,
|
||||
library,
|
||||
modulemap,
|
||||
} = generate_bindings(config, ci)?;
|
||||
pub struct SwiftBindingGenerator;
|
||||
impl BindingGenerator for SwiftBindingGenerator {
|
||||
type Config = Config;
|
||||
|
||||
let source_file = out_dir.join(format!("{}.swift", config.module_name()));
|
||||
fs::write(&source_file, library)?;
|
||||
|
||||
let header_file = out_dir.join(config.header_filename());
|
||||
fs::write(header_file, header)?;
|
||||
|
||||
if let Some(modulemap) = modulemap {
|
||||
let modulemap_file = out_dir.join(config.modulemap_filename());
|
||||
fs::write(modulemap_file, modulemap)?;
|
||||
fn new_config(&self, root_toml: &toml::Value) -> Result<Self::Config> {
|
||||
Ok(
|
||||
match root_toml.get("bindings").and_then(|b| b.get("swift")) {
|
||||
Some(v) => v.clone().try_into()?,
|
||||
None => Default::default(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("swiftformat")
|
||||
.arg(source_file.as_str())
|
||||
.output()
|
||||
{
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using swiftformat: {e:?}",
|
||||
source_file.file_name().unwrap(),
|
||||
);
|
||||
fn update_component_configs(
|
||||
&self,
|
||||
_settings: &GenerationSettings,
|
||||
components: &mut Vec<Component<Self::Config>>,
|
||||
) -> Result<()> {
|
||||
for c in &mut *components {
|
||||
c.config
|
||||
.module_name
|
||||
.get_or_insert_with(|| c.ci.namespace().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
/// Unlike other target languages, binding to Rust code from Swift involves more than just
|
||||
/// generating a `.swift` file. We also need to produce a `.h` file with the C-level API
|
||||
/// declarations, and a `.modulemap` file to tell Swift how to use it.
|
||||
fn write_bindings(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &[Component<Self::Config>],
|
||||
) -> Result<()> {
|
||||
for Component { ci, config, .. } in components {
|
||||
let Bindings {
|
||||
header,
|
||||
library,
|
||||
modulemap,
|
||||
} = generate_bindings(config, ci)?;
|
||||
|
||||
let source_file = settings
|
||||
.out_dir
|
||||
.join(format!("{}.swift", config.module_name()));
|
||||
fs::write(&source_file, library)?;
|
||||
|
||||
let header_file = settings.out_dir.join(config.header_filename());
|
||||
fs::write(header_file, header)?;
|
||||
|
||||
if let Some(modulemap) = modulemap {
|
||||
let modulemap_file = settings.out_dir.join(config.modulemap_filename());
|
||||
fs::write(modulemap_file, modulemap)?;
|
||||
}
|
||||
|
||||
if settings.try_format_code {
|
||||
if let Err(e) = Command::new("swiftformat")
|
||||
.arg(source_file.as_str())
|
||||
.output()
|
||||
{
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using swiftformat: {e:?}",
|
||||
source_file.file_name().unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ fileprivate func uniffiRustCallAsync<F, T>(
|
|||
completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
|
||||
freeFunc: (UInt64) -> (),
|
||||
liftFunc: (F) throws -> T,
|
||||
errorHandler: ((RustBuffer) throws -> Error)?
|
||||
errorHandler: ((RustBuffer) throws -> Swift.Error)?
|
||||
) async throws -> T {
|
||||
// Make sure to call uniffiEnsureInitialized() since future creation doesn't have a
|
||||
// RustCallStatus param, so doesn't use makeRustCall()
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
* Typealias from the type name used in the UDL file to the builtin type. This
|
||||
* is needed because the UDL type name is used in function/method signatures.
|
||||
*/
|
||||
public typealias {{ name }} = {{ builtin|type_name }}
|
||||
public typealias {{ type_name }} = {{ builtin|type_name }}
|
||||
public struct FfiConverterType{{ name }}: FfiConverter {
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> {{ name }} {
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> {{ type_name }} {
|
||||
return try {{ builtin|read_fn }}(from: &buf)
|
||||
}
|
||||
|
||||
public static func write(_ value: {{ name }}, into buf: inout [UInt8]) {
|
||||
public static func write(_ value: {{ type_name }}, into buf: inout [UInt8]) {
|
||||
return {{ builtin|write_fn }}(value, into: &buf)
|
||||
}
|
||||
|
||||
public static func lift(_ value: {{ ffi_type_name }}) throws -> {{ name }} {
|
||||
public static func lift(_ value: {{ ffi_type_name }}) throws -> {{ type_name }} {
|
||||
return try {{ builtin|lift_fn }}(value)
|
||||
}
|
||||
|
||||
public static func lower(_ value: {{ name }}) -> {{ ffi_type_name }} {
|
||||
public static func lower(_ value: {{ type_name }}) -> {{ ffi_type_name }} {
|
||||
return {{ builtin|lower_fn }}(value)
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ public struct FfiConverterType{{ name }}: FfiConverter {
|
|||
* Typealias from the type name used in the UDL file to the custom type. This
|
||||
* is needed because the UDL type name is used in function/method signatures.
|
||||
*/
|
||||
public typealias {{ name }} = {{ concrete_type_name }}
|
||||
public typealias {{ type_name }} = {{ concrete_type_name }}
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
|
@ -49,22 +49,22 @@ public typealias {{ name }} = {{ concrete_type_name }}
|
|||
public struct FfiConverterType{{ name }}: FfiConverter {
|
||||
{#- Custom type config supplied, use it to convert the builtin type #}
|
||||
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> {{ name }} {
|
||||
public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> {{ type_name }} {
|
||||
let builtinValue = try {{ builtin|read_fn }}(from: &buf)
|
||||
return {{ config.into_custom.render("builtinValue") }}
|
||||
}
|
||||
|
||||
public static func write(_ value: {{ name }}, into buf: inout [UInt8]) {
|
||||
public static func write(_ value: {{ type_name }}, into buf: inout [UInt8]) {
|
||||
let builtinValue = {{ config.from_custom.render("value") }}
|
||||
return {{ builtin|write_fn }}(builtinValue, into: &buf)
|
||||
}
|
||||
|
||||
public static func lift(_ value: {{ ffi_type_name }}) throws -> {{ name }} {
|
||||
public static func lift(_ value: {{ ffi_type_name }}) throws -> {{ type_name }} {
|
||||
let builtinValue = try {{ builtin|lift_fn }}(value)
|
||||
return {{ config.into_custom.render("builtinValue") }}
|
||||
}
|
||||
|
||||
public static func lower(_ value: {{ name }}) -> {{ ffi_type_name }} {
|
||||
public static func lower(_ value: {{ type_name }}) -> {{ ffi_type_name }} {
|
||||
let builtinValue = {{ config.from_custom.render("value") }}
|
||||
return {{ builtin|lower_fn }}(builtinValue)
|
||||
}
|
||||
|
@ -76,11 +76,11 @@ public struct FfiConverterType{{ name }}: FfiConverter {
|
|||
We always write these public functions just incase the type is used as
|
||||
an external type by another crate.
|
||||
#}
|
||||
public func FfiConverterType{{ name }}_lift(_ value: {{ ffi_type_name }}) throws -> {{ name }} {
|
||||
public func FfiConverterType{{ name }}_lift(_ value: {{ ffi_type_name }}) throws -> {{ type_name }} {
|
||||
return try FfiConverterType{{ name }}.lift(value)
|
||||
}
|
||||
|
||||
public func FfiConverterType{{ name }}_lower(_ value: {{ name }}) -> {{ ffi_type_name }} {
|
||||
public func FfiConverterType{{ name }}_lower(_ value: {{ type_name }}) -> {{ ffi_type_name }} {
|
||||
return FfiConverterType{{ name }}.lower(value)
|
||||
}
|
||||
|
||||
|
|
|
@ -37,9 +37,13 @@ public struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
|||
{% else %}
|
||||
|
||||
{% for variant in e.variants() %}
|
||||
case {{ loop.index }}: return .{{ variant.name()|class_name }}{% if variant.has_fields() -%}(
|
||||
case {{ loop.index }}: return .{{ variant.name()|error_variant_swift_quoted }}{% if variant.has_fields() %}(
|
||||
{% for field in variant.fields() -%}
|
||||
{%- if variant.has_nameless_fields() -%}
|
||||
try {{ field|read_fn }}(from: &buf)
|
||||
{%- else -%}
|
||||
{{ field.name()|var_name }}: try {{ field|read_fn }}(from: &buf)
|
||||
{%- endif -%}
|
||||
{%- if !loop.last %}, {% endif %}
|
||||
{% endfor -%}
|
||||
){% endif -%}
|
||||
|
@ -64,10 +68,10 @@ public struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
|||
|
||||
{% for variant in e.variants() %}
|
||||
{% if variant.has_fields() %}
|
||||
case let .{{ variant.name()|class_name }}({% for field in variant.fields() %}{{ field.name()|var_name }}{%- if loop.last -%}{%- else -%},{%- endif -%}{% endfor %}):
|
||||
case let .{{ variant.name()|error_variant_swift_quoted }}({% for field in variant.fields() %}{%- call swift::field_name(field, loop.index) -%}{%- if loop.last -%}{%- else -%},{%- endif -%}{% endfor %}):
|
||||
writeInt(&buf, Int32({{ loop.index }}))
|
||||
{% for field in variant.fields() -%}
|
||||
{{ field|write_fn }}({{ field.name()|var_name }}, into: &buf)
|
||||
{{ field|write_fn }}({% call swift::field_name(field, loop.index) %}, into: &buf)
|
||||
{% endfor -%}
|
||||
{% else %}
|
||||
case .{{ variant.name()|class_name }}:
|
||||
|
@ -83,4 +87,8 @@ public struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
|||
{% if !contains_object_references %}
|
||||
extension {{ type_name }}: Equatable, Hashable {}
|
||||
{% endif %}
|
||||
extension {{ type_name }}: Error { }
|
||||
extension {{ type_name }}: Foundation.LocalizedError {
|
||||
public var errorDescription: String? {
|
||||
String(reflecting: self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,18 +53,19 @@ fileprivate extension RustCallStatus {
|
|||
}
|
||||
|
||||
private func rustCall<T>(_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||
try makeRustCall(callback, errorHandler: nil)
|
||||
let neverThrow: ((RustBuffer) throws -> Never)? = nil
|
||||
return try makeRustCall(callback, errorHandler: neverThrow)
|
||||
}
|
||||
|
||||
private func rustCallWithError<T>(
|
||||
_ errorHandler: @escaping (RustBuffer) throws -> Error,
|
||||
private func rustCallWithError<T, E: Swift.Error>(
|
||||
_ errorHandler: @escaping (RustBuffer) throws -> E,
|
||||
_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T) throws -> T {
|
||||
try makeRustCall(callback, errorHandler: errorHandler)
|
||||
}
|
||||
|
||||
private func makeRustCall<T>(
|
||||
private func makeRustCall<T, E: Swift.Error>(
|
||||
_ callback: (UnsafeMutablePointer<RustCallStatus>) -> T,
|
||||
errorHandler: ((RustBuffer) throws -> Error)?
|
||||
errorHandler: ((RustBuffer) throws -> E)?
|
||||
) throws -> T {
|
||||
uniffiEnsureInitialized()
|
||||
var callStatus = RustCallStatus.init()
|
||||
|
@ -73,9 +74,9 @@ private func makeRustCall<T>(
|
|||
return returnedVal
|
||||
}
|
||||
|
||||
private func uniffiCheckCallStatus(
|
||||
private func uniffiCheckCallStatus<E: Swift.Error>(
|
||||
callStatus: RustCallStatus,
|
||||
errorHandler: ((RustBuffer) throws -> Error)?
|
||||
errorHandler: ((RustBuffer) throws -> E)?
|
||||
) throws {
|
||||
switch callStatus.code {
|
||||
case CALL_SUCCESS:
|
||||
|
|
|
@ -23,7 +23,7 @@ open class {{ impl_class_name }}:
|
|||
{%- endmatch %}
|
||||
{%- endfor %}
|
||||
{%- if is_error %}
|
||||
Error,
|
||||
Swift.Error,
|
||||
{% endif %}
|
||||
{{ protocol_name }} {
|
||||
fileprivate let pointer: UnsafeMutableRawPointer!
|
||||
|
@ -161,6 +161,13 @@ public struct {{ ffi_converter_name }}: FfiConverter {
|
|||
|
||||
{# Objects as error #}
|
||||
{%- if is_error %}
|
||||
|
||||
extension {{ type_name }}: Foundation.LocalizedError {
|
||||
public var errorDescription: String? {
|
||||
String(reflecting: self)
|
||||
}
|
||||
}
|
||||
|
||||
{# Due to some mismatches in the ffi converter mechanisms, errors are a RustBuffer holding a pointer #}
|
||||
public struct {{ ffi_converter_name }}__as_error: FfiConverterRustBuffer {
|
||||
public static func lift(_ buf: RustBuffer) throws -> {{ type_name }} {
|
||||
|
|
|
@ -37,9 +37,11 @@ fileprivate extension ForeignBytes {
|
|||
|
||||
fileprivate extension Data {
|
||||
init(rustBuffer: RustBuffer) {
|
||||
// TODO: This copies the buffer. Can we read directly from a
|
||||
// Rust buffer?
|
||||
self.init(bytes: rustBuffer.data!, count: Int(rustBuffer.len))
|
||||
self.init(
|
||||
bytesNoCopy: rustBuffer.data!,
|
||||
count: Int(rustBuffer.len),
|
||||
deallocator: .none
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +142,7 @@ fileprivate func writeDouble(_ writer: inout [UInt8], _ value: Double) {
|
|||
}
|
||||
|
||||
// Protocol for types that transfer other types across the FFI. This is
|
||||
// analogous go the Rust trait of the same name.
|
||||
// analogous to the Rust trait of the same name.
|
||||
fileprivate protocol FfiConverter {
|
||||
associatedtype FfiType
|
||||
associatedtype SwiftType
|
||||
|
|
|
@ -38,9 +38,9 @@ private enum InitializationResult {
|
|||
case contractVersionMismatch
|
||||
case apiChecksumMismatch
|
||||
}
|
||||
// Use a global variables to perform the versioning checks. Swift ensures that
|
||||
// Use a global variable to perform the versioning checks. Swift ensures that
|
||||
// the code inside is only computed once.
|
||||
private var initializationResult: InitializationResult {
|
||||
private var initializationResult: InitializationResult = {
|
||||
// Get the bindings contract version from our ComponentInterface
|
||||
let bindings_contract_version = {{ ci.uniffi_contract_version() }}
|
||||
// Get the scaffolding contract version by calling the into the dylib
|
||||
|
@ -60,7 +60,7 @@ private var initializationResult: InitializationResult {
|
|||
{% endfor -%}
|
||||
|
||||
return InitializationResult.ok
|
||||
}
|
||||
}()
|
||||
|
||||
private func uniffiEnsureInitialized() {
|
||||
switch initializationResult {
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
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 crate::{bindings::RunScriptOptions, library_mode::generate_bindings, BindingGeneratorDefault};
|
||||
use crate::bindings::RunScriptOptions;
|
||||
use crate::cargo_metadata::CrateConfigSupplier;
|
||||
use crate::library_mode::generate_bindings;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use cargo_metadata::Metadata;
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::{read_to_string, File};
|
||||
|
@ -12,13 +16,11 @@ use std::io::Write;
|
|||
use std::process::{Command, Stdio};
|
||||
use uniffi_testing::UniFFITestHelper;
|
||||
|
||||
use crate::bindings::TargetLanguage;
|
||||
|
||||
/// Run Swift tests for a UniFFI test fixture
|
||||
pub fn run_test(tmp_dir: &str, fixture_name: &str, script_file: &str) -> Result<()> {
|
||||
pub fn run_test(tmp_dir: &str, package_name: &str, script_file: &str) -> Result<()> {
|
||||
run_script(
|
||||
tmp_dir,
|
||||
fixture_name,
|
||||
package_name,
|
||||
script_file,
|
||||
vec![],
|
||||
&RunScriptOptions::default(),
|
||||
|
@ -30,16 +32,21 @@ pub fn run_test(tmp_dir: &str, fixture_name: &str, script_file: &str) -> Result<
|
|||
/// This function will set things up so that the script can import the UniFFI bindings for a crate
|
||||
pub fn run_script(
|
||||
tmp_dir: &str,
|
||||
crate_name: &str,
|
||||
package_name: &str,
|
||||
script_file: &str,
|
||||
args: Vec<String>,
|
||||
options: &RunScriptOptions,
|
||||
) -> Result<()> {
|
||||
let script_path = Utf8Path::new(script_file).canonicalize_utf8()?;
|
||||
let test_helper = UniFFITestHelper::new(crate_name)?;
|
||||
let test_helper = UniFFITestHelper::new(package_name)?;
|
||||
let out_dir = test_helper.create_out_dir(tmp_dir, &script_path)?;
|
||||
let cdylib_path = test_helper.copy_cdylib_to_out_dir(&out_dir)?;
|
||||
let generated_sources = GeneratedSources::new(crate_name, &cdylib_path, &out_dir)?;
|
||||
let generated_sources = GeneratedSources::new(
|
||||
test_helper.crate_name(),
|
||||
&cdylib_path,
|
||||
test_helper.cargo_metadata(),
|
||||
&out_dir,
|
||||
)?;
|
||||
|
||||
// Compile the generated sources together to create a single swift module
|
||||
compile_swift_module(
|
||||
|
@ -124,23 +131,26 @@ struct GeneratedSources {
|
|||
}
|
||||
|
||||
impl GeneratedSources {
|
||||
fn new(crate_name: &str, cdylib_path: &Utf8Path, out_dir: &Utf8Path) -> Result<Self> {
|
||||
fn new(
|
||||
crate_name: &str,
|
||||
cdylib_path: &Utf8Path,
|
||||
cargo_metadata: Metadata,
|
||||
out_dir: &Utf8Path,
|
||||
) -> Result<Self> {
|
||||
let sources = generate_bindings(
|
||||
cdylib_path,
|
||||
None,
|
||||
&BindingGeneratorDefault {
|
||||
target_languages: vec![TargetLanguage::Swift],
|
||||
try_format_code: false,
|
||||
},
|
||||
&super::SwiftBindingGenerator,
|
||||
&CrateConfigSupplier::from(cargo_metadata),
|
||||
None,
|
||||
out_dir,
|
||||
false,
|
||||
)?;
|
||||
let main_source = sources
|
||||
.iter()
|
||||
.find(|s| s.package.name == crate_name)
|
||||
.find(|s| s.ci.crate_name() == crate_name)
|
||||
.unwrap();
|
||||
let main_module = main_source.config.bindings.swift.module_name();
|
||||
let main_module = main_source.config.module_name();
|
||||
let modulemap_glob = glob(&out_dir.join("*.modulemap"))?;
|
||||
let module_map = match modulemap_glob.len() {
|
||||
0 => bail!("No modulemap files found in {out_dir}"),
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* 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/. */
|
||||
|
||||
//! Helpers for data returned by cargo_metadata. Note that this doesn't
|
||||
//! execute cargo_metadata, just parses its output.
|
||||
|
||||
use anyhow::{bail, Context};
|
||||
use camino::Utf8PathBuf;
|
||||
use cargo_metadata::Metadata;
|
||||
use std::{collections::HashMap, fs};
|
||||
|
||||
use crate::BindgenCrateConfigSupplier;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct CrateConfigSupplier {
|
||||
paths: HashMap<String, Utf8PathBuf>,
|
||||
}
|
||||
|
||||
impl BindgenCrateConfigSupplier for CrateConfigSupplier {
|
||||
fn get_toml(&self, crate_name: &str) -> anyhow::Result<Option<toml::value::Table>> {
|
||||
let toml = self.paths.get(crate_name).map(|p| p.join("uniffi.toml"));
|
||||
crate::load_toml_file(toml.as_deref())
|
||||
}
|
||||
|
||||
fn get_udl(&self, crate_name: &str, udl_name: &str) -> anyhow::Result<String> {
|
||||
let path = self
|
||||
.paths
|
||||
.get(crate_name)
|
||||
.context(format!("No path known to UDL files for '{crate_name}'"))?
|
||||
.join("src")
|
||||
.join(format!("{udl_name}.udl"));
|
||||
if path.exists() {
|
||||
Ok(fs::read_to_string(path)?)
|
||||
} else {
|
||||
bail!(format!("No UDL file found at '{path}'"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Metadata> for CrateConfigSupplier {
|
||||
fn from(metadata: Metadata) -> Self {
|
||||
let paths: HashMap<String, Utf8PathBuf> = metadata
|
||||
.packages
|
||||
.iter()
|
||||
.flat_map(|p| {
|
||||
p.targets.iter().filter(|t| t.is_lib()).filter_map(|t| {
|
||||
p.manifest_path
|
||||
.parent()
|
||||
.map(|p| (t.name.replace('-', "_"), p.to_owned()))
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Self { paths }
|
||||
}
|
||||
}
|
|
@ -93,11 +93,11 @@ impl CallbackInterface {
|
|||
}
|
||||
|
||||
/// Vec of (ffi_callback, method) pairs
|
||||
pub fn vtable_methods(&self) -> Vec<(FfiCallbackFunction, &Method)> {
|
||||
pub fn vtable_methods(&self) -> Vec<(FfiCallbackFunction, Method)> {
|
||||
self.methods
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, method)| (method_ffi_callback(&self.name, method, i), method))
|
||||
.map(|(i, method)| (method_ffi_callback(&self.name, method, i), method.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
//! ```
|
||||
|
||||
use anyhow::Result;
|
||||
use uniffi_meta::Checksum;
|
||||
use uniffi_meta::{Checksum, EnumShape};
|
||||
|
||||
use super::record::Field;
|
||||
use super::{AsType, Literal, Type, TypeIterator};
|
||||
|
@ -176,24 +176,7 @@ pub struct Enum {
|
|||
pub(super) module_path: String,
|
||||
pub(super) discr_type: Option<Type>,
|
||||
pub(super) variants: Vec<Variant>,
|
||||
// NOTE: `flat` is a misleading name and to make matters worse, has 2 different
|
||||
// meanings depending on the context :(
|
||||
// * When used as part of Rust scaffolding generation, it means "is this enum
|
||||
// used with an Error, and that error should we lowered to foreign bindings
|
||||
// by converting each variant to a string and lowering the variant with that
|
||||
// string?". In that context, it should probably be called `lowered_as_string` or
|
||||
// similar.
|
||||
// * When used as part of bindings generation, it means "does this enum have only
|
||||
// variants with no associated data"? The foreign binding generators are likely
|
||||
// to generate significantly different versions of the enum based on that value.
|
||||
//
|
||||
// The reason it is described as "has 2 different meanings" by way of example:
|
||||
// * For an Enum described as being a flat error, but the enum itself has variants with data,
|
||||
// `flat` will be `true` for the Enum when generating scaffolding and `false` when
|
||||
// generating bindings.
|
||||
// * For an Enum not used as an error but which has no variants with data, `flat` will be
|
||||
// false when generating the scaffolding but `true` when generating bindings.
|
||||
pub(super) flat: bool,
|
||||
pub(super) shape: EnumShape,
|
||||
pub(super) non_exhaustive: bool,
|
||||
#[checksum_ignore]
|
||||
pub(super) docstring: Option<String>,
|
||||
|
@ -204,6 +187,10 @@ impl Enum {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, name: String) {
|
||||
self.name = name;
|
||||
}
|
||||
|
||||
pub fn variants(&self) -> &[Variant] {
|
||||
&self.variants
|
||||
}
|
||||
|
@ -248,7 +235,10 @@ impl Enum {
|
|||
}
|
||||
|
||||
pub fn is_flat(&self) -> bool {
|
||||
self.flat
|
||||
match self.shape {
|
||||
EnumShape::Error { flat } => flat,
|
||||
EnumShape::Enum => self.variants.iter().all(|v| v.fields.is_empty()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_non_exhaustive(&self) -> bool {
|
||||
|
@ -262,14 +252,12 @@ impl Enum {
|
|||
pub fn docstring(&self) -> Option<&str> {
|
||||
self.docstring.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
// Sadly can't use TryFrom due to the 'is_flat' complication.
|
||||
pub fn try_from_meta(meta: uniffi_meta::EnumMetadata, flat: bool) -> Result<Self> {
|
||||
// This is messy - error enums are considered "flat" if the user
|
||||
// opted in via a special attribute, regardless of whether the enum
|
||||
// is actually flat.
|
||||
// Real enums are considered flat iff they are actually flat.
|
||||
// We don't have that context here, so this is handled by our caller.
|
||||
impl TryFrom<uniffi_meta::EnumMetadata> for Enum {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(meta: uniffi_meta::EnumMetadata) -> Result<Self> {
|
||||
Ok(Self {
|
||||
name: meta.name,
|
||||
module_path: meta.module_path,
|
||||
|
@ -279,7 +267,7 @@ impl Enum {
|
|||
.into_iter()
|
||||
.map(TryInto::try_into)
|
||||
.collect::<Result<_>>()?,
|
||||
flat,
|
||||
shape: meta.shape,
|
||||
non_exhaustive: meta.non_exhaustive,
|
||||
docstring: meta.docstring.clone(),
|
||||
})
|
||||
|
@ -312,6 +300,10 @@ impl Variant {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn fields(&self) -> &[Field] {
|
||||
&self.fields
|
||||
}
|
||||
|
@ -414,6 +406,7 @@ mod test {
|
|||
// The enum with associated data.
|
||||
let ed = ci.get_enum_definition("TestEnumWithData").unwrap();
|
||||
assert!(!ed.is_flat());
|
||||
assert_eq!(ed.shape, EnumShape::Enum);
|
||||
assert_eq!(ed.variants().len(), 3);
|
||||
assert_eq!(
|
||||
ed.variants().iter().map(|v| v.name()).collect::<Vec<_>>(),
|
||||
|
@ -462,6 +455,8 @@ mod test {
|
|||
);
|
||||
assert_eq!(ewd.variants()[0].fields().len(), 0);
|
||||
assert_eq!(ewd.variants()[1].fields().len(), 0);
|
||||
assert!(ewd.is_flat());
|
||||
assert_eq!(ewd.shape, EnumShape::Enum);
|
||||
|
||||
// Flat enums pass over the FFI as bytebuffers.
|
||||
// (It might be nice to optimize these to pass as plain integers, but that's
|
||||
|
@ -669,7 +664,7 @@ mod test {
|
|||
name: "test".to_string(),
|
||||
discr_type: None,
|
||||
variants: vec![],
|
||||
flat: false,
|
||||
shape: EnumShape::Enum,
|
||||
non_exhaustive: false,
|
||||
docstring: None,
|
||||
};
|
||||
|
|
|
@ -43,7 +43,7 @@ pub enum FfiType {
|
|||
/// or pass it to someone that will.
|
||||
/// If the inner option is Some, it is the name of the external type. The bindings may need
|
||||
/// to use this name to import the correct RustBuffer for that type.
|
||||
RustBuffer(Option<String>),
|
||||
RustBuffer(Option<ExternalFfiMetadata>),
|
||||
/// 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,
|
||||
|
@ -144,13 +144,26 @@ impl From<&Type> for FfiType {
|
|||
Type::External {
|
||||
name,
|
||||
kind: ExternalKind::DataClass,
|
||||
module_path,
|
||||
namespace,
|
||||
..
|
||||
} => FfiType::RustBuffer(Some(name.clone())),
|
||||
} => FfiType::RustBuffer(Some(ExternalFfiMetadata {
|
||||
name: name.clone(),
|
||||
module_path: module_path.clone(),
|
||||
namespace: namespace.clone(),
|
||||
})),
|
||||
Type::Custom { builtin, .. } => FfiType::from(builtin.as_ref()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ExternalFfiMetadata {
|
||||
pub name: String,
|
||||
pub module_path: String,
|
||||
pub namespace: String,
|
||||
}
|
||||
|
||||
// Needed for rust scaffolding askama template
|
||||
impl From<Type> for FfiType {
|
||||
fn from(ty: Type) -> Self {
|
||||
|
@ -218,6 +231,10 @@ impl FfiFunction {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
/// Name of the FFI buffer version of this function that's generated when the
|
||||
/// `scaffolding-ffi-buffer-fns` feature is enabled.
|
||||
pub fn ffi_buffer_fn_name(&self) -> String {
|
||||
|
@ -293,6 +310,10 @@ impl FfiArgument {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn type_(&self) -> FfiType {
|
||||
self.type_.clone()
|
||||
}
|
||||
|
@ -315,6 +336,10 @@ impl FfiCallbackFunction {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn arguments(&self) -> Vec<&FfiArgument> {
|
||||
self.arguments.iter().collect()
|
||||
}
|
||||
|
@ -341,6 +366,10 @@ impl FfiStruct {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
/// Get the fields for this struct
|
||||
pub fn fields(&self) -> &[FfiField] {
|
||||
&self.fields
|
||||
|
@ -369,6 +398,10 @@ impl FfiField {
|
|||
pub fn type_(&self) -> FfiType {
|
||||
self.type_.clone()
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, name: String) {
|
||||
self.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FfiFunction> for FfiDefinition {
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
//! ```
|
||||
|
||||
use anyhow::Result;
|
||||
use uniffi_meta::Checksum;
|
||||
|
||||
use super::ffi::{FfiArgument, FfiFunction, FfiType};
|
||||
use super::{AsType, ComponentInterface, Literal, ObjectImpl, Type, TypeIterator};
|
||||
use uniffi_meta::Checksum;
|
||||
|
||||
/// Represents a standalone function.
|
||||
///
|
||||
|
@ -73,6 +73,12 @@ impl Function {
|
|||
&self.name
|
||||
}
|
||||
|
||||
// Note: Don't recalculate the checksum. In order to have consistent checksums,
|
||||
// we use the Rust names as input.
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn is_async(&self) -> bool {
|
||||
self.is_async
|
||||
}
|
||||
|
@ -194,6 +200,10 @@ impl Argument {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn by_ref(&self) -> bool {
|
||||
self.by_ref
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ use std::{
|
|||
use anyhow::{anyhow, bail, ensure, Result};
|
||||
|
||||
pub mod universe;
|
||||
pub use uniffi_meta::{AsType, ExternalKind, ObjectImpl, Type};
|
||||
pub use uniffi_meta::{AsType, EnumShape, ExternalKind, ObjectImpl, Type};
|
||||
use universe::{TypeIterator, TypeUniverse};
|
||||
|
||||
mod callbacks;
|
||||
|
@ -67,6 +67,7 @@ mod record;
|
|||
pub use record::{Field, Record};
|
||||
|
||||
pub mod ffi;
|
||||
mod visit_mut;
|
||||
pub use ffi::{
|
||||
FfiArgument, FfiCallbackFunction, FfiDefinition, FfiField, FfiFunction, FfiStruct, FfiType,
|
||||
};
|
||||
|
@ -79,7 +80,7 @@ pub type Literal = LiteralMetadata;
|
|||
|
||||
/// The main public interface for this module, representing the complete details of an interface exposed
|
||||
/// by a rust component and the details of consuming it via an extern-C FFI layer.
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ComponentInterface {
|
||||
/// All of the types used in the interface.
|
||||
// We can't checksum `self.types`, but its contents are implied by the other fields
|
||||
|
@ -164,6 +165,11 @@ impl ComponentInterface {
|
|||
self.types.namespace_docstring.as_deref()
|
||||
}
|
||||
|
||||
/// The crate this interfaces lives in.
|
||||
pub fn crate_name(&self) -> &str {
|
||||
&self.types.namespace.crate_name
|
||||
}
|
||||
|
||||
pub fn uniffi_contract_version(&self) -> u32 {
|
||||
// This is set by the scripts in the version-mismatch fixture
|
||||
let force_version = std::env::var("UNIFFI_FORCE_CONTRACT_VERSION");
|
||||
|
@ -810,6 +816,9 @@ impl ComponentInterface {
|
|||
pub(super) fn add_enum_definition(&mut self, defn: Enum) -> Result<()> {
|
||||
match self.enums.entry(defn.name().to_owned()) {
|
||||
Entry::Vacant(v) => {
|
||||
if matches!(defn.shape, EnumShape::Error { .. }) {
|
||||
self.errors.insert(defn.name.clone());
|
||||
}
|
||||
self.types.add_known_types(defn.iter_types())?;
|
||||
v.insert(defn);
|
||||
}
|
||||
|
@ -1174,7 +1183,7 @@ existing definition: Enum {
|
|||
docstring: None,
|
||||
},
|
||||
],
|
||||
flat: true,
|
||||
shape: Enum,
|
||||
non_exhaustive: false,
|
||||
docstring: None,
|
||||
},
|
||||
|
@ -1196,7 +1205,9 @@ new definition: Enum {
|
|||
docstring: None,
|
||||
},
|
||||
],
|
||||
flat: true,
|
||||
shape: Error {
|
||||
flat: true,
|
||||
},
|
||||
non_exhaustive: false,
|
||||
docstring: None,
|
||||
}",
|
||||
|
|
|
@ -116,6 +116,10 @@ impl Object {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
/// Returns the fully qualified name that should be used by Rust code for this object.
|
||||
/// Includes `r#`, traits get a leading `dyn`. If we ever supported associated types, then
|
||||
/// this would also include them.
|
||||
|
@ -266,14 +270,14 @@ impl Object {
|
|||
}
|
||||
|
||||
/// Vec of (ffi_callback_name, method) pairs
|
||||
pub fn vtable_methods(&self) -> Vec<(FfiCallbackFunction, &Method)> {
|
||||
pub fn vtable_methods(&self) -> Vec<(FfiCallbackFunction, Method)> {
|
||||
self.methods
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, method)| {
|
||||
(
|
||||
callbacks::method_ffi_callback(&self.name, method, i),
|
||||
method,
|
||||
method.clone(),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
|
@ -379,6 +383,10 @@ impl Constructor {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn arguments(&self) -> Vec<&Argument> {
|
||||
self.arguments.iter().collect()
|
||||
}
|
||||
|
@ -494,6 +502,10 @@ impl Method {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, new_name: String) {
|
||||
self.name = new_name;
|
||||
}
|
||||
|
||||
pub fn is_async(&self) -> bool {
|
||||
self.is_async
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ impl Record {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, name: String) {
|
||||
self.name = name;
|
||||
}
|
||||
|
||||
pub fn fields(&self) -> &[Field] {
|
||||
&self.fields
|
||||
}
|
||||
|
@ -127,6 +131,10 @@ impl Field {
|
|||
&self.name
|
||||
}
|
||||
|
||||
pub fn rename(&mut self, name: String) {
|
||||
self.name = name;
|
||||
}
|
||||
|
||||
pub fn default_value(&self) -> Option<&Literal> {
|
||||
self.default.as_ref()
|
||||
}
|
||||
|
|
|
@ -21,16 +21,16 @@ pub use uniffi_meta::{AsType, ExternalKind, NamespaceMetadata, ObjectImpl, Type,
|
|||
/// You could imagine this struct doing some clever interning of names and so-on in future,
|
||||
/// to reduce the overhead of passing around [Type] instances. For now we just do a whole
|
||||
/// lot of cloning.
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub(crate) struct TypeUniverse {
|
||||
/// The unique prefixes that we'll use for namespacing when exposing this component's API.
|
||||
pub namespace: NamespaceMetadata,
|
||||
pub namespace_docstring: Option<String>,
|
||||
|
||||
// Named type definitions (including aliases).
|
||||
type_definitions: HashMap<String, Type>,
|
||||
pub(super) type_definitions: HashMap<String, Type>,
|
||||
// All the types in the universe, by canonical type name, in a well-defined order.
|
||||
all_known_types: BTreeSet<Type>,
|
||||
pub(super) all_known_types: BTreeSet<Type>,
|
||||
}
|
||||
|
||||
impl TypeUniverse {
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
use crate::interface::{Enum, FfiDefinition, Record};
|
||||
use crate::{ComponentInterface, VisitMut};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use uniffi_meta::Type;
|
||||
|
||||
impl ComponentInterface {
|
||||
/// A generic interface for mutating items in the [`ComponentInterface`].
|
||||
///
|
||||
/// Walk down the [`ComponentInterface`] and adjust the names of each type
|
||||
/// based on the naming conventions of the supported languages.
|
||||
///
|
||||
/// Each suppoerted language implements the [`VisitMut`] Trait and is able
|
||||
/// to alter the functions, enums etc. to its own naming conventions.
|
||||
pub fn visit_mut<V: VisitMut>(&mut self, visitor: &V) {
|
||||
for type_ in self.types.type_definitions.values_mut() {
|
||||
visitor.visit_type(type_);
|
||||
}
|
||||
|
||||
let mut all_known_types_altered: BTreeSet<Type> = BTreeSet::new();
|
||||
|
||||
for type_ in self.types.all_known_types.iter() {
|
||||
let mut type_altered = type_.clone();
|
||||
visitor.visit_type(&mut type_altered);
|
||||
all_known_types_altered.insert(type_altered);
|
||||
}
|
||||
|
||||
self.types.all_known_types = all_known_types_altered;
|
||||
|
||||
let mut updated_enums: BTreeMap<String, Enum> = BTreeMap::new();
|
||||
let errors_clone = self.errors.clone();
|
||||
for (enum_name, enum_item) in self.enums.iter_mut() {
|
||||
let updated_key = visitor.visit_enum_key(&mut enum_name.clone());
|
||||
let is_error = errors_clone.contains(enum_item.name());
|
||||
|
||||
visitor.visit_enum(is_error, enum_item);
|
||||
|
||||
for variant in enum_item.variants.iter_mut() {
|
||||
visitor.visit_variant(is_error, variant);
|
||||
|
||||
for field in variant.fields.iter_mut() {
|
||||
visitor.visit_field(field);
|
||||
visitor.visit_type(&mut field.type_);
|
||||
}
|
||||
}
|
||||
updated_enums.insert(updated_key, enum_item.clone());
|
||||
}
|
||||
self.enums = updated_enums;
|
||||
|
||||
for record_item in self.records.values_mut() {
|
||||
visitor.visit_record(record_item);
|
||||
|
||||
for field in &mut record_item.fields {
|
||||
visitor.visit_field(field);
|
||||
visitor.visit_type(&mut field.type_);
|
||||
}
|
||||
}
|
||||
self.fix_record_keys_after_rename();
|
||||
|
||||
for function in self.functions.iter_mut() {
|
||||
visitor.visit_function(function);
|
||||
|
||||
if function.clone().return_type.is_some() {
|
||||
let mut return_type = function.clone().return_type.unwrap();
|
||||
visitor.visit_type(&mut return_type);
|
||||
function.return_type = Some(return_type);
|
||||
}
|
||||
|
||||
for argument in function.arguments.iter_mut() {
|
||||
visitor.visit_argument(argument);
|
||||
visitor.visit_type(&mut argument.type_);
|
||||
}
|
||||
}
|
||||
|
||||
for object in self.objects.iter_mut() {
|
||||
visitor.visit_object(object);
|
||||
|
||||
for method in object.methods.iter_mut() {
|
||||
visitor.visit_method(method);
|
||||
|
||||
for argument in method.arguments.iter_mut() {
|
||||
visitor.visit_argument(argument);
|
||||
visitor.visit_type(&mut argument.type_);
|
||||
}
|
||||
|
||||
if method.clone().return_type.is_some() {
|
||||
let mut return_type = method.clone().return_type.unwrap();
|
||||
visitor.visit_type(&mut return_type);
|
||||
method.return_type = Some(return_type);
|
||||
}
|
||||
}
|
||||
|
||||
for constructor in object.constructors.iter_mut() {
|
||||
visitor.visit_constructor(constructor);
|
||||
|
||||
for argument in constructor.arguments.iter_mut() {
|
||||
visitor.visit_argument(argument);
|
||||
visitor.visit_type(&mut argument.type_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for callback_interface in self.callback_interfaces.iter_mut() {
|
||||
for method in callback_interface.methods.iter_mut() {
|
||||
visitor.visit_method(method);
|
||||
|
||||
for argument in method.arguments.iter_mut() {
|
||||
visitor.visit_argument(argument);
|
||||
visitor.visit_type(&mut argument.type_);
|
||||
}
|
||||
}
|
||||
|
||||
for ffi_arg in callback_interface.ffi_init_callback.arguments.iter_mut() {
|
||||
visitor.visit_ffi_argument(ffi_arg);
|
||||
}
|
||||
}
|
||||
|
||||
let mut throw_types_altered: BTreeSet<Type> = BTreeSet::new();
|
||||
|
||||
for throw_type in self.callback_interface_throws_types.iter() {
|
||||
let mut type_ = throw_type.clone();
|
||||
visitor.visit_type(&mut type_);
|
||||
throw_types_altered.insert(type_);
|
||||
}
|
||||
|
||||
self.callback_interface_throws_types = throw_types_altered;
|
||||
|
||||
for ffi_definition in self.ffi_definitions() {
|
||||
if let FfiDefinition::Struct(mut ffi_struct) = ffi_definition {
|
||||
for field in ffi_struct.fields.iter_mut() {
|
||||
visitor.visit_ffi_field(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fix_record_keys_after_rename(&mut self) {
|
||||
let mut new_records: BTreeMap<String, Record> = BTreeMap::new();
|
||||
|
||||
for record in self.records.values() {
|
||||
new_records.insert(record.name().to_string(), record.clone());
|
||||
}
|
||||
|
||||
self.records = new_records;
|
||||
}
|
||||
}
|
|
@ -95,10 +95,10 @@
|
|||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use fs_err::{self as fs, File};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
use std::io::prelude::*;
|
||||
use std::io::ErrorKind;
|
||||
use std::{collections::HashMap, process::Command};
|
||||
use std::process::Command;
|
||||
|
||||
pub mod backend;
|
||||
pub mod bindings;
|
||||
|
@ -107,38 +107,28 @@ pub mod library_mode;
|
|||
pub mod macro_metadata;
|
||||
pub mod scaffolding;
|
||||
|
||||
use bindings::TargetLanguage;
|
||||
#[cfg(feature = "cargo-metadata")]
|
||||
pub mod cargo_metadata;
|
||||
|
||||
use crate::interface::{
|
||||
Argument, Constructor, Enum, FfiArgument, FfiField, Field, Function, Method, Object, Record,
|
||||
Variant,
|
||||
};
|
||||
pub use interface::ComponentInterface;
|
||||
pub use library_mode::find_components;
|
||||
use scaffolding::RustScaffolding;
|
||||
use uniffi_meta::Type;
|
||||
|
||||
/// Trait for bindings configuration. Each bindings language defines one of these.
|
||||
///
|
||||
/// BindingsConfigs are initially loaded from `uniffi.toml` file. Then the trait methods are used
|
||||
/// to fill in missing values.
|
||||
pub trait BindingsConfig: DeserializeOwned {
|
||||
/// Update missing values using the `ComponentInterface`
|
||||
fn update_from_ci(&mut self, ci: &ComponentInterface);
|
||||
|
||||
/// Update missing values using the dylib file for the main crate, when in library mode.
|
||||
///
|
||||
/// cdylib_name will be the library filename without the leading `lib` and trailing extension
|
||||
fn update_from_cdylib_name(&mut self, cdylib_name: &str);
|
||||
|
||||
/// Update missing values from config instances from dependent crates
|
||||
///
|
||||
/// config_map maps crate names to config instances. This is mostly used to set up external
|
||||
/// types.
|
||||
fn update_from_dependency_configs(&mut self, config_map: HashMap<&str, &Self>);
|
||||
}
|
||||
|
||||
/// Binding generator config with no members
|
||||
#[derive(Clone, Debug, Deserialize, Hash, PartialEq, PartialOrd, Ord, Eq)]
|
||||
pub struct EmptyBindingsConfig;
|
||||
|
||||
impl BindingsConfig for EmptyBindingsConfig {
|
||||
fn update_from_ci(&mut self, _ci: &ComponentInterface) {}
|
||||
fn update_from_cdylib_name(&mut self, _cdylib_name: &str) {}
|
||||
fn update_from_dependency_configs(&mut self, _config_map: HashMap<&str, &Self>) {}
|
||||
/// The options used when creating bindings. Named such
|
||||
/// it doesn't cause confusion that it's settings specific to
|
||||
/// the generator itself.
|
||||
// TODO: We should try and move the public interface of the module to
|
||||
// this struct. For now, only the BindingGenerator uses it.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct GenerationSettings {
|
||||
pub out_dir: Utf8PathBuf,
|
||||
pub try_format_code: bool,
|
||||
pub cdylib: Option<String>,
|
||||
}
|
||||
|
||||
/// A trait representing a UniFFI Binding Generator
|
||||
|
@ -147,61 +137,127 @@ impl BindingsConfig for EmptyBindingsConfig {
|
|||
/// and call the [`generate_external_bindings`] using a type that implements this trait.
|
||||
pub trait BindingGenerator: Sized {
|
||||
/// Handles configuring the bindings
|
||||
type Config: BindingsConfig;
|
||||
type Config;
|
||||
|
||||
/// Creates a new config.
|
||||
fn new_config(&self, root_toml: &toml::Value) -> Result<Self::Config>;
|
||||
|
||||
/// Update the various config items in preparation to write one or more of them.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `cdylib`: The name of the cdylib file, if known.
|
||||
/// - `library_path`: The name of library used to extract the symbols.
|
||||
/// - `components`: A mutable array of [`Component`]s to be updated.
|
||||
fn update_component_configs(
|
||||
&self,
|
||||
settings: &GenerationSettings,
|
||||
components: &mut Vec<Component<Self::Config>>,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Writes the bindings to the output directory
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `ci`: A [`ComponentInterface`] representing the interface
|
||||
/// - `config`: An instance of the [`BindingsConfig`] associated with this type
|
||||
/// - `components`: An array of [`Component`]s representing the items to be generated.
|
||||
/// - `out_dir`: The path to where the binding generator should write the output bindings
|
||||
fn write_bindings(
|
||||
&self,
|
||||
ci: &ComponentInterface,
|
||||
config: &Self::Config,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
settings: &GenerationSettings,
|
||||
components: &[Component<Self::Config>],
|
||||
) -> Result<()>;
|
||||
|
||||
/// Check if `library_path` used by library mode is valid for this generator
|
||||
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct BindingGeneratorDefault {
|
||||
pub target_languages: Vec<TargetLanguage>,
|
||||
pub try_format_code: bool,
|
||||
/// A trait to alter language specific type representations.
|
||||
///
|
||||
/// It is meant to be implemented by each language oracle. It takes a
|
||||
/// ['ComponentInterface'] and uses its own specific language adjustment
|
||||
/// functions to be able to generate language specific templates.
|
||||
pub trait VisitMut {
|
||||
/// Go through each `Record` of a [`ComponentInterface`] and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_record(&self, record: &mut Record);
|
||||
|
||||
/// Change the name of an `Object` of a [`ComponentInterface`
|
||||
/// to language specific naming conventions.
|
||||
fn visit_object(&self, object: &mut Object);
|
||||
|
||||
/// Change the name of a `Field` of an `Enum` `Variant`
|
||||
/// to language specific naming conventions.
|
||||
fn visit_field(&self, field: &mut Field);
|
||||
|
||||
/// Change the name of a `FfiField` inside a `FfiStruct`
|
||||
/// to language specific naming conventions.
|
||||
fn visit_ffi_field(&self, ffi_field: &mut FfiField);
|
||||
|
||||
/// Change the `Arugment` of a `FfiFunction` in the [`ComponentInterface`]
|
||||
/// to language specific naming conventions.
|
||||
fn visit_ffi_argument(&self, ffi_argument: &mut FfiArgument);
|
||||
|
||||
/// Go through each `Enum` of a [`ComponentInterface`] and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_enum(&self, is_error: bool, enum_: &mut Enum);
|
||||
|
||||
/// Change the naming of the key in the [`ComponentInterface`]
|
||||
/// `BTreeMap` where all `Enum`s are stored to reflect the changed
|
||||
/// name of an `Enum`.
|
||||
fn visit_enum_key(&self, key: &mut String) -> String;
|
||||
|
||||
/// Go through each `Variant` of an `Enum` and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_variant(&self, is_error: bool, variant: &mut Variant);
|
||||
|
||||
/// Go through each `Type` in the `TypeUniverse` of
|
||||
/// a [`ComponentInterface`] and adjust it to language specific
|
||||
/// naming conventions.
|
||||
fn visit_type(&self, type_: &mut Type);
|
||||
|
||||
/// Go through each `Method` of an `Object` and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_method(&self, method: &mut Method);
|
||||
|
||||
/// Go through each `Argument` of a `Function` and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_argument(&self, argument: &mut Argument);
|
||||
|
||||
/// Go through each `Constructor` of a [`ComponentInterface`] and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_constructor(&self, constructor: &mut Constructor);
|
||||
|
||||
/// Go through each `Function` of a [`ComponentInterface`] and
|
||||
/// adjust it to language specific naming conventions.
|
||||
fn visit_function(&self, function: &mut Function);
|
||||
}
|
||||
|
||||
impl BindingGenerator for BindingGeneratorDefault {
|
||||
type Config = Config;
|
||||
/// Everything needed to generate a ComponentInterface.
|
||||
#[derive(Debug)]
|
||||
pub struct Component<Config> {
|
||||
pub ci: ComponentInterface,
|
||||
pub config: Config,
|
||||
}
|
||||
|
||||
fn write_bindings(
|
||||
&self,
|
||||
ci: &ComponentInterface,
|
||||
config: &Self::Config,
|
||||
out_dir: &Utf8Path,
|
||||
_try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
for &language in &self.target_languages {
|
||||
bindings::write_bindings(
|
||||
&config.bindings,
|
||||
ci,
|
||||
out_dir,
|
||||
language,
|
||||
self.try_format_code,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
/// A trait used by the bindgen to obtain config information about a source crate
|
||||
/// which was found in the metadata for the library.
|
||||
///
|
||||
/// This is an abstraction around needing the source directory for a crate.
|
||||
/// In most cases `cargo_metadata` can be used, but this should be able to work in
|
||||
/// more environments.
|
||||
pub trait BindgenCrateConfigSupplier {
|
||||
/// Get the toml for the crate. Probably came from uniffi.toml in the root of the crate source.
|
||||
fn get_toml(&self, _crate_name: &str) -> Result<Option<toml::value::Table>> {
|
||||
Ok(None)
|
||||
}
|
||||
/// Obtains the contents of the named UDL file which was referenced by the type metadata.
|
||||
fn get_udl(&self, crate_name: &str, udl_name: &str) -> Result<String> {
|
||||
bail!("Crate {crate_name} has no UDL {udl_name}")
|
||||
}
|
||||
}
|
||||
|
||||
fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
|
||||
for &language in &self.target_languages {
|
||||
if cdylib_name.is_none() && language != TargetLanguage::Swift {
|
||||
bail!("Generate bindings for {language} requires a cdylib, but {library_path} was given");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub struct EmptyCrateConfigSupplier;
|
||||
impl BindgenCrateConfigSupplier for EmptyCrateConfigSupplier {}
|
||||
|
||||
/// A convenience function for the CLI to help avoid using static libs
|
||||
/// in places cdylibs are required.
|
||||
pub fn is_cdylib(library_file: impl AsRef<Utf8Path>) -> bool {
|
||||
crate::library_mode::calc_cdylib_name(library_file.as_ref()).is_some()
|
||||
}
|
||||
|
||||
/// Generate bindings for an external binding generator
|
||||
|
@ -210,7 +266,6 @@ impl BindingGenerator for BindingGeneratorDefault {
|
|||
/// Implements an entry point for external binding generators.
|
||||
/// The function does the following:
|
||||
/// - It parses the `udl` in a [`ComponentInterface`]
|
||||
/// - Parses the `uniffi.toml` and loads it into the type that implements [`BindingsConfig`]
|
||||
/// - Creates an instance of [`BindingGenerator`], based on type argument `B`, and run [`BindingGenerator::write_bindings`] on it
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -232,31 +287,39 @@ pub fn generate_external_bindings<T: BindingGenerator>(
|
|||
let crate_name = crate_name
|
||||
.map(|c| Ok(c.to_string()))
|
||||
.unwrap_or_else(|| crate_name_from_cargo_toml(udl_file.as_ref()))?;
|
||||
let mut component = parse_udl(udl_file.as_ref(), &crate_name)?;
|
||||
let mut ci = parse_udl(udl_file.as_ref(), &crate_name)?;
|
||||
if let Some(ref library_file) = library_file {
|
||||
macro_metadata::add_to_ci_from_library(&mut component, library_file.as_ref())?;
|
||||
macro_metadata::add_to_ci_from_library(&mut ci, library_file.as_ref())?;
|
||||
}
|
||||
let crate_root = &guess_crate_root(udl_file.as_ref()).context("Failed to guess crate root")?;
|
||||
|
||||
let config_file_override = config_file_override.as_ref().map(|p| p.as_ref());
|
||||
|
||||
let config = {
|
||||
let mut config = load_initial_config::<T::Config>(crate_root, config_file_override)?;
|
||||
config.update_from_ci(&component);
|
||||
if let Some(ref library_file) = library_file {
|
||||
if let Some(cdylib_name) = crate::library_mode::calc_cdylib_name(library_file.as_ref())
|
||||
{
|
||||
config.update_from_cdylib_name(cdylib_name)
|
||||
}
|
||||
};
|
||||
config
|
||||
let crate_config = load_toml_file(Some(&crate_root.join("uniffi.toml")))
|
||||
.context("failed to load {crate_root}/uniffi.toml")?;
|
||||
let toml_value =
|
||||
overridden_config_value(crate_config.unwrap_or_default(), config_file_override)?;
|
||||
binding_generator.new_config(&toml_value)?
|
||||
};
|
||||
|
||||
let out_dir = get_out_dir(
|
||||
udl_file.as_ref(),
|
||||
out_dir_override.as_ref().map(|p| p.as_ref()),
|
||||
)?;
|
||||
binding_generator.write_bindings(&component, &config, &out_dir, try_format_code)
|
||||
let settings = GenerationSettings {
|
||||
cdylib: match library_file {
|
||||
Some(ref library_file) => {
|
||||
crate::library_mode::calc_cdylib_name(library_file.as_ref()).map(ToOwned::to_owned)
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
out_dir: get_out_dir(
|
||||
udl_file.as_ref(),
|
||||
out_dir_override.as_ref().map(|p| p.as_ref()),
|
||||
)?,
|
||||
try_format_code,
|
||||
};
|
||||
|
||||
let mut components = vec![Component { ci, config }];
|
||||
binding_generator.update_component_configs(&settings, &mut components)?;
|
||||
binding_generator.write_bindings(&settings, &components)
|
||||
}
|
||||
|
||||
// Generate the infrastructural Rust code for implementing the UDL interface,
|
||||
|
@ -435,20 +498,15 @@ fn load_toml_file(source: Option<&Utf8Path>) -> Result<Option<toml::value::Table
|
|||
}
|
||||
|
||||
/// Load the default `uniffi.toml` config, merge TOML trees with `config_file_override` if specified.
|
||||
fn load_initial_config<Config: DeserializeOwned>(
|
||||
crate_root: &Utf8Path,
|
||||
fn overridden_config_value(
|
||||
mut config: toml::value::Table,
|
||||
config_file_override: Option<&Utf8Path>,
|
||||
) -> Result<Config> {
|
||||
let mut config = load_toml_file(Some(crate_root.join("uniffi.toml").as_path()))
|
||||
.context("default config")?
|
||||
.unwrap_or(toml::value::Table::default());
|
||||
|
||||
) -> Result<toml::Value> {
|
||||
let override_config = load_toml_file(config_file_override).context("override config")?;
|
||||
if let Some(override_config) = override_config {
|
||||
merge_toml(&mut config, override_config);
|
||||
}
|
||||
|
||||
Ok(toml::Value::from(config).try_into()?)
|
||||
Ok(toml::Value::from(config))
|
||||
}
|
||||
|
||||
fn merge_toml(a: &mut toml::value::Table, b: toml::value::Table) {
|
||||
|
@ -467,55 +525,6 @@ fn merge_toml(a: &mut toml::value::Table, b: toml::value::Table) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
#[serde(default)]
|
||||
bindings: bindings::Config,
|
||||
}
|
||||
|
||||
impl BindingsConfig for Config {
|
||||
fn update_from_ci(&mut self, ci: &ComponentInterface) {
|
||||
self.bindings.kotlin.update_from_ci(ci);
|
||||
self.bindings.swift.update_from_ci(ci);
|
||||
self.bindings.python.update_from_ci(ci);
|
||||
self.bindings.ruby.update_from_ci(ci);
|
||||
}
|
||||
|
||||
fn update_from_cdylib_name(&mut self, cdylib_name: &str) {
|
||||
self.bindings.kotlin.update_from_cdylib_name(cdylib_name);
|
||||
self.bindings.swift.update_from_cdylib_name(cdylib_name);
|
||||
self.bindings.python.update_from_cdylib_name(cdylib_name);
|
||||
self.bindings.ruby.update_from_cdylib_name(cdylib_name);
|
||||
}
|
||||
|
||||
fn update_from_dependency_configs(&mut self, config_map: HashMap<&str, &Self>) {
|
||||
self.bindings.kotlin.update_from_dependency_configs(
|
||||
config_map
|
||||
.iter()
|
||||
.map(|(key, config)| (*key, &config.bindings.kotlin))
|
||||
.collect(),
|
||||
);
|
||||
self.bindings.swift.update_from_dependency_configs(
|
||||
config_map
|
||||
.iter()
|
||||
.map(|(key, config)| (*key, &config.bindings.swift))
|
||||
.collect(),
|
||||
);
|
||||
self.bindings.python.update_from_dependency_configs(
|
||||
config_map
|
||||
.iter()
|
||||
.map(|(key, config)| (*key, &config.bindings.python))
|
||||
.collect(),
|
||||
);
|
||||
self.bindings.ruby.update_from_dependency_configs(
|
||||
config_map
|
||||
.iter()
|
||||
.map(|(key, config)| (*key, &config.bindings.ruby))
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(HACK):
|
||||
// Include the askama config file into the build.
|
||||
// That way cargo tracks the file and other tools relying on file tracking see it as well.
|
||||
|
|
|
@ -16,111 +16,65 @@
|
|||
/// - UniFFI can figure out the package/module names for each crate, eliminating the external
|
||||
/// package maps.
|
||||
use crate::{
|
||||
load_initial_config, macro_metadata, BindingGenerator, BindingsConfig, ComponentInterface,
|
||||
Result,
|
||||
macro_metadata, overridden_config_value, BindgenCrateConfigSupplier, BindingGenerator,
|
||||
Component, ComponentInterface, GenerationSettings, Result,
|
||||
};
|
||||
use anyhow::{bail, Context};
|
||||
use anyhow::bail;
|
||||
use camino::Utf8Path;
|
||||
use cargo_metadata::{MetadataCommand, Package};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fs,
|
||||
};
|
||||
use std::{collections::HashMap, fs};
|
||||
use toml::value::Table as TomlTable;
|
||||
use uniffi_meta::{
|
||||
create_metadata_groups, fixup_external_type, group_metadata, Metadata, MetadataGroup,
|
||||
};
|
||||
|
||||
/// Generate foreign bindings
|
||||
///
|
||||
/// This replicates the current process used for generating the builtin bindings.
|
||||
/// External bindings authors should consider using [find_components], which provides a simpler
|
||||
/// interface and allows for more flexibility in how the external bindings are generated.
|
||||
///
|
||||
/// Returns the list of sources used to generate the bindings, in no particular order.
|
||||
pub fn generate_bindings<T: BindingGenerator + ?Sized>(
|
||||
library_path: &Utf8Path,
|
||||
crate_name: Option<String>,
|
||||
binding_generator: &T,
|
||||
config_supplier: &dyn BindgenCrateConfigSupplier,
|
||||
config_file_override: Option<&Utf8Path>,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<Vec<Source<T::Config>>> {
|
||||
generate_external_bindings(
|
||||
binding_generator,
|
||||
library_path,
|
||||
crate_name.clone(),
|
||||
config_file_override,
|
||||
out_dir,
|
||||
) -> Result<Vec<Component<T::Config>>> {
|
||||
let mut components = find_components(library_path, config_supplier)?
|
||||
.into_iter()
|
||||
.map(|Component { ci, config }| {
|
||||
let toml_value = overridden_config_value(config, config_file_override)?;
|
||||
let config = binding_generator.new_config(&toml_value)?;
|
||||
Ok(Component { ci, config })
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let settings = GenerationSettings {
|
||||
out_dir: out_dir.to_owned(),
|
||||
try_format_code,
|
||||
)
|
||||
}
|
||||
cdylib: calc_cdylib_name(library_path).map(ToOwned::to_owned),
|
||||
};
|
||||
binding_generator.update_component_configs(&settings, &mut components)?;
|
||||
|
||||
/// Generate foreign bindings
|
||||
///
|
||||
/// Returns the list of sources used to generate the bindings, in no particular order.
|
||||
pub fn generate_external_bindings<T: BindingGenerator>(
|
||||
binding_generator: &T,
|
||||
library_path: &Utf8Path,
|
||||
crate_name: Option<String>,
|
||||
config_file_override: Option<&Utf8Path>,
|
||||
out_dir: &Utf8Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<Vec<Source<T::Config>>> {
|
||||
let cargo_metadata = MetadataCommand::new()
|
||||
.exec()
|
||||
.context("error running cargo metadata")?;
|
||||
let cdylib_name = calc_cdylib_name(library_path);
|
||||
binding_generator.check_library_path(library_path, cdylib_name)?;
|
||||
|
||||
let mut sources = find_sources(
|
||||
&cargo_metadata,
|
||||
library_path,
|
||||
cdylib_name,
|
||||
config_file_override,
|
||||
)?;
|
||||
for i in 0..sources.len() {
|
||||
// Partition up the sources list because we're eventually going to call
|
||||
// `update_from_dependency_configs()` which requires an exclusive reference to one source and
|
||||
// shared references to all other sources.
|
||||
let (sources_before, rest) = sources.split_at_mut(i);
|
||||
let (source, sources_after) = rest.split_first_mut().unwrap();
|
||||
let other_sources = sources_before.iter().chain(sources_after.iter());
|
||||
// Calculate which configs come from dependent crates
|
||||
let dependencies =
|
||||
HashSet::<&str>::from_iter(source.package.dependencies.iter().map(|d| d.name.as_str()));
|
||||
let config_map: HashMap<&str, &T::Config> = other_sources
|
||||
.filter_map(|s| {
|
||||
dependencies
|
||||
.contains(s.package.name.as_str())
|
||||
.then_some((s.crate_name.as_str(), &s.config))
|
||||
})
|
||||
.collect();
|
||||
// We can finally call update_from_dependency_configs
|
||||
source.config.update_from_dependency_configs(config_map);
|
||||
}
|
||||
fs::create_dir_all(out_dir)?;
|
||||
if let Some(crate_name) = &crate_name {
|
||||
let old_elements = sources.drain(..);
|
||||
let old_elements = components.drain(..);
|
||||
let mut matches: Vec<_> = old_elements
|
||||
.filter(|s| &s.crate_name == crate_name)
|
||||
.filter(|s| s.ci.crate_name() == crate_name)
|
||||
.collect();
|
||||
match matches.len() {
|
||||
0 => bail!("Crate {crate_name} not found in {library_path}"),
|
||||
1 => sources.push(matches.pop().unwrap()),
|
||||
1 => components.push(matches.pop().unwrap()),
|
||||
n => bail!("{n} crates named {crate_name} found in {library_path}"),
|
||||
}
|
||||
}
|
||||
|
||||
for source in sources.iter() {
|
||||
binding_generator.write_bindings(&source.ci, &source.config, out_dir, try_format_code)?;
|
||||
}
|
||||
binding_generator.write_bindings(&settings, &components)?;
|
||||
|
||||
Ok(sources)
|
||||
}
|
||||
|
||||
// A single source that we generate bindings for
|
||||
#[derive(Debug)]
|
||||
pub struct Source<Config: BindingsConfig> {
|
||||
pub package: Package,
|
||||
pub crate_name: String,
|
||||
pub ci: ComponentInterface,
|
||||
pub config: Config,
|
||||
Ok(components)
|
||||
}
|
||||
|
||||
// If `library_path` is a C dynamic library, return its name
|
||||
|
@ -136,12 +90,17 @@ pub fn calc_cdylib_name(library_path: &Utf8Path) -> Option<&str> {
|
|||
None
|
||||
}
|
||||
|
||||
fn find_sources<Config: BindingsConfig>(
|
||||
cargo_metadata: &cargo_metadata::Metadata,
|
||||
/// Find UniFFI components from a shared library file
|
||||
///
|
||||
/// This method inspects the library file and creates [ComponentInterface] instances for each
|
||||
/// component used to build it. It parses the UDL files from `uniffi::include_scaffolding!` macro
|
||||
/// calls.
|
||||
///
|
||||
/// `config_supplier` is used to find UDL files on disk and load config data.
|
||||
pub fn find_components(
|
||||
library_path: &Utf8Path,
|
||||
cdylib_name: Option<&str>,
|
||||
config_file_override: Option<&Utf8Path>,
|
||||
) -> Result<Vec<Source<Config>>> {
|
||||
config_supplier: &dyn BindgenCrateConfigSupplier,
|
||||
) -> Result<Vec<Component<TomlTable>>> {
|
||||
let items = macro_metadata::extract_from_library(library_path)?;
|
||||
let mut metadata_groups = create_metadata_groups(&items);
|
||||
group_metadata(&mut metadata_groups, items)?;
|
||||
|
@ -151,13 +110,8 @@ fn find_sources<Config: BindingsConfig>(
|
|||
let mut udl_items: HashMap<String, MetadataGroup> = HashMap::new();
|
||||
|
||||
for group in metadata_groups.values() {
|
||||
let package = find_package_by_crate_name(cargo_metadata, &group.namespace.crate_name)?;
|
||||
let crate_root = package
|
||||
.manifest_path
|
||||
.parent()
|
||||
.context("manifest path has no parent")?;
|
||||
let crate_name = group.namespace.crate_name.clone();
|
||||
if let Some(mut metadata_group) = load_udl_metadata(group, crate_root, &crate_name)? {
|
||||
if let Some(mut metadata_group) = load_udl_metadata(group, &crate_name, config_supplier)? {
|
||||
// fixup the items.
|
||||
metadata_group.items = metadata_group
|
||||
.items
|
||||
|
@ -175,55 +129,24 @@ fn find_sources<Config: BindingsConfig>(
|
|||
metadata_groups
|
||||
.into_values()
|
||||
.map(|group| {
|
||||
let package = find_package_by_crate_name(cargo_metadata, &group.namespace.crate_name)?;
|
||||
let crate_root = package
|
||||
.manifest_path
|
||||
.parent()
|
||||
.context("manifest path has no parent")?;
|
||||
let crate_name = group.namespace.crate_name.clone();
|
||||
let mut ci = ComponentInterface::new(&crate_name);
|
||||
if let Some(metadata) = udl_items.remove(&crate_name) {
|
||||
let crate_name = &group.namespace.crate_name;
|
||||
let mut ci = ComponentInterface::new(crate_name);
|
||||
if let Some(metadata) = udl_items.remove(crate_name) {
|
||||
ci.add_metadata(metadata)?;
|
||||
};
|
||||
ci.add_metadata(group)?;
|
||||
let mut config = load_initial_config::<Config>(crate_root, config_file_override)?;
|
||||
if let Some(cdylib_name) = cdylib_name {
|
||||
config.update_from_cdylib_name(cdylib_name);
|
||||
}
|
||||
config.update_from_ci(&ci);
|
||||
Ok(Source {
|
||||
config,
|
||||
crate_name,
|
||||
ci,
|
||||
package,
|
||||
})
|
||||
let config = config_supplier
|
||||
.get_toml(ci.crate_name())?
|
||||
.unwrap_or_default();
|
||||
Ok(Component { ci, config })
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_package_by_crate_name(
|
||||
metadata: &cargo_metadata::Metadata,
|
||||
crate_name: &str,
|
||||
) -> Result<Package> {
|
||||
let matching: Vec<&Package> = metadata
|
||||
.packages
|
||||
.iter()
|
||||
.filter(|p| {
|
||||
p.targets
|
||||
.iter()
|
||||
.any(|t| t.name.replace('-', "_") == crate_name)
|
||||
})
|
||||
.collect();
|
||||
match matching.len() {
|
||||
1 => Ok(matching[0].clone()),
|
||||
n => bail!("cargo metadata returned {n} packages for crate name {crate_name}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_udl_metadata(
|
||||
group: &MetadataGroup,
|
||||
crate_root: &Utf8Path,
|
||||
crate_name: &str,
|
||||
config_supplier: &dyn BindgenCrateConfigSupplier,
|
||||
) -> Result<Option<MetadataGroup>> {
|
||||
let udl_items = group
|
||||
.items
|
||||
|
@ -233,10 +156,9 @@ fn load_udl_metadata(
|
|||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// We only support 1 UDL file per crate, for no good reason!
|
||||
match udl_items.len() {
|
||||
// No UDL files, load directly from the group
|
||||
0 => Ok(None),
|
||||
// Found a UDL file, use it to load the CI, then add the MetadataGroup
|
||||
1 => {
|
||||
if udl_items[0].module_path != crate_name {
|
||||
bail!(
|
||||
|
@ -245,17 +167,11 @@ fn load_udl_metadata(
|
|||
crate_name
|
||||
);
|
||||
}
|
||||
let ci_name = &udl_items[0].file_stub;
|
||||
let ci_path = crate_root.join("src").join(format!("{ci_name}.udl"));
|
||||
if ci_path.exists() {
|
||||
let udl = fs::read_to_string(ci_path)?;
|
||||
let udl_group = uniffi_udl::parse_udl(&udl, crate_name)?;
|
||||
Ok(Some(udl_group))
|
||||
} else {
|
||||
bail!("{ci_path} not found");
|
||||
}
|
||||
let udl = config_supplier.get_udl(crate_name, &udl_items[0].file_stub)?;
|
||||
let udl_group = uniffi_udl::parse_udl(&udl, crate_name)?;
|
||||
Ok(Some(udl_group))
|
||||
}
|
||||
n => bail!("{n} UDL files found for {crate_root}"),
|
||||
n => bail!("{n} UDL files found for {crate_name}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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 crate::interface::{CallbackInterface, ComponentInterface, Enum, Record, Type};
|
||||
use crate::interface::{CallbackInterface, ComponentInterface, Record, Type};
|
||||
use anyhow::{bail, Context};
|
||||
use uniffi_meta::{create_metadata_groups, group_metadata, EnumMetadata, Metadata, MetadataGroup};
|
||||
|
||||
|
@ -57,19 +57,13 @@ pub fn add_group_to_ci(iface: &mut ComponentInterface, group: MetadataGroup) ->
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn add_enum_to_ci(
|
||||
iface: &mut ComponentInterface,
|
||||
meta: EnumMetadata,
|
||||
is_flat: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
fn add_enum_to_ci(iface: &mut ComponentInterface, meta: EnumMetadata) -> anyhow::Result<()> {
|
||||
let ty = Type::Enum {
|
||||
name: meta.name.clone(),
|
||||
module_path: meta.module_path.clone(),
|
||||
};
|
||||
iface.types.add_known_type(&ty)?;
|
||||
|
||||
let enum_ = Enum::try_from_meta(meta, is_flat)?;
|
||||
iface.add_enum_definition(enum_)?;
|
||||
iface.add_enum_definition(meta.try_into()?)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -96,10 +90,7 @@ fn add_item_to_ci(iface: &mut ComponentInterface, item: Metadata) -> anyhow::Res
|
|||
iface.add_record_definition(record)?;
|
||||
}
|
||||
Metadata::Enum(meta) => {
|
||||
let flat = meta
|
||||
.forced_flatness
|
||||
.unwrap_or_else(|| meta.variants.iter().all(|v| v.fields.is_empty()));
|
||||
add_enum_to_ci(iface, meta, flat)?;
|
||||
add_enum_to_ci(iface, meta)?;
|
||||
}
|
||||
Metadata::Object(meta) => {
|
||||
iface.types.add_known_type(&Type::Object {
|
||||
|
|
|
@ -36,24 +36,24 @@ mod filters {
|
|||
Type::Float32 => "f32".into(),
|
||||
Type::Float64 => "f64".into(),
|
||||
Type::Boolean => "bool".into(),
|
||||
Type::String => "String".into(),
|
||||
Type::Bytes => "Vec<u8>".into(),
|
||||
Type::Timestamp => "std::time::SystemTime".into(),
|
||||
Type::Duration => "std::time::Duration".into(),
|
||||
Type::String => "::std::string::String".into(),
|
||||
Type::Bytes => "::std::vec::Vec<u8>".into(),
|
||||
Type::Timestamp => "::std::time::SystemTime".into(),
|
||||
Type::Duration => "::std::time::Duration".into(),
|
||||
Type::Enum { name, .. } | Type::Record { name, .. } => format!("r#{name}"),
|
||||
Type::Object { name, imp, .. } => {
|
||||
format!("std::sync::Arc<{}>", imp.rust_name_for(name))
|
||||
format!("::std::sync::Arc<{}>", imp.rust_name_for(name))
|
||||
}
|
||||
Type::CallbackInterface { name, .. } => format!("Box<dyn r#{name}>"),
|
||||
Type::Optional { inner_type } => {
|
||||
format!("std::option::Option<{}>", type_rs(inner_type)?)
|
||||
format!("::std::option::Option<{}>", type_rs(inner_type)?)
|
||||
}
|
||||
Type::Sequence { inner_type } => format!("std::vec::Vec<{}>", type_rs(inner_type)?),
|
||||
Type::Map {
|
||||
key_type,
|
||||
value_type,
|
||||
} => format!(
|
||||
"std::collections::HashMap<{}, {}>",
|
||||
"::std::collections::HashMap<{}, {}>",
|
||||
type_rs(key_type)?,
|
||||
type_rs(value_type)?
|
||||
),
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
// Forward work to `uniffi_macros` This keeps macro-based and UDL-based generated code consistent.
|
||||
#}
|
||||
|
||||
#[::uniffi::derive_enum_for_udl(
|
||||
{%- if e.is_non_exhaustive() -%}
|
||||
non_exhaustive,
|
||||
{%- endif %}
|
||||
)]
|
||||
#[::uniffi::udl_derive(Enum)]
|
||||
{%- if e.is_non_exhaustive() %}
|
||||
#[non_exhaustive]
|
||||
{%- endif %}
|
||||
enum r#{{ e.name() }} {
|
||||
{%- for variant in e.variants() %}
|
||||
r#{{ variant.name() }} {
|
||||
|
|
|
@ -2,17 +2,16 @@
|
|||
// Forward work to `uniffi_macros` This keeps macro-based and UDL-based generated code consistent.
|
||||
#}
|
||||
|
||||
#[::uniffi::derive_error_for_udl(
|
||||
{% if e.is_flat() -%}
|
||||
flat_error,
|
||||
{% if ci.should_generate_error_read(e) -%}
|
||||
with_try_read,
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if e.is_non_exhaustive() -%}
|
||||
non_exhaustive,
|
||||
{%- endif %}
|
||||
)]
|
||||
#[::uniffi::udl_derive(Error)]
|
||||
{% if e.is_flat() -%}
|
||||
#[uniffi(flat_error)]
|
||||
{% if ci.should_generate_error_read(e) -%}
|
||||
#[uniffi(with_try_read)]
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if e.is_non_exhaustive() -%}
|
||||
#[non_exhaustive]
|
||||
{%- endif %}
|
||||
enum r#{{ e.name() }} {
|
||||
{%- for variant in e.variants() %}
|
||||
r#{{ variant.name() }} {
|
||||
|
|
|
@ -33,7 +33,7 @@ pub trait r#{{ obj.name() }} {
|
|||
#[uniffi::export(Eq)]
|
||||
{% endmatch %}
|
||||
{% endfor %}
|
||||
#[::uniffi::derive_object_for_udl]
|
||||
#[::uniffi::udl_derive(Object)]
|
||||
struct {{ obj.rust_name() }} { }
|
||||
|
||||
{%- for cons in obj.constructors() %}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче