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:
Ben Dean-Kawamura 2024-09-09 15:42:32 +00:00
Родитель 5fe168ff7d
Коммит 415d48c0cb
159 изменённых файлов: 3502 добавлений и 2369 удалений

Просмотреть файл

@ -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"]

88
Cargo.lock сгенерированный
Просмотреть файл

@ -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",

Просмотреть файл

@ -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}

4
third_party/rust/error-support/Cargo.toml поставляемый
Просмотреть файл

@ -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"]

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

99
third_party/rust/glean-core/Cargo.toml поставляемый
Просмотреть файл

@ -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

2
third_party/rust/glean/.cargo-checksum.json поставляемый
Просмотреть файл

@ -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"}

6
third_party/rust/glean/Cargo.toml поставляемый
Просмотреть файл

@ -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}

4
third_party/rust/relevancy/Cargo.toml поставляемый
Просмотреть файл

@ -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}

4
third_party/rust/remote_settings/Cargo.toml поставляемый
Просмотреть файл

@ -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}

4
third_party/rust/suggest/Cargo.toml поставляемый
Просмотреть файл

@ -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}

4
third_party/rust/sync15/Cargo.toml поставляемый
Просмотреть файл

@ -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]

2
third_party/rust/tabs/.cargo-checksum.json поставляемый
Просмотреть файл

@ -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}

4
third_party/rust/tabs/Cargo.toml поставляемый
Просмотреть файл

@ -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"}

26
third_party/rust/uniffi/Cargo.toml поставляемый
Просмотреть файл

@ -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",

216
third_party/rust/uniffi/src/cli.rs поставляемый
Просмотреть файл

@ -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(),

19
third_party/rust/uniffi/src/lib.rs поставляемый
Просмотреть файл

@ -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>`

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

27
third_party/rust/uniffi_bindgen/Cargo.toml поставляемый
Просмотреть файл

@ -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"]

1
third_party/rust/uniffi_bindgen/src/bindings/README.md поставляемый Normal file
Просмотреть файл

@ -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}"),

56
third_party/rust/uniffi_bindgen/src/cargo_metadata.rs поставляемый Normal file
Просмотреть файл

@ -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 {

145
third_party/rust/uniffi_bindgen/src/interface/visit_mut.rs поставляемый Normal file
Просмотреть файл

@ -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;
}
}

301
third_party/rust/uniffi_bindgen/src/lib.rs поставляемый
Просмотреть файл

@ -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() %}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше