diff --git a/.cargo/config.toml.in b/.cargo/config.toml.in index 3f6f8e2dca56..f9adc255437a 100644 --- a/.cargo/config.toml.in +++ b/.cargo/config.toml.in @@ -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"] diff --git a/Cargo.lock b/Cargo.lock index f097456de7c2..9807db848a01 100644 --- a/Cargo.lock +++ b/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", diff --git a/Cargo.toml b/Cargo.toml index 66391e442c1c..56409ac5eecd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,8 +55,8 @@ resolver = "2" [workspace.dependencies] # Shared across multiple UniFFI consumers. -uniffi = "0.27.3" -uniffi_bindgen = "0.27.3" +uniffi = "0.28.1" +uniffi_bindgen = "0.28.1" # Shared across multiple application-services consumers. rusqlite = "0.31.0" # Shared across multiple glean consumers. @@ -172,9 +172,6 @@ hashbrown = { path = "build/rust/hashbrown" } # Patch `socket2` 0.4 to 0.5 socket2 = { path = "build/rust/socket2" } -# Patch heck 0.4 to 0.5 -heck = { path = "build/rust/heck" } - # The following overrides point to dummy projects, as a temporary measure until this is resolved: # https://github.com/rust-lang/cargo/issues/6179 js-sys = { path = "build/rust/dummy-web/js-sys" } @@ -213,14 +210,14 @@ midir = { git = "https://github.com/mozilla/midir.git", rev = "85156e360a37d8517 malloc_size_of_derive = { path = "xpcom/rust/malloc_size_of_derive" } # application-services overrides to make updating them all simpler. -interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -relevancy = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -sql-support = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -suggest = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -sync15 = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -tabs = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -viaduct = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } -webext-storage = { git = "https://github.com/mozilla/application-services", rev = "dbeaef2eb28e9da7cc2f96e26296513cc4e07c07" } +interrupt-support = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +relevancy = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +sql-support = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +suggest = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +sync15 = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +tabs = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +viaduct = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } +webext-storage = { git = "https://github.com/mozilla/application-services", rev = "6651984e3b456d99fad0df1deb727b7c2f62ec16" } # Patch `gpu-descriptor` 0.3.0 to remove unnecessary `allocator-api2` dep.: # Still waiting for the now-merged to be released. diff --git a/build/rust/heck/Cargo.toml b/build/rust/heck/Cargo.toml deleted file mode 100644 index 90035b066da9..000000000000 --- a/build/rust/heck/Cargo.toml +++ /dev/null @@ -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" diff --git a/build/rust/heck/lib.rs b/build/rust/heck/lib.rs deleted file mode 100644 index 8e169c46c4b6..000000000000 --- a/build/rust/heck/lib.rs +++ /dev/null @@ -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::*; diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index f4861c670d46..e649f31b623d 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -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" diff --git a/third_party/rust/error-support/.cargo-checksum.json b/third_party/rust/error-support/.cargo-checksum.json index f602db9bff11..112893421d10 100644 --- a/third_party/rust/error-support/.cargo-checksum.json +++ b/third_party/rust/error-support/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/error-support/Cargo.toml b/third_party/rust/error-support/Cargo.toml index a425a3d54835..205cbcedc4af 100644 --- a/third_party/rust/error-support/Cargo.toml +++ b/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"] diff --git a/third_party/rust/glean-core/.cargo-checksum.json b/third_party/rust/glean-core/.cargo-checksum.json index 824b4420e8d2..f8543923e41a 100644 --- a/third_party/rust/glean-core/.cargo-checksum.json +++ b/third_party/rust/glean-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"5c467da9b977ccdbaad7f1294a0c6c4bdcc12f022dacaf8a79da37dca1ec0c14","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"026495898699b54608eb4ec16074ffafc57920d80ccb59961c501a1ea28c9985","build.rs":"4857bea99c6b8c08db8818efa9d3738716f52d3acb68159323957ae52892a3eb","src/common_metric_data.rs":"02dd1628fed6587621c089952dd0cb80bed3c352cdacfb33be7e218ad1d847e9","src/core/mod.rs":"ecd4bbacd14c48f110c509a6e3ccd436a1116b10d3842b65d0739e3641371497","src/core_metrics.rs":"a877e42e0f8b932adb52a5681ad76fd977808cb48c7eeb29b1e4bbe804f1ea96","src/coverage.rs":"49613fd310bd24d779472720975fbe6c97ec370a95eb55f10afa43f67539c942","src/database/mod.rs":"5889c2b8000d70524cef3cec199f27fca65a05d431d2e4be6070bc176e1071d0","src/debug.rs":"7bd9e199d0d5c8170f6dbb9a725a18eaca1df34309d32b02081574962a86816e","src/dispatcher/global.rs":"17493b1a5e926ca1e9c1cda2ee031773402a19183911eb80048630d60266d89e","src/dispatcher/mod.rs":"391310269947452d7e0de24c848c183110c60149d75e345ba6d5d146f222dace","src/error.rs":"b93c7d3e243b21bb9eafc95f17860aba1a942b2f2b0a7f43307690f05fece516","src/error_recording.rs":"1aba34e9d3c741755055f5b76415114b25b146b0aa90049c3457cfe12066deda","src/event_database/mod.rs":"e5255c4669bf5b0eb670e012c43368e327d9e2bb38358a1037b0894025295b4f","src/fd_logger.rs":"0c9def6fa53db1a2ab93c85795f8a7df57797bcfd3978146923e151752e291a6","src/glean.udl":"c141d2eab0dda5cec9d12584b5efa52f9bf311906919652ff1fa7baf7338049c","src/glean_metrics.rs":"9414fb1453d19f6832df33e4c6ef7383d62203e47026bf5bc9552b083101ddd1","src/histogram/exponential.rs":"d39c4ec11d9c48d7a98b19f5ef8f181d1e5c12c614179902c61bbb894501b4ac","src/histogram/functional.rs":"1a63a305b48bcef7bc38136b40d916df4bb8f098dc602514ada54a9b091f6951","src/histogram/linear.rs":"0c9383b0a7233325e64833bcc6c7fe150e495f81b0cc70ae8d53b83493ba3a33","src/histogram/mod.rs":"bbb9535a633b5a85b6b11c6e4eed3314ab797950355a9bb8ccf3a22000f1e093","src/internal_metrics.rs":"872aff76bd0690bfea7e675092f1a8cad9d35b76459f9fc67d8cd7bc3d614ae9","src/internal_pings.rs":"c54339cb2530eec7717a3f6dd81ce98adf5da5d615bcf0a071fd90f415016866","src/lib.rs":"80fb55ca2bf22fca363f539dedcc45e58f640bebddb8eb1fb9479454740b7fbe","src/lib_unit_tests.rs":"3246160f2150d9ad0f50a1cab1e69c4ba400bdf33df42a814bec03b5df8e2ed4","src/metrics/boolean.rs":"2b9ef57e3582c9bd8b2cca8ab94c962a4871ecc00e837b913c9b0349ba9dff08","src/metrics/counter.rs":"b4a52a8167fb0edd6354f952525e59f3eadb4261de3483374f03c94449d30b92","src/metrics/custom_distribution.rs":"c99a57e087aa2a36c1f5904f16a3a9cd0703b89ba14f1840260e70a4eec02564","src/metrics/datetime.rs":"e4405762fc71718299fa1b208e3d5fda654bd1b82fe908c884c284e3530de2ec","src/metrics/denominator.rs":"95e8442f90bad97f80fc74b146782f215344b52c5f3825ae0a8baffdc001a714","src/metrics/event.rs":"cd52e200d313e2e6f31707419d4a7fe1cab34916ee145f8136440d6da34aaad4","src/metrics/experiment.rs":"5f9278cca4e133eb8df33bbfe36d1fe0ef3eade8c09f1b46db3c4d0790515412","src/metrics/labeled.rs":"2f792a9a682d5f5234928b4af6a536fc672e0a42db7ec06151897db56fe63957","src/metrics/memory_distribution.rs":"fe094a870a4a5a0a35656ef901e9ecdef7c4b4ee645d1594ffdb4149b709f6c3","src/metrics/memory_unit.rs":"ee32e020cb303dd631457374048a3ed53a2e7cbacc29c54d17d836fb15507538","src/metrics/mod.rs":"12133f4921e865d2b5895ad46b928d494f9319297e57a44aeb1d9f3d2f3637b7","src/metrics/numerator.rs":"937dfd583b797ac798a525cedca95c5a36262356760a89670d8113983c263154","src/metrics/object.rs":"2a1f1cc31973b576e55ba464b35c41b9420f62471eebba51273bca6856459538","src/metrics/ping.rs":"639d2dff2dbeb8e836c38c64281cfbfa62c87ef80091d6260167b2dd07eba0d6","src/metrics/quantity.rs":"aa13a8f8cf8e5e0281668fbbafc2998411df2a499479423558fd91b9bd7f8702","src/metrics/rate.rs":"603cc45c149c7a27c93b6a80146bf43f8ce70d9655f905bb5be6bc2c15bcb22b","src/metrics/recorded_experiment.rs":"33958abee79d8b55dec4cb5d20742640423713010f76314075cefde18b5c118a","src/metrics/remote_settings_config.rs":"908bae1aa4ea06d5b50d6b80d74b9877a8fc6fc05462cf34b8723269c7f79593","src/metrics/string.rs":"88beb1a847e5df9898b72ca7ed8ced3b7d2b40d83ff3670baf66f83a3e6cb005","src/metrics/string_list.rs":"ed53a095184c3e8224d0511809b5d7601ba3166505a39b0570f24ebeb0a5b97c","src/metrics/text.rs":"757f6919124d74e0512faa5bb9751a729b6bbc63ebe4d16ca81e9087f5595eaf","src/metrics/time_unit.rs":"4704703e19e799933aec3f39e3d3a125058756d7c7ba04f8729885c7843df447","src/metrics/timespan.rs":"1ad5233c7522cab70b4c095fb24cace66ace9741731f97bc001ede071f10d1ef","src/metrics/timing_distribution.rs":"2e38792a6bcfbcc85946d28bc671d8ef5912d5dfb810a8ca280b0180a4baa042","src/metrics/url.rs":"589ae1f8047367ad8c19b57a48ca8130d5f36cf3ce5954124150f0eb89c620ea","src/metrics/uuid.rs":"cacffd95ab30ed327ec2fa5feaf1359e667706746401f1e2c1195ad9553c4b54","src/ping/mod.rs":"307ddb82a2fb1804fb12673bb9ccc809f728c59ad8d1d023b94b4e78eeaf4186","src/scheduler.rs":"4cab95b3b97e103a37c73061d3b885263664736cf50cf7c1b08ea624c94fbe64","src/storage/mod.rs":"91f02556f113799e0d88d732ab342bda443f43461369e8b41c424c074d742591","src/system.rs":"e3d1b54e1d39cafe6f4dc7ff5021b08c879733f909951b0e1332b3efa9ed97bd","src/traits/boolean.rs":"be0e130f8043215705becc956d45b126c340568f1b24a396c0af9b4334a41ced","src/traits/counter.rs":"c686d26e131d854cd7a7df83c900ca7c17a03c663a30cf58ab48c7259476ce85","src/traits/custom_distribution.rs":"0bd1d425e4c059cca6af2dfb13c78e5e4c6c07fb46c7e31489ad0c5959854833","src/traits/datetime.rs":"636ac1456b1b042e38cf5ae6193c5b232ea0b80df62f583a2097891baef9641b","src/traits/event.rs":"a02235aae630aba7a45a3166b756927252b397af3ecdfab7236931e62725ac49","src/traits/labeled.rs":"c633c68e70a44e73f8aff88aaab1029c0faded3cad08d822590ed8838f24b4fd","src/traits/memory_distribution.rs":"55bb8f45e948319fbba9d28a50d8742da134b066a42e480887db7c7e435f4096","src/traits/mod.rs":"3560fdf3b81dceabbac9d97b0356aa8f883e477dcb787c81a09529047fda7161","src/traits/numerator.rs":"6e4f236bdc448f1bde7a8c249dcd086204c2c69990d3f444e746290929226ed3","src/traits/object.rs":"c03bad670ec7affbc578247f9e1904e898c1870b9bf25750c5094113f995623f","src/traits/ping.rs":"8831c106c03afeb458b0b028fa1ce61f056ebf8e82bc0a171a1bff255d920748","src/traits/quantity.rs":"6ffe25c913bef4315573d747308c182de740b2a4e02ba22cd21d0c33ba521f31","src/traits/rate.rs":"f000790440e0f389f0b160526a9a9a266e58d1405915ae56ac550f482858222c","src/traits/string.rs":"0c3c88382ff2e8eba89c7cfe129c4b84e31140af717819533c14919541ad790c","src/traits/string_list.rs":"14e56b62c2c2be1dd8013f12001f235b084abd2a0d5aa2f7932843877af49ac0","src/traits/text.rs":"8af7d3a0c87cfd8c6d33d6ad47532b431055bbdd395f9110da5630222c23cf93","src/traits/timespan.rs":"52be325a9c061916f34c5b638a07a93b4a14aa89fe365783103d2e06b998f547","src/traits/timing_distribution.rs":"0d35acddd9e35a7f8859cf007162460b5fd0bf06d205cd195ed1c857bbe58c42","src/traits/url.rs":"c27f7add23214ff051078b65b88120b620560d2841a1056c7214d5237e86b9e4","src/traits/uuid.rs":"81322e71c7e847bacaf827a2cd58f6193bdc208355524207f7f38db039da6aa8","src/upload/directory.rs":"5545042c1d1f37ebb08445b88c0fa8b97aad145e81e34051fad3da2a94b1b52d","src/upload/mod.rs":"7b65a31ed8b12c4a7e708edb9bbf48ab6a4c99422b4bb1f50891cde07f5e6a3c","src/upload/policy.rs":"c250957a37783e74af8002cd80ba06ef9780a389fb0f61b8b665b79688f0a360","src/upload/request.rs":"5891364d4254aafdb43751f476b0b908b681544793ac98802fe103de321ec326","src/upload/result.rs":"7efbbe50e8d36beb3f23e7bfd172d22e1c003472d2dd8055b06f6050c36437c5","src/util.rs":"ee7500434d9758a320dd410f18d7e18da956591e19d2555db87eef9623e4b916","tests/boolean.rs":"76d6014ff108cb6514d9bceb1b2b14749a55b09921f4595a5e30f1bd3546e9f0","tests/common/mod.rs":"b52367b79772875902b24d05a211139be02b38305cd2991dee1d369f3a8514f1","tests/counter.rs":"4c59def10e64de0d7a0241dde0267fd02c828b38be8cc67fba90a76004ca6721","tests/custom_distribution.rs":"41c593a0b4561e21f29d1a5b948de964a866253c58ca76ffefebe370fca150e0","tests/datetime.rs":"ec3c9760e70bb2cbc61ab23281c891bc1ec493c5c545466c29fd13e4f05c2c96","tests/event.rs":"63b3dee970e144e522a10aa4512d7c2179b4900867ba13aa15f194bd37aa1b59","tests/labeled.rs":"38d9569e53beefa3d902f5623cfacf0dccd0bc79dd08d140c8eaddcfec5c340a","tests/memory_distribution.rs":"a5a7aa955e60823ea29a6f4bc96c61e41f1e41f08958aa4854668cf8fe04cde6","tests/object.rs":"8c35676e04f6ccf54a28764700915e753fc0355bfa5d7804d72caba66fd564cd","tests/ping.rs":"3330885672b3f3ffccf1044c27f800255f099449d8f1b5fef64e47bee51cfc3e","tests/ping_maker.rs":"3959842767920acb34db9d00fe7341f3a30ca7f8a378f73e77cd5cf5121f84a1","tests/quantity.rs":"55e7dca346fd1d27f0974b78ca3fb12427cb5da2ee637afc08a54f360f947361","tests/rate.rs":"1de571b9f0ee9a9006cbc8a31f91352d3ff1190b50840f0f668b470a7cd2a3a5","tests/storage.rs":"f0c8312bd789d7bda502cd45f35fef6b8591652bd194d07da4d81935ebe69b48","tests/string.rs":"397fcfd27c25f0e81e2a40db3265b0d7dc0dd56b190319c1f86cb1c2c0ed4f9d","tests/string_list.rs":"77188a2b90663c3f8dac5da89a6cb6b1d16a9f8c66ccd032d02966dfd14a3486","tests/text.rs":"1d43f6b90a43124311cacf0a6ee16f9e1e9263bcd11fee8b996d6efd81633638","tests/timespan.rs":"d50d75c7d75da3a878d67331cb0df8ae5e6a099ffab474361f71a408e02528d7","tests/timing_distribution.rs":"44d97357047feefb0cd16e3809d3ef113dcc33b302c943d2f836d69575c5b370","tests/uuid.rs":"052ad26a6927c56272219340211cf4a059d200f14287b482fe8621d7bce3cc54","uniffi.toml":"6ddc98b686b0925a81abd9d1c769e5c98ac29771b210a1c535931a46dec9a8e3"},"package":"8de1ecd4c5de0b0ecad949e29f6973bfaa4d53b668ebccdd5bc1a1f2591d0271"} \ No newline at end of file +{"files":{"Cargo.toml":"8f0994507cb1de658c0f00be7d85d8e5ac177b3cf181de045adc53662b4748c7","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"026495898699b54608eb4ec16074ffafc57920d80ccb59961c501a1ea28c9985","build.rs":"4857bea99c6b8c08db8818efa9d3738716f52d3acb68159323957ae52892a3eb","src/common_metric_data.rs":"02dd1628fed6587621c089952dd0cb80bed3c352cdacfb33be7e218ad1d847e9","src/core/mod.rs":"ecd4bbacd14c48f110c509a6e3ccd436a1116b10d3842b65d0739e3641371497","src/core_metrics.rs":"a877e42e0f8b932adb52a5681ad76fd977808cb48c7eeb29b1e4bbe804f1ea96","src/coverage.rs":"49613fd310bd24d779472720975fbe6c97ec370a95eb55f10afa43f67539c942","src/database/mod.rs":"5889c2b8000d70524cef3cec199f27fca65a05d431d2e4be6070bc176e1071d0","src/debug.rs":"7bd9e199d0d5c8170f6dbb9a725a18eaca1df34309d32b02081574962a86816e","src/dispatcher/global.rs":"17493b1a5e926ca1e9c1cda2ee031773402a19183911eb80048630d60266d89e","src/dispatcher/mod.rs":"391310269947452d7e0de24c848c183110c60149d75e345ba6d5d146f222dace","src/error.rs":"b93c7d3e243b21bb9eafc95f17860aba1a942b2f2b0a7f43307690f05fece516","src/error_recording.rs":"1aba34e9d3c741755055f5b76415114b25b146b0aa90049c3457cfe12066deda","src/event_database/mod.rs":"e5255c4669bf5b0eb670e012c43368e327d9e2bb38358a1037b0894025295b4f","src/fd_logger.rs":"0c9def6fa53db1a2ab93c85795f8a7df57797bcfd3978146923e151752e291a6","src/glean.udl":"c141d2eab0dda5cec9d12584b5efa52f9bf311906919652ff1fa7baf7338049c","src/glean_metrics.rs":"9414fb1453d19f6832df33e4c6ef7383d62203e47026bf5bc9552b083101ddd1","src/histogram/exponential.rs":"d39c4ec11d9c48d7a98b19f5ef8f181d1e5c12c614179902c61bbb894501b4ac","src/histogram/functional.rs":"1a63a305b48bcef7bc38136b40d916df4bb8f098dc602514ada54a9b091f6951","src/histogram/linear.rs":"0c9383b0a7233325e64833bcc6c7fe150e495f81b0cc70ae8d53b83493ba3a33","src/histogram/mod.rs":"bbb9535a633b5a85b6b11c6e4eed3314ab797950355a9bb8ccf3a22000f1e093","src/internal_metrics.rs":"872aff76bd0690bfea7e675092f1a8cad9d35b76459f9fc67d8cd7bc3d614ae9","src/internal_pings.rs":"c54339cb2530eec7717a3f6dd81ce98adf5da5d615bcf0a071fd90f415016866","src/lib.rs":"80fb55ca2bf22fca363f539dedcc45e58f640bebddb8eb1fb9479454740b7fbe","src/lib_unit_tests.rs":"3246160f2150d9ad0f50a1cab1e69c4ba400bdf33df42a814bec03b5df8e2ed4","src/metrics/boolean.rs":"2b9ef57e3582c9bd8b2cca8ab94c962a4871ecc00e837b913c9b0349ba9dff08","src/metrics/counter.rs":"b4a52a8167fb0edd6354f952525e59f3eadb4261de3483374f03c94449d30b92","src/metrics/custom_distribution.rs":"c99a57e087aa2a36c1f5904f16a3a9cd0703b89ba14f1840260e70a4eec02564","src/metrics/datetime.rs":"e4405762fc71718299fa1b208e3d5fda654bd1b82fe908c884c284e3530de2ec","src/metrics/denominator.rs":"95e8442f90bad97f80fc74b146782f215344b52c5f3825ae0a8baffdc001a714","src/metrics/event.rs":"cd52e200d313e2e6f31707419d4a7fe1cab34916ee145f8136440d6da34aaad4","src/metrics/experiment.rs":"5f9278cca4e133eb8df33bbfe36d1fe0ef3eade8c09f1b46db3c4d0790515412","src/metrics/labeled.rs":"2f792a9a682d5f5234928b4af6a536fc672e0a42db7ec06151897db56fe63957","src/metrics/memory_distribution.rs":"fe094a870a4a5a0a35656ef901e9ecdef7c4b4ee645d1594ffdb4149b709f6c3","src/metrics/memory_unit.rs":"ee32e020cb303dd631457374048a3ed53a2e7cbacc29c54d17d836fb15507538","src/metrics/mod.rs":"12133f4921e865d2b5895ad46b928d494f9319297e57a44aeb1d9f3d2f3637b7","src/metrics/numerator.rs":"937dfd583b797ac798a525cedca95c5a36262356760a89670d8113983c263154","src/metrics/object.rs":"2a1f1cc31973b576e55ba464b35c41b9420f62471eebba51273bca6856459538","src/metrics/ping.rs":"639d2dff2dbeb8e836c38c64281cfbfa62c87ef80091d6260167b2dd07eba0d6","src/metrics/quantity.rs":"aa13a8f8cf8e5e0281668fbbafc2998411df2a499479423558fd91b9bd7f8702","src/metrics/rate.rs":"603cc45c149c7a27c93b6a80146bf43f8ce70d9655f905bb5be6bc2c15bcb22b","src/metrics/recorded_experiment.rs":"33958abee79d8b55dec4cb5d20742640423713010f76314075cefde18b5c118a","src/metrics/remote_settings_config.rs":"908bae1aa4ea06d5b50d6b80d74b9877a8fc6fc05462cf34b8723269c7f79593","src/metrics/string.rs":"88beb1a847e5df9898b72ca7ed8ced3b7d2b40d83ff3670baf66f83a3e6cb005","src/metrics/string_list.rs":"ed53a095184c3e8224d0511809b5d7601ba3166505a39b0570f24ebeb0a5b97c","src/metrics/text.rs":"757f6919124d74e0512faa5bb9751a729b6bbc63ebe4d16ca81e9087f5595eaf","src/metrics/time_unit.rs":"4704703e19e799933aec3f39e3d3a125058756d7c7ba04f8729885c7843df447","src/metrics/timespan.rs":"1ad5233c7522cab70b4c095fb24cace66ace9741731f97bc001ede071f10d1ef","src/metrics/timing_distribution.rs":"2e38792a6bcfbcc85946d28bc671d8ef5912d5dfb810a8ca280b0180a4baa042","src/metrics/url.rs":"589ae1f8047367ad8c19b57a48ca8130d5f36cf3ce5954124150f0eb89c620ea","src/metrics/uuid.rs":"cacffd95ab30ed327ec2fa5feaf1359e667706746401f1e2c1195ad9553c4b54","src/ping/mod.rs":"307ddb82a2fb1804fb12673bb9ccc809f728c59ad8d1d023b94b4e78eeaf4186","src/scheduler.rs":"4cab95b3b97e103a37c73061d3b885263664736cf50cf7c1b08ea624c94fbe64","src/storage/mod.rs":"91f02556f113799e0d88d732ab342bda443f43461369e8b41c424c074d742591","src/system.rs":"e3d1b54e1d39cafe6f4dc7ff5021b08c879733f909951b0e1332b3efa9ed97bd","src/traits/boolean.rs":"be0e130f8043215705becc956d45b126c340568f1b24a396c0af9b4334a41ced","src/traits/counter.rs":"c686d26e131d854cd7a7df83c900ca7c17a03c663a30cf58ab48c7259476ce85","src/traits/custom_distribution.rs":"0bd1d425e4c059cca6af2dfb13c78e5e4c6c07fb46c7e31489ad0c5959854833","src/traits/datetime.rs":"636ac1456b1b042e38cf5ae6193c5b232ea0b80df62f583a2097891baef9641b","src/traits/event.rs":"a02235aae630aba7a45a3166b756927252b397af3ecdfab7236931e62725ac49","src/traits/labeled.rs":"c633c68e70a44e73f8aff88aaab1029c0faded3cad08d822590ed8838f24b4fd","src/traits/memory_distribution.rs":"55bb8f45e948319fbba9d28a50d8742da134b066a42e480887db7c7e435f4096","src/traits/mod.rs":"3560fdf3b81dceabbac9d97b0356aa8f883e477dcb787c81a09529047fda7161","src/traits/numerator.rs":"6e4f236bdc448f1bde7a8c249dcd086204c2c69990d3f444e746290929226ed3","src/traits/object.rs":"c03bad670ec7affbc578247f9e1904e898c1870b9bf25750c5094113f995623f","src/traits/ping.rs":"8831c106c03afeb458b0b028fa1ce61f056ebf8e82bc0a171a1bff255d920748","src/traits/quantity.rs":"6ffe25c913bef4315573d747308c182de740b2a4e02ba22cd21d0c33ba521f31","src/traits/rate.rs":"f000790440e0f389f0b160526a9a9a266e58d1405915ae56ac550f482858222c","src/traits/string.rs":"0c3c88382ff2e8eba89c7cfe129c4b84e31140af717819533c14919541ad790c","src/traits/string_list.rs":"14e56b62c2c2be1dd8013f12001f235b084abd2a0d5aa2f7932843877af49ac0","src/traits/text.rs":"8af7d3a0c87cfd8c6d33d6ad47532b431055bbdd395f9110da5630222c23cf93","src/traits/timespan.rs":"52be325a9c061916f34c5b638a07a93b4a14aa89fe365783103d2e06b998f547","src/traits/timing_distribution.rs":"0d35acddd9e35a7f8859cf007162460b5fd0bf06d205cd195ed1c857bbe58c42","src/traits/url.rs":"c27f7add23214ff051078b65b88120b620560d2841a1056c7214d5237e86b9e4","src/traits/uuid.rs":"81322e71c7e847bacaf827a2cd58f6193bdc208355524207f7f38db039da6aa8","src/upload/directory.rs":"5545042c1d1f37ebb08445b88c0fa8b97aad145e81e34051fad3da2a94b1b52d","src/upload/mod.rs":"7b65a31ed8b12c4a7e708edb9bbf48ab6a4c99422b4bb1f50891cde07f5e6a3c","src/upload/policy.rs":"c250957a37783e74af8002cd80ba06ef9780a389fb0f61b8b665b79688f0a360","src/upload/request.rs":"5891364d4254aafdb43751f476b0b908b681544793ac98802fe103de321ec326","src/upload/result.rs":"7efbbe50e8d36beb3f23e7bfd172d22e1c003472d2dd8055b06f6050c36437c5","src/util.rs":"ee7500434d9758a320dd410f18d7e18da956591e19d2555db87eef9623e4b916","tests/boolean.rs":"76d6014ff108cb6514d9bceb1b2b14749a55b09921f4595a5e30f1bd3546e9f0","tests/common/mod.rs":"b52367b79772875902b24d05a211139be02b38305cd2991dee1d369f3a8514f1","tests/counter.rs":"4c59def10e64de0d7a0241dde0267fd02c828b38be8cc67fba90a76004ca6721","tests/custom_distribution.rs":"41c593a0b4561e21f29d1a5b948de964a866253c58ca76ffefebe370fca150e0","tests/datetime.rs":"ec3c9760e70bb2cbc61ab23281c891bc1ec493c5c545466c29fd13e4f05c2c96","tests/event.rs":"63b3dee970e144e522a10aa4512d7c2179b4900867ba13aa15f194bd37aa1b59","tests/labeled.rs":"38d9569e53beefa3d902f5623cfacf0dccd0bc79dd08d140c8eaddcfec5c340a","tests/memory_distribution.rs":"a5a7aa955e60823ea29a6f4bc96c61e41f1e41f08958aa4854668cf8fe04cde6","tests/object.rs":"8c35676e04f6ccf54a28764700915e753fc0355bfa5d7804d72caba66fd564cd","tests/ping.rs":"3330885672b3f3ffccf1044c27f800255f099449d8f1b5fef64e47bee51cfc3e","tests/ping_maker.rs":"3959842767920acb34db9d00fe7341f3a30ca7f8a378f73e77cd5cf5121f84a1","tests/quantity.rs":"55e7dca346fd1d27f0974b78ca3fb12427cb5da2ee637afc08a54f360f947361","tests/rate.rs":"1de571b9f0ee9a9006cbc8a31f91352d3ff1190b50840f0f668b470a7cd2a3a5","tests/storage.rs":"f0c8312bd789d7bda502cd45f35fef6b8591652bd194d07da4d81935ebe69b48","tests/string.rs":"397fcfd27c25f0e81e2a40db3265b0d7dc0dd56b190319c1f86cb1c2c0ed4f9d","tests/string_list.rs":"77188a2b90663c3f8dac5da89a6cb6b1d16a9f8c66ccd032d02966dfd14a3486","tests/text.rs":"1d43f6b90a43124311cacf0a6ee16f9e1e9263bcd11fee8b996d6efd81633638","tests/timespan.rs":"d50d75c7d75da3a878d67331cb0df8ae5e6a099ffab474361f71a408e02528d7","tests/timing_distribution.rs":"44d97357047feefb0cd16e3809d3ef113dcc33b302c943d2f836d69575c5b370","tests/uuid.rs":"052ad26a6927c56272219340211cf4a059d200f14287b482fe8621d7bce3cc54","uniffi.toml":"6ddc98b686b0925a81abd9d1c769e5c98ac29771b210a1c535931a46dec9a8e3"},"package":"bfd39741d1790f1022b0bf65d7b4a73fbb7a646158e0c96a0c845b097cce2ba2"} \ No newline at end of file diff --git a/third_party/rust/glean-core/Cargo.toml b/third_party/rust/glean-core/Cargo.toml index b8c4561a4002..b239305a4da2 100644 --- a/third_party/rust/glean-core/Cargo.toml +++ b/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 ", "The Glean Team ", ] +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 diff --git a/third_party/rust/glean/.cargo-checksum.json b/third_party/rust/glean/.cargo-checksum.json index d3bde14ac107..46482b5c179f 100644 --- a/third_party/rust/glean/.cargo-checksum.json +++ b/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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/third_party/rust/glean/Cargo.toml b/third_party/rust/glean/Cargo.toml index ccb4b0ddf8df..665c1e7b393f 100644 --- a/third_party/rust/glean/Cargo.toml +++ b/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 ", "The Glean Team ", @@ -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" diff --git a/third_party/rust/interrupt-support/.cargo-checksum.json b/third_party/rust/interrupt-support/.cargo-checksum.json index fc2244ad2a10..ef1774fc4b9d 100644 --- a/third_party/rust/interrupt-support/.cargo-checksum.json +++ b/third_party/rust/interrupt-support/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/interrupt-support/Cargo.toml b/third_party/rust/interrupt-support/Cargo.toml index 03b87ee30455..fe36f0665394 100644 --- a/third_party/rust/interrupt-support/Cargo.toml +++ b/third_party/rust/interrupt-support/Cargo.toml @@ -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"] diff --git a/third_party/rust/relevancy/.cargo-checksum.json b/third_party/rust/relevancy/.cargo-checksum.json index 88f839ffb146..d38487c76f20 100644 --- a/third_party/rust/relevancy/.cargo-checksum.json +++ b/third_party/rust/relevancy/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/relevancy/Cargo.toml b/third_party/rust/relevancy/Cargo.toml index cae166b37734..2f5cc939d898 100644 --- a/third_party/rust/relevancy/Cargo.toml +++ b/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"] diff --git a/third_party/rust/remote_settings/.cargo-checksum.json b/third_party/rust/remote_settings/.cargo-checksum.json index dd17c17d5a4d..c6ab8a0eb615 100644 --- a/third_party/rust/remote_settings/.cargo-checksum.json +++ b/third_party/rust/remote_settings/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/remote_settings/Cargo.toml b/third_party/rust/remote_settings/Cargo.toml index 87cd8467cf81..ed73488f3542 100644 --- a/third_party/rust/remote_settings/Cargo.toml +++ b/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"] diff --git a/third_party/rust/suggest/.cargo-checksum.json b/third_party/rust/suggest/.cargo-checksum.json index 9b2cae524afa..b99348a0eaba 100644 --- a/third_party/rust/suggest/.cargo-checksum.json +++ b/third_party/rust/suggest/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/suggest/Cargo.toml b/third_party/rust/suggest/Cargo.toml index 3097d8bed7b8..baabf64219ec 100644 --- a/third_party/rust/suggest/Cargo.toml +++ b/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] diff --git a/third_party/rust/sync15/.cargo-checksum.json b/third_party/rust/sync15/.cargo-checksum.json index fa8171bc74f9..cdb54a78f9a3 100644 --- a/third_party/rust/sync15/.cargo-checksum.json +++ b/third_party/rust/sync15/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/sync15/Cargo.toml b/third_party/rust/sync15/Cargo.toml index 06f5dfda921e..9931a375c475 100644 --- a/third_party/rust/sync15/Cargo.toml +++ b/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] diff --git a/third_party/rust/tabs/.cargo-checksum.json b/third_party/rust/tabs/.cargo-checksum.json index e8e4f8b7166e..3bd6c7ba5b45 100644 --- a/third_party/rust/tabs/.cargo-checksum.json +++ b/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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/tabs/Cargo.toml b/third_party/rust/tabs/Cargo.toml index e9da5e091c5b..8f3a7a1e443f 100644 --- a/third_party/rust/tabs/Cargo.toml +++ b/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"] diff --git a/third_party/rust/uniffi/.cargo-checksum.json b/third_party/rust/uniffi/.cargo-checksum.json index 81ca3764cfda..9ef7e69a3e8f 100644 --- a/third_party/rust/uniffi/.cargo-checksum.json +++ b/third_party/rust/uniffi/.cargo-checksum.json @@ -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"} \ No newline at end of file +{"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"} \ No newline at end of file diff --git a/third_party/rust/uniffi/Cargo.toml b/third_party/rust/uniffi/Cargo.toml index 8081d8f8f669..b8dbb9b9c939 100644 --- a/third_party/rust/uniffi/Cargo.toml +++ b/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 "] 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", diff --git a/third_party/rust/uniffi/src/cli.rs b/third_party/rust/uniffi/src/cli.rs index 77d7f219a920..e3d5cf41e902 100644 --- a/third_party/rust/uniffi/src/cli.rs +++ b/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 { + 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 { + match value.to_str() { + None => bail!("Unreadable target language"), + Some(s) => s.try_into(), + } + } +} + +impl TryFrom for TargetLanguage { + type Error = anyhow::Error; + fn try_from(value: String) -> Result { + 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, + languages: Vec, + 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, + 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(), diff --git a/third_party/rust/uniffi/src/lib.rs b/third_party/rust/uniffi/src/lib.rs index 319b3c783627..d49e89e584dd 100644 --- a/third_party/rust/uniffi/src/lib.rs +++ b/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}; diff --git a/third_party/rust/uniffi/tests/ui/proc_macro_arc.stderr b/third_party/rust/uniffi/tests/ui/proc_macro_arc.stderr index 0654a29e2580..5d801f6e01ad 100644 --- a/third_party/rust/uniffi/tests/ui/proc_macro_arc.stderr +++ b/third_party/rust/uniffi/tests/ui/proc_macro_arc.stderr @@ -2,7 +2,7 @@ error[E0277]: the trait bound `Foo: FfiConverterArc` is not satisfied --> tests/ui/proc_macro_arc.rs:10:1 | 10 | #[uniffi::export] - | ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc` is not implemented for `Foo`, which is required by `Arc: LowerReturn` | = help: the trait `LowerReturn` is implemented for `Arc` = note: required for `Arc` to implement `FfiConverter` @@ -10,13 +10,33 @@ error[E0277]: the trait bound `Foo: FfiConverterArc` is not satisfied = note: required for `Arc` to implement `LowerReturn` = 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` is not satisfied + --> tests/ui/proc_macro_arc.rs:11:18 + | +11 | fn make_foo() -> Arc { + | ^^^^^^^^ the trait `FfiConverterArc` is not implemented for `Foo`, which is required by `Arc: uniffi::TypeId` + | + = help: the trait `uniffi::TypeId` is implemented for `Arc` + = note: required for `Arc` to implement `FfiConverter` + = note: required for `Arc` to implement `uniffi::TypeId` + error[E0277]: the trait bound `child::Foo: FfiConverterArc` is not satisfied --> tests/ui/proc_macro_arc.rs:20:5 | 20 | #[uniffi::export] - | ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc` is not implemented for `child::Foo` + | ^^^^^^^^^^^^^^^^^ the trait `FfiConverterArc` is not implemented for `child::Foo`, which is required by `Arc: Lift` | = help: the trait `Lift` is implemented for `Arc` = note: required for `Arc` to implement `FfiConverter` = note: required for `Arc` to implement `Lift` = 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` is not satisfied + --> tests/ui/proc_macro_arc.rs:21:22 + | +21 | fn take_foo(foo: Arc) { + | ^^^^^^^^ the trait `FfiConverterArc` is not implemented for `child::Foo`, which is required by `Arc: uniffi::TypeId` + | + = help: the trait `uniffi::TypeId` is implemented for `Arc` + = note: required for `Arc` to implement `FfiConverter` + = note: required for `Arc` to implement `uniffi::TypeId` diff --git a/third_party/rust/uniffi_bindgen/.cargo-checksum.json b/third_party/rust/uniffi_bindgen/.cargo-checksum.json index c32688568271..38426872899a 100644 --- a/third_party/rust/uniffi_bindgen/.cargo-checksum.json +++ b/third_party/rust/uniffi_bindgen/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"a0c485377fe182c5abfb8e5f42b4e29491f1d383061253a6f837aed266b2ac8f","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","askama.toml":"1a245b7803adca782837e125c49100147d2de0d5a1c949ff95e91af1701f6058","src/backend/config.rs":"4861dbf251dbb10beb1ed7e3eea7d79499a0de1cd9ce9ee8381a0e729c097dea","src/backend/filters.rs":"8a818952896f9c5f438d6705bb28f56e77fbfce6d9757a2d74e1b3a925ed36e1","src/backend/mod.rs":"2ee9d974cd259f7fb156028b4f4f7601691e94fb5692a6daf0d362df3ecf79a8","src/backend/types.rs":"598df3a861f5d53b2c710848943f6049dd43cb4f37aa81f2c08fd36fc5b2f5d5","src/bindings/kotlin/gen_kotlin/callback_interface.rs":"741100c2b4b484583d34408b276394078a24918c47101fbaa6233df9c4da32f2","src/bindings/kotlin/gen_kotlin/compounds.rs":"b40d1ab8c70d7da458ff45d2ce58efb6cc3b24bf560c093cbec7d0854d461dc4","src/bindings/kotlin/gen_kotlin/custom.rs":"7e619f7320796ecd8c4ced82904b4bd3c6a0043b55d5829274ab3040cdf9cd7f","src/bindings/kotlin/gen_kotlin/enum_.rs":"6559bb00d8e359126b016e549263c0c9bc1dfc5654ed662c0c2912b47931b1e4","src/bindings/kotlin/gen_kotlin/external.rs":"38f42be67105b9a2ca5ecefec959e6659af728bedb9d107a51c595fe6ff5d332","src/bindings/kotlin/gen_kotlin/miscellany.rs":"6541987e627c4ff27a17ebe919b2b5cd97cb66ff41187ed636396b4e35ea2414","src/bindings/kotlin/gen_kotlin/mod.rs":"34328d11c59a67159620a21bc660fae149bbf452a817d6c9d3f7657cc5b79134","src/bindings/kotlin/gen_kotlin/object.rs":"1cb8d1f5eaf06ceaadb6d2cedca482fdd1502c24500ba270d8fcac48ef2f1231","src/bindings/kotlin/gen_kotlin/primitives.rs":"249896ec7d18f0f8d1d5dc8dc66ea6f3d0cc7b13344ab6892fb985f339d99b9f","src/bindings/kotlin/gen_kotlin/record.rs":"96fd1a180095a062b4a9b71d4f603b232f0133f46355a3e427c4064701d900f2","src/bindings/kotlin/gen_kotlin/variant.rs":"d111d6888745195fc2c24bdddc57359e771616102a8d182c5c8ad268b0a13460","src/bindings/kotlin/mod.rs":"ef88eb9b5b7d6f920c62a525ea4d4bf2a3b1a9154afaa012cdb2feea597fbf23","src/bindings/kotlin/templates/Async.kt":"2130ef176ffabe85cc737059203f2bda38df1f22f2398aa338c9d3099e6d46e2","src/bindings/kotlin/templates/BooleanHelper.kt":"50d8a5109e2d2676f25a02772079efbaac61776a76e3e84eebd1fb13294842de","src/bindings/kotlin/templates/ByteArrayHelper.kt":"dc4aafffacb1fa8f3b4e15f714c13b8d715eec178c63bdba6260baf612dd80d8","src/bindings/kotlin/templates/CallbackInterfaceImpl.kt":"be4d5a5d3ed4f7b1d4c9822905c5732bdb8593c3dbf8d4aabab62291d7ccec99","src/bindings/kotlin/templates/CallbackInterfaceRuntime.kt":"76689c1bfa8aa7dc6e2c9e77c42212b9f317763fb35cd7704ca470675dd2648d","src/bindings/kotlin/templates/CallbackInterfaceTemplate.kt":"b497250899bfd0c79bd01d77f23454b12b108fa269055d6f3699be74fb93d015","src/bindings/kotlin/templates/CustomTypeTemplate.kt":"d42eba4334c39749037d14ef9e2219a2e515479c18905df3f49534424317c848","src/bindings/kotlin/templates/DurationHelper.kt":"dfb45fe1b47bc04dd8c70cb98531c40606eca554791132ee6bed2846f8ee099c","src/bindings/kotlin/templates/EnumTemplate.kt":"7cefbb1e29d4e89420f6a95275bbab891984a56978cf4852a1e52bcc82afd9e8","src/bindings/kotlin/templates/ErrorTemplate.kt":"8f41de90753a42cfe33ba837997baa2954208b987e70cec13ecb4124faf25aa6","src/bindings/kotlin/templates/ExternalTypeTemplate.kt":"b1df8566d000431bfc3820a2e455426e810cba6d8683e77ab78ab0bb7d003720","src/bindings/kotlin/templates/FfiConverterTemplate.kt":"bc0bdbc99ee2459f50c84abf6c1bb236a6179eaf519f1c5f5b3f72d8184dc662","src/bindings/kotlin/templates/Float32Helper.kt":"789246343d34594fc39072c1a5393b848cecadb353659fc6e9080fc7e760fc21","src/bindings/kotlin/templates/Float64Helper.kt":"b87eac72da313b1d559b1738bba1c771f43bb7566fdbb3a34546dd56beeb5832","src/bindings/kotlin/templates/HandleMap.kt":"feb456ea4dfb2ad07331d49d606faf396737817c6f6712a2d9a9d843daebdc1e","src/bindings/kotlin/templates/Helpers.kt":"e7657732f44e8092d492ef291e3ce11aa803531d82be99645b8513c00dca99ac","src/bindings/kotlin/templates/Int16Helper.kt":"54bb1aefbcae1c3c10e0cdc6a9d45e070e3ca57c9ffa53b2d65e5c59808c9743","src/bindings/kotlin/templates/Int32Helper.kt":"49b3e5274d5c7853d227ec986d0a0c71621a448391b2c9aaf4351b86f310dadf","src/bindings/kotlin/templates/Int64Helper.kt":"264fd99a4109f0b2c40b806fc1a0181f27331346a02d94e398f1e34110e3414b","src/bindings/kotlin/templates/Int8Helper.kt":"a50c315d8474a212914f10f43ca7e75061bb73067e0de686b182891c6c7f1bc3","src/bindings/kotlin/templates/Interface.kt":"c66912069c3f61848bbee3d1886abbfa74895f759853f6b4a3c62cef5976766c","src/bindings/kotlin/templates/MapTemplate.kt":"f7e0360d3be74e543573bd56925bf25c6c22e6203aecc1cf519464704eeeb0ee","src/bindings/kotlin/templates/NamespaceLibraryTemplate.kt":"db4c30cfcb709c5413892cf3cf69391ba36c6160543274e8d1f2bedf9001d058","src/bindings/kotlin/templates/ObjectCleanerHelper.kt":"9ebcfcb3fe7788e93cf8cba30fd7470b363719e9ed25cdde43c95aebe1b90c2a","src/bindings/kotlin/templates/ObjectCleanerHelperAndroid.kt":"049e1e32a23b7923393e3dcabce49532737d44e9dbb331f62984ada67bde3125","src/bindings/kotlin/templates/ObjectCleanerHelperJvm.kt":"b6287f72afdb0ab9af5e56136c28e6a4f5e18a50305bce8923ee061b9406cfc3","src/bindings/kotlin/templates/ObjectTemplate.kt":"6a776feb36b0379c43e0013a26ba85cdef385aa1e59b4c2efa7a794140aa99bb","src/bindings/kotlin/templates/OptionalTemplate.kt":"918f2029e60710f4b048a77830b12b388c917af1a488c9f05f38323c58ee0f9e","src/bindings/kotlin/templates/README.md":"83587ff54a31fa47d2c0849cb5db52d6f079551e1cfb73c76c6dd02a7b164ad9","src/bindings/kotlin/templates/RecordTemplate.kt":"677bb63ae4fae9117e9c77928370a8911ab959c6b884c6af2ba4efc686c52721","src/bindings/kotlin/templates/RustBufferTemplate.kt":"b3b78b2c41cbfff6262d758f9ebe064e76d20841ec4db7705142449f7ffc75a9","src/bindings/kotlin/templates/SequenceTemplate.kt":"c1aa28ca87528c97c62656f850205023c2eb8d218264ef7b1e70207ab4f1b9b6","src/bindings/kotlin/templates/StringHelper.kt":"4e942e36af05dc823d5f28ab336c55ff86bf0f95bbb748399bcaa8ad291c7032","src/bindings/kotlin/templates/TimestampHelper.kt":"70137e78de18796996889e8d648f1e90830aa652a93a0b4639ff9f7ccb967a25","src/bindings/kotlin/templates/TopLevelFunctionTemplate.kt":"68c714cc8c7fa244166c5902a59c90317cdfc402193624cade405e3454f9bf67","src/bindings/kotlin/templates/Types.kt":"c725f7e57eda5b2d52c3c92b24f93d9321591e72c89d16973163b3b8d713b85b","src/bindings/kotlin/templates/UInt16Helper.kt":"ee96270f426933cfcd914894d4c7895544f7e3d4a7c24be78afc2896b46cbcbe","src/bindings/kotlin/templates/UInt32Helper.kt":"b2d7543098277e7b92502a0a6693dc25dd42e360f776b19987a48dd7fc6db7fd","src/bindings/kotlin/templates/UInt64Helper.kt":"fc855eb78a4b50d76fc53509dae8218c48a221db5bf73cf5368d755fb9aae478","src/bindings/kotlin/templates/UInt8Helper.kt":"af22d9e6f99fe9d8d7d5175cb03f7a9f62628c9dd939dbbfb5a4085359e52e0e","src/bindings/kotlin/templates/macros.kt":"0a221962503f6977b129eb3c1e3772e3e9d51cbab6d813c55b0387c24d784184","src/bindings/kotlin/templates/wrapper.kt":"a02028a86c620679602f26714c7feb4a306867cda1cba8240ca6e83d99cebd91","src/bindings/kotlin/test.rs":"28bf88a9e9aa9510adbe78005a2027a62818433f49426172046dc83a3ad41911","src/bindings/mod.rs":"949f323d6eb5c018497103dbb9dcffb8f395eb5960694b551a24b4887e853afb","src/bindings/python/gen_python/callback_interface.rs":"5df3e091d3c88ef7645e570f693942161a9b9c6307419c15a2534fbc5da974af","src/bindings/python/gen_python/compounds.rs":"4a83b02e11ae969ab360ba61df44d91dc790f372b5960b350b0b019a57d19de4","src/bindings/python/gen_python/custom.rs":"81501641648eb638f5a338c01a71db0d0e96601c3dda83acdb2d49072b387d42","src/bindings/python/gen_python/enum_.rs":"7c3f8f6a97c1491175c8b93b8f9ab13748e2f8084bb717836b6935d024805439","src/bindings/python/gen_python/error.rs":"161bd2e041e3a63a91899de173eec8450cc10e1e9552d064969aa72a02fdfd5e","src/bindings/python/gen_python/external.rs":"d7101124c22dd7837e227a7f1b683c57b92229a2cd5b25b06740f2fe3d76bed5","src/bindings/python/gen_python/miscellany.rs":"d6f6305dd0af85b7ba87b70cbe6ecba00c83d5082c5bdcaf25962fff853973ea","src/bindings/python/gen_python/mod.rs":"b8aac9a146551cd660f1cd310f8ef02e3bd4a11540a087551bbb7c7706b99e16","src/bindings/python/gen_python/object.rs":"a4d4c20a0a52687feff2b9a547a13aa9bda09b3af9ec26508646658a88eec8b3","src/bindings/python/gen_python/primitives.rs":"b830c68e20d8539b8ac5566f1ca0dd262c1b14712a747f79e70004cd8f409ba1","src/bindings/python/gen_python/record.rs":"f8e12ce43d7e0f37f05420a849e7867b7251f9790933609a4cb99050fd063089","src/bindings/python/mod.rs":"eac32ce383460d58d3ccf1d406173465fc8a1db8a24408df67620b7d14dcd0cd","src/bindings/python/templates/Async.py":"f1cf32d8e28b5e2fcbad6ccd00d03fd49f4b54eac47adcfe23cbf786d523eee7","src/bindings/python/templates/BooleanHelper.py":"cf7bcd414197258b0cfa54c6ad2aeb81a1a6a4a45af5b6aaf6f8e484bc5af59d","src/bindings/python/templates/BytesHelper.py":"8c39cf1760678316cf2b3903632f2bacae4f8aaa961b37eeb03e06e9f07241d1","src/bindings/python/templates/CallbackInterfaceImpl.py":"7dbb049ffebc3565ffb4605d53843c69f782f3e86472e060e3194be4986d328b","src/bindings/python/templates/CallbackInterfaceRuntime.py":"54dbda8a6ffe284ef2045da290a69d37974fed672eb57309c9fc7ac665969397","src/bindings/python/templates/CallbackInterfaceTemplate.py":"ef235bd7927592eb19a2db422352a435b7466595ef31e4822a16c3caa24cdda6","src/bindings/python/templates/CustomType.py":"4647a60dbe63ead2b23d07cf3a3a4a190a219d81357532364fd4afdf990d6e1b","src/bindings/python/templates/DurationHelper.py":"eb9278b546f79b71525ae61a5b30bfe4a1260fd2268c87c600d157bf9b0e2a44","src/bindings/python/templates/EnumTemplate.py":"49903d969b8b160d8f1a0747c803d5f54a6f000a6781493eacad1f6ca7811d7a","src/bindings/python/templates/ErrorTemplate.py":"d7af297596e5ef894e3fdaeb92bd6446843c987f8283c77973bd10fce537c9c1","src/bindings/python/templates/ExternalTemplate.py":"0cd36fc89f0a587dadfe0cb89c4d45a641822ba07cb9410299bdcd73ad3edb79","src/bindings/python/templates/Float32Helper.py":"4aa522163f121fcb84d2f024774d8dd9321c31f09b9a95da3a3131b6d2756971","src/bindings/python/templates/Float64Helper.py":"e7fa247fd9c3907b818f0d1ba28c2cee897e75fdd07fdacad1b8a2b5c26ba418","src/bindings/python/templates/HandleMap.py":"9dbfdcb4ddde5927fd9b9fb26b5194bc16b1d2280c2259895fd0ea443af4afd6","src/bindings/python/templates/Helpers.py":"09ddd46d6fcc6ee7e9b1c123b0830426c967f94e22ab18b3ee248b873f7d5ebc","src/bindings/python/templates/Int16Helper.py":"613345b35e63e7284caf97de9630747ec9cdadc8dd3f8451d2e878cb762958f5","src/bindings/python/templates/Int32Helper.py":"758b093b66dc0a8d3f0b13b9388d21f47de31b5e948689041c4d43ef98cf2c4f","src/bindings/python/templates/Int64Helper.py":"c7e76441ee14e78e856f8819f73243bc04b33ec16083ae7390e0ec27141855f2","src/bindings/python/templates/Int8Helper.py":"d963a76b218a32ea2b3bb26f265dbbc47e859b7d1bc939b43fd9b93c51a62292","src/bindings/python/templates/MapTemplate.py":"9dc81ebced353d0137ef6fe3187e170e3e72d32a3b5520dbbcc1f95354ebf62d","src/bindings/python/templates/NamespaceLibraryTemplate.py":"e480a80a27ed5e54a3ff9c72d3d6ab13343764da6c413d813c4bd72429139193","src/bindings/python/templates/ObjectTemplate.py":"976aa726baf36b53d1c319b262c34b8b2de2e414cb8d3c645ed3bf006833b9e8","src/bindings/python/templates/OptionalTemplate.py":"2629f3b46ff394df620bbff1699935e6844d9aa017e74ac43c0b38acd05f8d42","src/bindings/python/templates/Protocol.py":"8446fe51d7c9d16d7086694cee8016c6f571dc5c930fd18848fadcf109aa0566","src/bindings/python/templates/RecordTemplate.py":"c99d10cc061af339349bb0c7e8b67223fdcd9064362badc137a2ad0df17c57c0","src/bindings/python/templates/RustBufferHelper.py":"a48e5ed1dcde19993ae50bec9b881afa3bc6dd5f7d8257fd60214f2100224929","src/bindings/python/templates/RustBufferTemplate.py":"017f31fd5075306f5c8c2bd0e3a21ea965c694c0daf2523187ab076fc786e9ca","src/bindings/python/templates/SequenceTemplate.py":"1b262e5f546a1923de6968e0233cc621a5fae16062e9e6ac874c9b62d8f145df","src/bindings/python/templates/StringHelper.py":"b303b7fcbbc0981a28c6a7d0cc5bd90f8e9c8b8d572792e217a324b2bdb95dbd","src/bindings/python/templates/TimestampHelper.py":"b3da14de54822f44ada4459355c842550b944b3cd2a85a4eac0f59e82d646877","src/bindings/python/templates/TopLevelFunctionTemplate.py":"1d9da1b6ca2175b30f3277a46a1749590490e82bee6b990ff35efb04e5f102ef","src/bindings/python/templates/Types.py":"3653e2cf773493c6ddfd13ef298b0c7cb33fabc1dba495fca64b9287aae03042","src/bindings/python/templates/UInt16Helper.py":"8ffe4b69a5d4a2b3c5677ff1d8954efc67ab67713ffe297380e930e0379d493d","src/bindings/python/templates/UInt32Helper.py":"83f9603aceae05f2134c7183313ab0a1a8f64cabd8070ae19557494fe41dd6d2","src/bindings/python/templates/UInt64Helper.py":"97269025377a256e821e57991b07e17af05f4d1c4228e01fe5f243d784cb509d","src/bindings/python/templates/UInt8Helper.py":"4896723ed0ab8f5aef4a58d599e0a0dbd63d373f5740821c21b4b429b6a7afda","src/bindings/python/templates/macros.py":"d766feb4dedd2d0e4cd2052da7a69c0b074b97f880b857ee457faa43975230ed","src/bindings/python/templates/wrapper.py":"ab05168e3d01d1a26e9589cd9855d7776c46c59d699f1402a29dfae6eb9ebfbc","src/bindings/python/test.rs":"69d3ee230820f38d743438c8212e1bfc4e92f948d9e73548a38c093e164b2759","src/bindings/ruby/gen_ruby/mod.rs":"861be105f9001d4ad8f7b8ac4a303a95459ec7de7a0c2fdac14a083c43d5a07c","src/bindings/ruby/gen_ruby/tests.rs":"7dcb86b08e643c43503f4cac6396833497f6988b004321c0067700ee29ffbf32","src/bindings/ruby/mod.rs":"0fdfab5306dc5c05fbcbfb273340d96ad70c5caf5074834ad6851af1a9a56734","src/bindings/ruby/templates/EnumTemplate.rb":"5480edb347f5829e478d19474691babd72f37616ed846d519b5a61cb1d6cf047","src/bindings/ruby/templates/ErrorTemplate.rb":"301c177e639f0a27f19d4935c5317e672aadecbee2f9bfa778df982320f5148d","src/bindings/ruby/templates/Helpers.rb":"ce7ed4be97dad507b991c69c28dc7bb6427e5e79a4b2fba9dad9dccabc3e090c","src/bindings/ruby/templates/NamespaceLibraryTemplate.rb":"9a24c427b9eba99d9e13181a5559a385b5d1d16beae2b72a402f2645b22a9048","src/bindings/ruby/templates/ObjectTemplate.rb":"a1c0cc38865195d61df3540284f4756f1b6406b205d74e3855e7089d763b2791","src/bindings/ruby/templates/RecordTemplate.rb":"343a4b159cf298045747fb48f17552e3bf2c9775fa5b4fa40b424976dc67e33a","src/bindings/ruby/templates/RustBufferBuilder.rb":"a36d9183f3e66cbbb1c3e584b78ab86e01bd6b89a4a5ef9614c5df24dc383acc","src/bindings/ruby/templates/RustBufferStream.rb":"ab4fc736906e320fca56dca280daf40138ba443d957c42fbf5cfbf1c6acf463a","src/bindings/ruby/templates/RustBufferTemplate.rb":"de577fbae811f72e260270656f2c12ad7a4d157c78f97898d0cd4e309d92ad6a","src/bindings/ruby/templates/TopLevelFunctionTemplate.rb":"26c9c2d53853792270795bd822e41968e995375478d246f808f9935af77a7d6a","src/bindings/ruby/templates/macros.rb":"dc60ed79844b04fe828a24aef3550a6b6c30f7c0b66f03608d7c56725287ceed","src/bindings/ruby/templates/wrapper.rb":"f82b41543546f8e5804cd0e1785f4735d9dd95383566d0e5ba1cd4d9e8c0578d","src/bindings/ruby/test.rs":"027d62085498b20977f025117e1fb7c30923a189961d679823f16ca62a575d0d","src/bindings/swift/gen_swift/callback_interface.rs":"1a2b56d16db841574be0762d66b57fbaef0519273d45c47ca687bf656546f201","src/bindings/swift/gen_swift/compounds.rs":"d62206bdab8a2a65b19342933efad54c171f0f8c217b82ee8b41617043662fe5","src/bindings/swift/gen_swift/custom.rs":"bddb601b4ea8810ecbad01271d5ec0b3958999b09bc9382c83637dfd43451734","src/bindings/swift/gen_swift/enum_.rs":"87be67ec3394616368d9ef8e99b7f234c053b3bee9a7f9e6f2dff37f147c8837","src/bindings/swift/gen_swift/external.rs":"a1d34b688679a74b0ddcfcb1147a7064b53883d9df9c0670f950078516492ee7","src/bindings/swift/gen_swift/miscellany.rs":"7fc2444596d76545ad82ee6c4bed64a29dd4a0438d50bfaafe511f41f6a0e409","src/bindings/swift/gen_swift/mod.rs":"e6c12506217d0a5479e946998a24ee984e4ea4c4f19334cbd014f53504300181","src/bindings/swift/gen_swift/object.rs":"45a6d6bb053f3ef397ab8c6feba8d0e126a8d14cd87597d25015f97c6ffc3417","src/bindings/swift/gen_swift/primitives.rs":"26a29ea764988d9e021bbac6505ef45e49ae42426522d6e3822e949b6f0b589c","src/bindings/swift/gen_swift/record.rs":"5ad98ab04a5d8178daf0956db819c87d26aae7bf968184e88d512e34c02feb90","src/bindings/swift/mod.rs":"26ba270cb7913661f3cee703038d1ea4a70bff64c3b31351d6bc77e67cdee20d","src/bindings/swift/templates/Async.swift":"1645ac8dbea8575dec05acf0aeb18e210f76231c36ea0178b183e02a3ff6e18f","src/bindings/swift/templates/BooleanHelper.swift":"f02e391bed44ca0e03c66c4e6a1545caaae490fc72c4cf5935e66220082a8c30","src/bindings/swift/templates/BridgingHeaderTemplate.h":"4e1e91859c4fc6f40db32648645f046fb7e71841f44ae84737ea85bdecff7fa3","src/bindings/swift/templates/CallbackInterfaceImpl.swift":"514a0932c445e4040460da2969e4f21595e17b9b960eb23c6d1526e47dd56c51","src/bindings/swift/templates/CallbackInterfaceRuntime.swift":"a5def6b3b41698a42e6ccf5c85d365fe0abc7eff629d9f49d9d396ee90aad3a0","src/bindings/swift/templates/CallbackInterfaceTemplate.swift":"4dcab3e590f897499782aef3c657b9b838b312d8b49a018bf0f1ebde15ada786","src/bindings/swift/templates/CustomType.swift":"71520eb38a4be9035dca9e3e0402f386e7eaa79b28568bbc2f20d3fd53b4544d","src/bindings/swift/templates/DataHelper.swift":"df11547a2df57dcca0ff9cddc691bb5fa07d5ffd3d328d1c3b4443078008b111","src/bindings/swift/templates/DurationHelper.swift":"cbc41aaa58bda6c2313ede36a9f656a01a28f9c72aa1624e0e1c1da7b841ffb6","src/bindings/swift/templates/EnumTemplate.swift":"4b980f8bfe65266d27d561e88c7d79d87f426b35b4b842ef80c5d56841e2f672","src/bindings/swift/templates/ErrorTemplate.swift":"1233d119320a44dbf6099681595dda9bf5dd2a1474af4380b704bff0563c38ef","src/bindings/swift/templates/Float32Helper.swift":"ea32538058c4b3c72b1cd2530ac00d0349fadab5e1bc617d33aae4c87692fc98","src/bindings/swift/templates/Float64Helper.swift":"e27e9424dc6e97b8cacc6ca4c796dd2d16dcfcb877e2f19c45eca03381a41e78","src/bindings/swift/templates/HandleMap.swift":"acd2b06d678e64a573f7b842c7d08b87140ddb5d7146c0bf3401d99999399ec2","src/bindings/swift/templates/Helpers.swift":"491553eb82cdc5c944451a541d4e4655537cccb961f220783459b57b2311ca84","src/bindings/swift/templates/Int16Helper.swift":"204906911813a3931436057c23032f4c4e39e023df90d641d6c6086aefe2f820","src/bindings/swift/templates/Int32Helper.swift":"0997f059c9c4edd3c41aee0bbad4aa2bda6d791a0d623ad8014d5aa6bdae718d","src/bindings/swift/templates/Int64Helper.swift":"bcf8c2deebb3ee9bce87735adc4bd100981989943b69f6a7fb499a9aec4c25d9","src/bindings/swift/templates/Int8Helper.swift":"ad1ec0fa213724933fa4dc4e2e304e13ac4722b774bfffac44793986b997dd33","src/bindings/swift/templates/MapTemplate.swift":"53971ec388417b02519f8deb8d66361ab4693eae77d116f6051cbea4738054ec","src/bindings/swift/templates/ModuleMapTemplate.modulemap":"99ad1e9bf550a21497296f9248ecd4385dd6d0b5892951d24cf990cdbf3eec2c","src/bindings/swift/templates/ObjectTemplate.swift":"37e57815e60900ae48b953fe01e01535d4ab8076f6160fc93c37dd08fdee47a4","src/bindings/swift/templates/OptionalTemplate.swift":"2376487ceadca3975f0e82ddf6ce61af8bbbf5b0592fa9cd977460f148d8c99d","src/bindings/swift/templates/Protocol.swift":"2614b1378cadf14e7617fedd7367c227ac2a774d528acd3a42e44fd0c4f58528","src/bindings/swift/templates/RecordTemplate.swift":"f9f576b72fda9d1e1db34d1765ec6ec8206103a297329720c1c9a1f58ad085b5","src/bindings/swift/templates/RustBufferTemplate.swift":"89ed33846c0cfb220e823a1002238b16f006f3170d8de0dbbf7775d4f8143c31","src/bindings/swift/templates/SequenceTemplate.swift":"8425b279197582a94b4cf363ab0463907a68a624e24045720ef7df2bcacf3383","src/bindings/swift/templates/StringHelper.swift":"968b9b9b7fbe06a2ac2143016edaff3552e201652accb8d613b03645f0d24a90","src/bindings/swift/templates/TimestampHelper.swift":"82eece13aa186c8e3745c8ad2f1290639ca9689573018a2bdc5c75afbae58c26","src/bindings/swift/templates/TopLevelFunctionTemplate.swift":"7aa473a5b12ad7623f61d6c31f6879f269f51d2c4134dd899ce24c7b31ef35f1","src/bindings/swift/templates/Types.swift":"15e255e35e267f2aca49ed5a4fe16ef79520f4261433fd30c5e6c7f637a4d3f6","src/bindings/swift/templates/UInt16Helper.swift":"d6fba577324fc0e9e50329c968df99341de418011be126bd29702f8a94d87c02","src/bindings/swift/templates/UInt32Helper.swift":"5e0cf151a0c40098b3d96815ba3de23e15fe52f3c517577e1b0c7e7a4c12428f","src/bindings/swift/templates/UInt64Helper.swift":"17237b38d09ced8d2a8ff1ad9ca86873a19e417280e0e60f33d7063397ea4b7b","src/bindings/swift/templates/UInt8Helper.swift":"c4cb2ee4a78b54ca8d0013383c6b43e9ecd42776e3dc7d6e40086325d41714e5","src/bindings/swift/templates/macros.swift":"b30ffd93fe2213e13c3b9910bf2404403b4b231d4cd32c81e0f76c3bb4d151b5","src/bindings/swift/templates/wrapper.swift":"e553af470320391d150e6489eac549064689a37e5db6947914ce5609d0128031","src/bindings/swift/test.rs":"f55ba6c05c250093b26ae91404fd9200951462c1cd99e6b2718f7fb4ebcb7fbb","src/interface/callbacks.rs":"4a019376ec8fbaec495a9e3a1d5cb079af65767b6d85bc9f508f92a1e7f5344f","src/interface/enum_.rs":"7baee60e02cc7f751d7a941e877c10a6afaffea626e79897a0e8b17702f13c15","src/interface/ffi.rs":"6e1d493e49df96d75dab1926b0ced90479d50160e8e72d61d476b1e6c7d801cf","src/interface/function.rs":"be0f9f268e1947381fa235c5a0cf3c1965fd73121172d31f9c130acf539f2ac0","src/interface/mod.rs":"b97b11295b91691e7e6b7b023bba019729ad02f2204bba460c48acf62c5ee363","src/interface/object.rs":"d37d55edc62f52cf7fac4e3b8be1e46557dcbcfa8eb2e5998a91be2c6c062d92","src/interface/record.rs":"d8ddf873c35beaff45ab522bc4cb809c459a7937fd4061dae8c2db0db4c4edb4","src/interface/universe.rs":"76f368ff2b5326c517025a460405d343618bcc9fc9cfb28346313c8f7a335050","src/lib.rs":"2e3adccd5f0a3dacce6e533edfb5640ddee05e4f87ce8144cba859a14af219f6","src/library_mode.rs":"43ee55e4bb8d27dcec8a164961f22de941603d79d4e10c270ba9e7a751d92a1b","src/macro_metadata/ci.rs":"fa87ef42065c821aa89d3fb7938888c035ce6fc03bb3fce575a878c8e49012fb","src/macro_metadata/extract.rs":"7554c7b19b50d40e90bb503320311c2caa3b1e45e4376a9266ce32c0d48afffb","src/macro_metadata/mod.rs":"bcb5e9a015510e9d74c288da928a4bfb8d80926a8ff85227c0eae8cdb2605519","src/scaffolding/mod.rs":"66c3f2d9e81ded234fdd5b34cbb1da334cc271fa6ff3daa41b9acf9ac02f2194","src/scaffolding/templates/CallbackInterfaceTemplate.rs":"11acee064df46f7b5132401ae49c03c77f296bc04065085d6fd5c4ad6b628718","src/scaffolding/templates/Checksums.rs":"ee926e840875c2e48e1d0cc5185c11f7a1ed3bde5264b07540812cb13c1d7481","src/scaffolding/templates/EnumTemplate.rs":"305b8f0e6ec38300f0ae576a1bf1c576d0088d0df8d0b45818ad25f0216a7ac0","src/scaffolding/templates/ErrorTemplate.rs":"e6ec4e1d4c594d9f14a8dfe0a24103a66c0cc91d2129f0e1644775740f85bea1","src/scaffolding/templates/ExternalTypesTemplate.rs":"4c45cefca1774de3f3b650ce3b9a1b1b8fc10c62e0e48e54ac300748c32959f6","src/scaffolding/templates/ObjectTemplate.rs":"80689b74cbb426e6ce8bce77359b122d747b34b48d9a30aef44f93c9aa726fa7","src/scaffolding/templates/RecordTemplate.rs":"644177d86b52bf39c277b4e60a66f594b3fb0454f6b62837f9041297135c09c9","src/scaffolding/templates/ReexportUniFFIScaffolding.rs":"aa8a1ffa98b6033707d965f90b5709474ed6bc79486fb47dacae8417fc056cf8","src/scaffolding/templates/TopLevelFunctionTemplate.rs":"c11a688cafc2e21c3be105533b34c1f73eab55202936f7c8a97191d7e27f26e0","src/scaffolding/templates/UdlMetadata.rs":"d7c50af1de92ef85630b385a910c7b29875502d622eb90da5541a7012b93d9e2","src/scaffolding/templates/macros.rs":"ea6bacd8dd9116ad739bdafe893d70407050f35e4a7ac8dd2c78b8ef34263e8e","src/scaffolding/templates/scaffolding_template.rs":"c8e18306a73ec5b764f665660fc5c91d498b63b6c3f489e524b2bae50f81f231"},"package":"0be2bc6bafd82c979b0faca77c7b26630d54017de9f5bd5a686ec6ef038ad5d9"} \ No newline at end of file +{"files":{"Cargo.toml":"e134e3667a7a28594e4fa28cdce307b521129b3f1e813cade9baf45d79216b30","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","askama.toml":"1a245b7803adca782837e125c49100147d2de0d5a1c949ff95e91af1701f6058","src/backend/config.rs":"4861dbf251dbb10beb1ed7e3eea7d79499a0de1cd9ce9ee8381a0e729c097dea","src/backend/filters.rs":"8a818952896f9c5f438d6705bb28f56e77fbfce6d9757a2d74e1b3a925ed36e1","src/backend/mod.rs":"2ee9d974cd259f7fb156028b4f4f7601691e94fb5692a6daf0d362df3ecf79a8","src/backend/types.rs":"598df3a861f5d53b2c710848943f6049dd43cb4f37aa81f2c08fd36fc5b2f5d5","src/bindings/README.md":"1f367f507e5b76971662b960653b0e743d3baab174597b38ab731ad44fc2e1d0","src/bindings/kotlin/gen_kotlin/callback_interface.rs":"741100c2b4b484583d34408b276394078a24918c47101fbaa6233df9c4da32f2","src/bindings/kotlin/gen_kotlin/compounds.rs":"b40d1ab8c70d7da458ff45d2ce58efb6cc3b24bf560c093cbec7d0854d461dc4","src/bindings/kotlin/gen_kotlin/custom.rs":"196cec00121025f4254a357f9b17ef49747e3db2ac607bb30ce7c8ea0b7874eb","src/bindings/kotlin/gen_kotlin/enum_.rs":"6559bb00d8e359126b016e549263c0c9bc1dfc5654ed662c0c2912b47931b1e4","src/bindings/kotlin/gen_kotlin/external.rs":"38f42be67105b9a2ca5ecefec959e6659af728bedb9d107a51c595fe6ff5d332","src/bindings/kotlin/gen_kotlin/miscellany.rs":"6541987e627c4ff27a17ebe919b2b5cd97cb66ff41187ed636396b4e35ea2414","src/bindings/kotlin/gen_kotlin/mod.rs":"d2d38ca238ecf6b060ecc8f931f0994bda91e5e54cf7280a3f432686ffb59625","src/bindings/kotlin/gen_kotlin/object.rs":"1cb8d1f5eaf06ceaadb6d2cedca482fdd1502c24500ba270d8fcac48ef2f1231","src/bindings/kotlin/gen_kotlin/primitives.rs":"249896ec7d18f0f8d1d5dc8dc66ea6f3d0cc7b13344ab6892fb985f339d99b9f","src/bindings/kotlin/gen_kotlin/record.rs":"96fd1a180095a062b4a9b71d4f603b232f0133f46355a3e427c4064701d900f2","src/bindings/kotlin/gen_kotlin/variant.rs":"d111d6888745195fc2c24bdddc57359e771616102a8d182c5c8ad268b0a13460","src/bindings/kotlin/mod.rs":"eb150a18febf5f450ee81fa91404896e522443932c26efbf3f7f10291565f15b","src/bindings/kotlin/templates/Async.kt":"18236b9458121d417cabe1150832570b0054d964ff0c2ecdf53186f5921fb561","src/bindings/kotlin/templates/BooleanHelper.kt":"50d8a5109e2d2676f25a02772079efbaac61776a76e3e84eebd1fb13294842de","src/bindings/kotlin/templates/ByteArrayHelper.kt":"dc4aafffacb1fa8f3b4e15f714c13b8d715eec178c63bdba6260baf612dd80d8","src/bindings/kotlin/templates/CallbackInterfaceImpl.kt":"be4d5a5d3ed4f7b1d4c9822905c5732bdb8593c3dbf8d4aabab62291d7ccec99","src/bindings/kotlin/templates/CallbackInterfaceRuntime.kt":"76689c1bfa8aa7dc6e2c9e77c42212b9f317763fb35cd7704ca470675dd2648d","src/bindings/kotlin/templates/CallbackInterfaceTemplate.kt":"b497250899bfd0c79bd01d77f23454b12b108fa269055d6f3699be74fb93d015","src/bindings/kotlin/templates/CustomTypeTemplate.kt":"9d789ec02421ea4399e960ad11f0b75a698d0d284fa2d7e39111af546c1176b2","src/bindings/kotlin/templates/DurationHelper.kt":"dfb45fe1b47bc04dd8c70cb98531c40606eca554791132ee6bed2846f8ee099c","src/bindings/kotlin/templates/EnumTemplate.kt":"8f25204786a9c5a31ff1f12813ac2ce8fc281d5caa2ea705d92e5042f1b74a42","src/bindings/kotlin/templates/ErrorTemplate.kt":"f71d4950421d3e004a9c86f098b55923f4f532368f50ce8f97b5a5fca769ec59","src/bindings/kotlin/templates/ExternalTypeTemplate.kt":"b1df8566d000431bfc3820a2e455426e810cba6d8683e77ab78ab0bb7d003720","src/bindings/kotlin/templates/FfiConverterTemplate.kt":"bc0bdbc99ee2459f50c84abf6c1bb236a6179eaf519f1c5f5b3f72d8184dc662","src/bindings/kotlin/templates/Float32Helper.kt":"789246343d34594fc39072c1a5393b848cecadb353659fc6e9080fc7e760fc21","src/bindings/kotlin/templates/Float64Helper.kt":"b87eac72da313b1d559b1738bba1c771f43bb7566fdbb3a34546dd56beeb5832","src/bindings/kotlin/templates/HandleMap.kt":"feb456ea4dfb2ad07331d49d606faf396737817c6f6712a2d9a9d843daebdc1e","src/bindings/kotlin/templates/Helpers.kt":"e32d82eb9021327bd59954b12d57bb025f4eb10766e0fab784612621a1004bfd","src/bindings/kotlin/templates/Int16Helper.kt":"54bb1aefbcae1c3c10e0cdc6a9d45e070e3ca57c9ffa53b2d65e5c59808c9743","src/bindings/kotlin/templates/Int32Helper.kt":"49b3e5274d5c7853d227ec986d0a0c71621a448391b2c9aaf4351b86f310dadf","src/bindings/kotlin/templates/Int64Helper.kt":"264fd99a4109f0b2c40b806fc1a0181f27331346a02d94e398f1e34110e3414b","src/bindings/kotlin/templates/Int8Helper.kt":"a50c315d8474a212914f10f43ca7e75061bb73067e0de686b182891c6c7f1bc3","src/bindings/kotlin/templates/Interface.kt":"c66912069c3f61848bbee3d1886abbfa74895f759853f6b4a3c62cef5976766c","src/bindings/kotlin/templates/MapTemplate.kt":"f7e0360d3be74e543573bd56925bf25c6c22e6203aecc1cf519464704eeeb0ee","src/bindings/kotlin/templates/NamespaceLibraryTemplate.kt":"db4c30cfcb709c5413892cf3cf69391ba36c6160543274e8d1f2bedf9001d058","src/bindings/kotlin/templates/ObjectCleanerHelper.kt":"9ebcfcb3fe7788e93cf8cba30fd7470b363719e9ed25cdde43c95aebe1b90c2a","src/bindings/kotlin/templates/ObjectCleanerHelperAndroid.kt":"049e1e32a23b7923393e3dcabce49532737d44e9dbb331f62984ada67bde3125","src/bindings/kotlin/templates/ObjectCleanerHelperJvm.kt":"b6287f72afdb0ab9af5e56136c28e6a4f5e18a50305bce8923ee061b9406cfc3","src/bindings/kotlin/templates/ObjectTemplate.kt":"680519d5d293f7e97b5fde029452dd42eeb40d50b0867bbdc7ae3a460af2afe6","src/bindings/kotlin/templates/OptionalTemplate.kt":"918f2029e60710f4b048a77830b12b388c917af1a488c9f05f38323c58ee0f9e","src/bindings/kotlin/templates/README.md":"83587ff54a31fa47d2c0849cb5db52d6f079551e1cfb73c76c6dd02a7b164ad9","src/bindings/kotlin/templates/RecordTemplate.kt":"677bb63ae4fae9117e9c77928370a8911ab959c6b884c6af2ba4efc686c52721","src/bindings/kotlin/templates/RustBufferTemplate.kt":"b3b78b2c41cbfff6262d758f9ebe064e76d20841ec4db7705142449f7ffc75a9","src/bindings/kotlin/templates/SequenceTemplate.kt":"c1aa28ca87528c97c62656f850205023c2eb8d218264ef7b1e70207ab4f1b9b6","src/bindings/kotlin/templates/StringHelper.kt":"4e942e36af05dc823d5f28ab336c55ff86bf0f95bbb748399bcaa8ad291c7032","src/bindings/kotlin/templates/TimestampHelper.kt":"70137e78de18796996889e8d648f1e90830aa652a93a0b4639ff9f7ccb967a25","src/bindings/kotlin/templates/TopLevelFunctionTemplate.kt":"68c714cc8c7fa244166c5902a59c90317cdfc402193624cade405e3454f9bf67","src/bindings/kotlin/templates/Types.kt":"c725f7e57eda5b2d52c3c92b24f93d9321591e72c89d16973163b3b8d713b85b","src/bindings/kotlin/templates/UInt16Helper.kt":"ee96270f426933cfcd914894d4c7895544f7e3d4a7c24be78afc2896b46cbcbe","src/bindings/kotlin/templates/UInt32Helper.kt":"b2d7543098277e7b92502a0a6693dc25dd42e360f776b19987a48dd7fc6db7fd","src/bindings/kotlin/templates/UInt64Helper.kt":"fc855eb78a4b50d76fc53509dae8218c48a221db5bf73cf5368d755fb9aae478","src/bindings/kotlin/templates/UInt8Helper.kt":"af22d9e6f99fe9d8d7d5175cb03f7a9f62628c9dd939dbbfb5a4085359e52e0e","src/bindings/kotlin/templates/macros.kt":"fc077e6827002e5c494d3d8155737df6d5fe40db7f2079d503d48ffb558c4344","src/bindings/kotlin/templates/wrapper.kt":"a3b606341464b4a4d1255f3f867c3669f1551f946fb435d62eec81cf54488607","src/bindings/kotlin/test.rs":"2467320059934345f1b3835afa2ec1a6d8a5671a44fd2e56588f46543126a4e0","src/bindings/mod.rs":"1e2196888fa2543ab8ae16658cea95912d437cbce65d76039cbd3807e41a4fbf","src/bindings/python/gen_python/callback_interface.rs":"5df3e091d3c88ef7645e570f693942161a9b9c6307419c15a2534fbc5da974af","src/bindings/python/gen_python/compounds.rs":"4a83b02e11ae969ab360ba61df44d91dc790f372b5960b350b0b019a57d19de4","src/bindings/python/gen_python/custom.rs":"07ecbee6c5add6690e0f62899190a2991690e60cf3ed83085ac85fc287af0a25","src/bindings/python/gen_python/enum_.rs":"7c3f8f6a97c1491175c8b93b8f9ab13748e2f8084bb717836b6935d024805439","src/bindings/python/gen_python/error.rs":"161bd2e041e3a63a91899de173eec8450cc10e1e9552d064969aa72a02fdfd5e","src/bindings/python/gen_python/external.rs":"d7101124c22dd7837e227a7f1b683c57b92229a2cd5b25b06740f2fe3d76bed5","src/bindings/python/gen_python/miscellany.rs":"d6f6305dd0af85b7ba87b70cbe6ecba00c83d5082c5bdcaf25962fff853973ea","src/bindings/python/gen_python/mod.rs":"ef4c279dcb38e80c1319446c992423e2283b805a0451eb74e5a49cef82c84d8b","src/bindings/python/gen_python/object.rs":"a4d4c20a0a52687feff2b9a547a13aa9bda09b3af9ec26508646658a88eec8b3","src/bindings/python/gen_python/primitives.rs":"b830c68e20d8539b8ac5566f1ca0dd262c1b14712a747f79e70004cd8f409ba1","src/bindings/python/gen_python/record.rs":"f8e12ce43d7e0f37f05420a849e7867b7251f9790933609a4cb99050fd063089","src/bindings/python/mod.rs":"79816aa47d8377cdcdc571aebdf3c67bdd9723da4bf1431e9c0246d5a29c8874","src/bindings/python/templates/Async.py":"8efa90fcb9ed3d41cbd365300ed07597e5960ae632df7aa080fe9cfa3219935c","src/bindings/python/templates/BooleanHelper.py":"cf7bcd414197258b0cfa54c6ad2aeb81a1a6a4a45af5b6aaf6f8e484bc5af59d","src/bindings/python/templates/BytesHelper.py":"8c39cf1760678316cf2b3903632f2bacae4f8aaa961b37eeb03e06e9f07241d1","src/bindings/python/templates/CallbackInterfaceImpl.py":"26812d415f3379cedf82977f97a43d5e9c13d629950823f20378277f6bb16711","src/bindings/python/templates/CallbackInterfaceRuntime.py":"8ffe6640283b907cfea9432c7c077da5ce725d2def37c8d23faa4f5f784ed4d1","src/bindings/python/templates/CallbackInterfaceTemplate.py":"966403be166d18494c2f468552821a8044c40e8a9b0693dcb886e96b1bc5ac40","src/bindings/python/templates/CustomType.py":"9a5cc6c028dac9aceb562335c9ef6c34e20b1d5f876fe78a92bca28844b7ed2b","src/bindings/python/templates/DurationHelper.py":"eb9278b546f79b71525ae61a5b30bfe4a1260fd2268c87c600d157bf9b0e2a44","src/bindings/python/templates/EnumTemplate.py":"454d12456c57e5a7a56ce1eb37ffb4bd7090164815b301289eec4873bf6efea0","src/bindings/python/templates/ErrorTemplate.py":"4318581da6acd8f9edda7dc2ac59349c5390db8de44e1cd5abf244c346f503fc","src/bindings/python/templates/ExternalTemplate.py":"8def7e27a0c335493daa86e07a783e15c8dc7ec9631969e4ee255a672a7a67af","src/bindings/python/templates/Float32Helper.py":"4aa522163f121fcb84d2f024774d8dd9321c31f09b9a95da3a3131b6d2756971","src/bindings/python/templates/Float64Helper.py":"e7fa247fd9c3907b818f0d1ba28c2cee897e75fdd07fdacad1b8a2b5c26ba418","src/bindings/python/templates/HandleMap.py":"6e0ff44a6ca91a7fafd4f72c7f9ee4450d163abab245af191e7cb417755f345d","src/bindings/python/templates/Helpers.py":"8976196887d93f6c25a9025c3164c118b9a5ff17942b75d5467a1ca6c75542cb","src/bindings/python/templates/Int16Helper.py":"613345b35e63e7284caf97de9630747ec9cdadc8dd3f8451d2e878cb762958f5","src/bindings/python/templates/Int32Helper.py":"758b093b66dc0a8d3f0b13b9388d21f47de31b5e948689041c4d43ef98cf2c4f","src/bindings/python/templates/Int64Helper.py":"c7e76441ee14e78e856f8819f73243bc04b33ec16083ae7390e0ec27141855f2","src/bindings/python/templates/Int8Helper.py":"d963a76b218a32ea2b3bb26f265dbbc47e859b7d1bc939b43fd9b93c51a62292","src/bindings/python/templates/MapTemplate.py":"9dc81ebced353d0137ef6fe3187e170e3e72d32a3b5520dbbcc1f95354ebf62d","src/bindings/python/templates/NamespaceLibraryTemplate.py":"bbd9b1e5510a69f5b41c55a9bb1aaddb1317d70578737c21deca442a5c30df97","src/bindings/python/templates/ObjectTemplate.py":"aceffb45f449915b38a1012ff40890aca260cf3e40d040b6c92554928e2774b3","src/bindings/python/templates/OptionalTemplate.py":"2629f3b46ff394df620bbff1699935e6844d9aa017e74ac43c0b38acd05f8d42","src/bindings/python/templates/Protocol.py":"f5b528b7f05e42037dd48c9b47c87ddadecc2beb2682a37866c7bbd0f17fbfad","src/bindings/python/templates/README.md":"ff099a3019c7cd81d770ae4f72a4681ab165b296a03cc5c3f0405cce224f4145","src/bindings/python/templates/RecordTemplate.py":"36466c811da4146dedb86e2ba29c4b7c793b7302210a688047e4af9be4e73a46","src/bindings/python/templates/RustBufferHelper.py":"a48e5ed1dcde19993ae50bec9b881afa3bc6dd5f7d8257fd60214f2100224929","src/bindings/python/templates/RustBufferTemplate.py":"52763d122401d12b6cca40940915b1c955c1ca08f9078c371e3d789c4206ee28","src/bindings/python/templates/SequenceTemplate.py":"1b262e5f546a1923de6968e0233cc621a5fae16062e9e6ac874c9b62d8f145df","src/bindings/python/templates/StringHelper.py":"b303b7fcbbc0981a28c6a7d0cc5bd90f8e9c8b8d572792e217a324b2bdb95dbd","src/bindings/python/templates/TimestampHelper.py":"b3da14de54822f44ada4459355c842550b944b3cd2a85a4eac0f59e82d646877","src/bindings/python/templates/TopLevelFunctionTemplate.py":"4a710ea958b9ab66b8c35e0ac5e6bff36225a805ba0b476eacc9939f6495e061","src/bindings/python/templates/Types.py":"3de92c75852142637d27dfce68040719f1a5b47b544e27bfa312b31ca3c8ac44","src/bindings/python/templates/UInt16Helper.py":"8ffe4b69a5d4a2b3c5677ff1d8954efc67ab67713ffe297380e930e0379d493d","src/bindings/python/templates/UInt32Helper.py":"83f9603aceae05f2134c7183313ab0a1a8f64cabd8070ae19557494fe41dd6d2","src/bindings/python/templates/UInt64Helper.py":"97269025377a256e821e57991b07e17af05f4d1c4228e01fe5f243d784cb509d","src/bindings/python/templates/UInt8Helper.py":"4896723ed0ab8f5aef4a58d599e0a0dbd63d373f5740821c21b4b429b6a7afda","src/bindings/python/templates/macros.py":"cdafa7e5abe6348b603a0f3e840e600bc6c690bd34ccd04f6f072b88ce96fe9c","src/bindings/python/templates/wrapper.py":"891ce4fa9b0a9643ce03d4071d36a446ff8c7613d225642f3caf013b85abf7c1","src/bindings/python/test.rs":"bdb0ced3d5d59ca24ab3da7eb70532b5fec7e729d8cb1a1ac260d55c06cc3e2c","src/bindings/ruby/gen_ruby/mod.rs":"fa5df3c9731eb61b27e407fc3b5e894e00d4d1e5368c5f6b2b49f35f34b58184","src/bindings/ruby/gen_ruby/tests.rs":"7dcb86b08e643c43503f4cac6396833497f6988b004321c0067700ee29ffbf32","src/bindings/ruby/mod.rs":"076e101e21d35b5fb3af99a47acf0842aef61e9343c893c2bd4ae21c06f527ca","src/bindings/ruby/templates/EnumTemplate.rb":"5480edb347f5829e478d19474691babd72f37616ed846d519b5a61cb1d6cf047","src/bindings/ruby/templates/ErrorTemplate.rb":"301c177e639f0a27f19d4935c5317e672aadecbee2f9bfa778df982320f5148d","src/bindings/ruby/templates/Helpers.rb":"ce7ed4be97dad507b991c69c28dc7bb6427e5e79a4b2fba9dad9dccabc3e090c","src/bindings/ruby/templates/NamespaceLibraryTemplate.rb":"9a24c427b9eba99d9e13181a5559a385b5d1d16beae2b72a402f2645b22a9048","src/bindings/ruby/templates/ObjectTemplate.rb":"a1c0cc38865195d61df3540284f4756f1b6406b205d74e3855e7089d763b2791","src/bindings/ruby/templates/RecordTemplate.rb":"343a4b159cf298045747fb48f17552e3bf2c9775fa5b4fa40b424976dc67e33a","src/bindings/ruby/templates/RustBufferBuilder.rb":"a36d9183f3e66cbbb1c3e584b78ab86e01bd6b89a4a5ef9614c5df24dc383acc","src/bindings/ruby/templates/RustBufferStream.rb":"ab4fc736906e320fca56dca280daf40138ba443d957c42fbf5cfbf1c6acf463a","src/bindings/ruby/templates/RustBufferTemplate.rb":"de577fbae811f72e260270656f2c12ad7a4d157c78f97898d0cd4e309d92ad6a","src/bindings/ruby/templates/TopLevelFunctionTemplate.rb":"26c9c2d53853792270795bd822e41968e995375478d246f808f9935af77a7d6a","src/bindings/ruby/templates/macros.rb":"dc60ed79844b04fe828a24aef3550a6b6c30f7c0b66f03608d7c56725287ceed","src/bindings/ruby/templates/wrapper.rb":"f82b41543546f8e5804cd0e1785f4735d9dd95383566d0e5ba1cd4d9e8c0578d","src/bindings/ruby/test.rs":"05391718d4bb79c4e70413d8213cddc4b92f32741a98b3a9aaf258c3754681e3","src/bindings/swift/gen_swift/callback_interface.rs":"1a2b56d16db841574be0762d66b57fbaef0519273d45c47ca687bf656546f201","src/bindings/swift/gen_swift/compounds.rs":"d62206bdab8a2a65b19342933efad54c171f0f8c217b82ee8b41617043662fe5","src/bindings/swift/gen_swift/custom.rs":"e09c822956b883606d2abb496eb523a9c0b274d777952b2c57c34086a647007a","src/bindings/swift/gen_swift/enum_.rs":"87be67ec3394616368d9ef8e99b7f234c053b3bee9a7f9e6f2dff37f147c8837","src/bindings/swift/gen_swift/external.rs":"a1d34b688679a74b0ddcfcb1147a7064b53883d9df9c0670f950078516492ee7","src/bindings/swift/gen_swift/miscellany.rs":"7fc2444596d76545ad82ee6c4bed64a29dd4a0438d50bfaafe511f41f6a0e409","src/bindings/swift/gen_swift/mod.rs":"b903a3b98d1a3f43b3ef08413c3fbfec4243b80441882c8dca969a9858bb092b","src/bindings/swift/gen_swift/object.rs":"45a6d6bb053f3ef397ab8c6feba8d0e126a8d14cd87597d25015f97c6ffc3417","src/bindings/swift/gen_swift/primitives.rs":"26a29ea764988d9e021bbac6505ef45e49ae42426522d6e3822e949b6f0b589c","src/bindings/swift/gen_swift/record.rs":"5ad98ab04a5d8178daf0956db819c87d26aae7bf968184e88d512e34c02feb90","src/bindings/swift/mod.rs":"9ffe5f62539cbdb7167879226077f49436f043c0f4b54b36c98bc5c5e2b044c5","src/bindings/swift/templates/Async.swift":"90bff20496c6b1e0c65a32ae3cfe2f7a8448e858d9aa371a924dc66a106aceff","src/bindings/swift/templates/BooleanHelper.swift":"f02e391bed44ca0e03c66c4e6a1545caaae490fc72c4cf5935e66220082a8c30","src/bindings/swift/templates/BridgingHeaderTemplate.h":"4e1e91859c4fc6f40db32648645f046fb7e71841f44ae84737ea85bdecff7fa3","src/bindings/swift/templates/CallbackInterfaceImpl.swift":"514a0932c445e4040460da2969e4f21595e17b9b960eb23c6d1526e47dd56c51","src/bindings/swift/templates/CallbackInterfaceRuntime.swift":"a5def6b3b41698a42e6ccf5c85d365fe0abc7eff629d9f49d9d396ee90aad3a0","src/bindings/swift/templates/CallbackInterfaceTemplate.swift":"4dcab3e590f897499782aef3c657b9b838b312d8b49a018bf0f1ebde15ada786","src/bindings/swift/templates/CustomType.swift":"edd87b8de27a1407353532a4dfce34d5cdc7b5f6c63df507734a438947a13d89","src/bindings/swift/templates/DataHelper.swift":"df11547a2df57dcca0ff9cddc691bb5fa07d5ffd3d328d1c3b4443078008b111","src/bindings/swift/templates/DurationHelper.swift":"cbc41aaa58bda6c2313ede36a9f656a01a28f9c72aa1624e0e1c1da7b841ffb6","src/bindings/swift/templates/EnumTemplate.swift":"4b980f8bfe65266d27d561e88c7d79d87f426b35b4b842ef80c5d56841e2f672","src/bindings/swift/templates/ErrorTemplate.swift":"78c1f245721e79e1aec9ae3fa39810cc14d509f9f7929033317f22913ce351dc","src/bindings/swift/templates/Float32Helper.swift":"ea32538058c4b3c72b1cd2530ac00d0349fadab5e1bc617d33aae4c87692fc98","src/bindings/swift/templates/Float64Helper.swift":"e27e9424dc6e97b8cacc6ca4c796dd2d16dcfcb877e2f19c45eca03381a41e78","src/bindings/swift/templates/HandleMap.swift":"acd2b06d678e64a573f7b842c7d08b87140ddb5d7146c0bf3401d99999399ec2","src/bindings/swift/templates/Helpers.swift":"160c63bc61c50c5a8a008a2890b250eb5fb367013e9e125de0f4deceac77e25d","src/bindings/swift/templates/Int16Helper.swift":"204906911813a3931436057c23032f4c4e39e023df90d641d6c6086aefe2f820","src/bindings/swift/templates/Int32Helper.swift":"0997f059c9c4edd3c41aee0bbad4aa2bda6d791a0d623ad8014d5aa6bdae718d","src/bindings/swift/templates/Int64Helper.swift":"bcf8c2deebb3ee9bce87735adc4bd100981989943b69f6a7fb499a9aec4c25d9","src/bindings/swift/templates/Int8Helper.swift":"ad1ec0fa213724933fa4dc4e2e304e13ac4722b774bfffac44793986b997dd33","src/bindings/swift/templates/MapTemplate.swift":"53971ec388417b02519f8deb8d66361ab4693eae77d116f6051cbea4738054ec","src/bindings/swift/templates/ModuleMapTemplate.modulemap":"99ad1e9bf550a21497296f9248ecd4385dd6d0b5892951d24cf990cdbf3eec2c","src/bindings/swift/templates/ObjectTemplate.swift":"d437e3ac2feeb288513b74e09a2f13bd5a05e6e5efaccd0b60afcf19d1e72166","src/bindings/swift/templates/OptionalTemplate.swift":"2376487ceadca3975f0e82ddf6ce61af8bbbf5b0592fa9cd977460f148d8c99d","src/bindings/swift/templates/Protocol.swift":"2614b1378cadf14e7617fedd7367c227ac2a774d528acd3a42e44fd0c4f58528","src/bindings/swift/templates/RecordTemplate.swift":"f9f576b72fda9d1e1db34d1765ec6ec8206103a297329720c1c9a1f58ad085b5","src/bindings/swift/templates/RustBufferTemplate.swift":"208444d8ee43a55f7bbfc7ba8d7c11dd16dcc305a05604c708ce9573190e43b3","src/bindings/swift/templates/SequenceTemplate.swift":"8425b279197582a94b4cf363ab0463907a68a624e24045720ef7df2bcacf3383","src/bindings/swift/templates/StringHelper.swift":"968b9b9b7fbe06a2ac2143016edaff3552e201652accb8d613b03645f0d24a90","src/bindings/swift/templates/TimestampHelper.swift":"82eece13aa186c8e3745c8ad2f1290639ca9689573018a2bdc5c75afbae58c26","src/bindings/swift/templates/TopLevelFunctionTemplate.swift":"7aa473a5b12ad7623f61d6c31f6879f269f51d2c4134dd899ce24c7b31ef35f1","src/bindings/swift/templates/Types.swift":"15e255e35e267f2aca49ed5a4fe16ef79520f4261433fd30c5e6c7f637a4d3f6","src/bindings/swift/templates/UInt16Helper.swift":"d6fba577324fc0e9e50329c968df99341de418011be126bd29702f8a94d87c02","src/bindings/swift/templates/UInt32Helper.swift":"5e0cf151a0c40098b3d96815ba3de23e15fe52f3c517577e1b0c7e7a4c12428f","src/bindings/swift/templates/UInt64Helper.swift":"17237b38d09ced8d2a8ff1ad9ca86873a19e417280e0e60f33d7063397ea4b7b","src/bindings/swift/templates/UInt8Helper.swift":"c4cb2ee4a78b54ca8d0013383c6b43e9ecd42776e3dc7d6e40086325d41714e5","src/bindings/swift/templates/macros.swift":"b30ffd93fe2213e13c3b9910bf2404403b4b231d4cd32c81e0f76c3bb4d151b5","src/bindings/swift/templates/wrapper.swift":"4905b560e60cd89015b5c95bcf37fddcdaf76976291277fb3276fa5561b6bb3d","src/bindings/swift/test.rs":"c5835a90578846208dc2c7757b9a556394e90d299f59b99e3b71ee21ea134c5a","src/cargo_metadata.rs":"4c253acc633187a2252809e8712496bf0e1990e9dcaa0b16cb4a92db95b284f3","src/interface/callbacks.rs":"daf4e46c0fafd0691907e8923c8164d494685c16dc187271a4909937834d82d5","src/interface/enum_.rs":"4b458345ddaa102788a5acffdfb94735328e62e8453d154d0b35fc589bdd6fb2","src/interface/ffi.rs":"2c08894d8ff07fc4baffb3399d4835ae8c32fc860aa7661db60c7e81b8d79c49","src/interface/function.rs":"bdca8cb81cebcf2d1f06b5f3bb82447a258ddfaf0d08c6f3d299e622511e398b","src/interface/mod.rs":"944e80df6f70a33c2df3d6068f23a51786b6f3c669f61558fdec90b7211eb54c","src/interface/object.rs":"16893d49f2727a98406daaeddf87a7159eb24090ed9b78363f61ee530210c726","src/interface/record.rs":"d064b0cb529a8a912414d6bc425c16949450a710da040e7f78d34a9b431a5964","src/interface/universe.rs":"38bbae076e87e4d6dd9eca88f54be6f7f70a2937b487a69cf1fb2155252ba9f5","src/interface/visit_mut.rs":"ed304e9a174f48770939a89e4c477e3fa88719f79643a337bf861026087e2b68","src/lib.rs":"915fdece74f894376dbe3fbf84382abb94633402a3253f73bc17dec935ce87af","src/library_mode.rs":"75b3632e5e7117ab6aab00acd7c96c3c1bce2d2b2d450701cc5d48fb1452e21b","src/macro_metadata/ci.rs":"47150355cd37997c3f5ba95eefa14c21e612622013dfb978c5b5a7334b38ac9f","src/macro_metadata/extract.rs":"7554c7b19b50d40e90bb503320311c2caa3b1e45e4376a9266ce32c0d48afffb","src/macro_metadata/mod.rs":"bcb5e9a015510e9d74c288da928a4bfb8d80926a8ff85227c0eae8cdb2605519","src/scaffolding/mod.rs":"6bf4621bbfdf1dd82b8d7eebef48dbdf41a617bbd96dfb596a425a068a08a560","src/scaffolding/templates/CallbackInterfaceTemplate.rs":"11acee064df46f7b5132401ae49c03c77f296bc04065085d6fd5c4ad6b628718","src/scaffolding/templates/Checksums.rs":"ee926e840875c2e48e1d0cc5185c11f7a1ed3bde5264b07540812cb13c1d7481","src/scaffolding/templates/EnumTemplate.rs":"1a0d514da4932f657c068c0f225b776555e07e8af6aeb8923659d725539c1fd0","src/scaffolding/templates/ErrorTemplate.rs":"9c8aa912d21afa76d88ff1f4526d428d98d94856a0b267354341628e91bdbae3","src/scaffolding/templates/ExternalTypesTemplate.rs":"4c45cefca1774de3f3b650ce3b9a1b1b8fc10c62e0e48e54ac300748c32959f6","src/scaffolding/templates/ObjectTemplate.rs":"666a7834724b15b7ada77ec821e5ccc75e02e2cd1835a3d440f53382fc70247f","src/scaffolding/templates/RecordTemplate.rs":"77e14199fb49048d5efc08a14ffe0af6c240eeebc2d75b2bfd7f2c2bdf2cf139","src/scaffolding/templates/ReexportUniFFIScaffolding.rs":"aa8a1ffa98b6033707d965f90b5709474ed6bc79486fb47dacae8417fc056cf8","src/scaffolding/templates/TopLevelFunctionTemplate.rs":"c11a688cafc2e21c3be105533b34c1f73eab55202936f7c8a97191d7e27f26e0","src/scaffolding/templates/UdlMetadata.rs":"d7c50af1de92ef85630b385a910c7b29875502d622eb90da5541a7012b93d9e2","src/scaffolding/templates/macros.rs":"ea6bacd8dd9116ad739bdafe893d70407050f35e4a7ac8dd2c78b8ef34263e8e","src/scaffolding/templates/scaffolding_template.rs":"c8e18306a73ec5b764f665660fc5c91d498b63b6c3f489e524b2bae50f81f231"},"package":"7a112599c9556d1581e4a3d72019a74c2c3e122cc27f4af12577a429c4d5e614"} \ No newline at end of file diff --git a/third_party/rust/uniffi_bindgen/Cargo.toml b/third_party/rust/uniffi_bindgen/Cargo.toml index 6d1dba588cc2..2f7bf8996f81 100644 --- a/third_party/rust/uniffi_bindgen/Cargo.toml +++ b/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 "] 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"] diff --git a/third_party/rust/uniffi_bindgen/src/bindings/README.md b/third_party/rust/uniffi_bindgen/src/bindings/README.md new file mode 100644 index 000000000000..d4b0c1980caf --- /dev/null +++ b/third_party/rust/uniffi_bindgen/src/bindings/README.md @@ -0,0 +1 @@ +[See the section in the manual for into about the bindings](../../../docs/manual/src/internals/rendering_foreign_bindings.md) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/custom.rs b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/custom.rs index 137cd0d8d92f..f1b67e79ae16 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/custom.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/custom.rs @@ -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 { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs index c4fc8e0ed6af..92f2f39c330b 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/gen_kotlin/mod.rs @@ -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, - cdylib_name: Option, + pub(super) package_name: Option, + pub(super) cdylib_name: Option, generate_immutable_records: Option, #[serde(default)] custom_types: HashMap, #[serde(default)] - external_packages: HashMap, + pub(super) external_packages: HashMap, #[serde(default)] android: bool, #[serde(default)] android_cleaner: Option, + #[serde(default)] + kotlin_target_version: Option, } 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 { + let components = version + .split('.') + .map(|n| { + n.parse::() + .map_err(|_| anyhow!("Invalid version string ({n} is not an integer)")) + }) + .collect::>>()?; + + 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 { 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)); + } +} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/mod.rs index 466fe778792d..501f449da0fd 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/mod.rs @@ -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 { + 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>, + ) -> 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::::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], + ) -> 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 { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Async.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Async.kt index b28fbd2c80da..a65f635ddc4f 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Async.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Async.kt @@ -12,7 +12,7 @@ internal object uniffiRustFutureContinuationCallbackImpl: UniffiRustFutureContin } } -internal suspend fun uniffiRustCallAsync( +internal suspend fun uniffiRustCallAsync( rustFuture: Long, pollFunc: (Long, UniffiRustFutureContinuationCallback, Long) -> Unit, completeFunc: (Long, UniffiRustCallStatus) -> F, diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/CustomTypeTemplate.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/CustomTypeTemplate.kt index aeb5f58002ed..123535e5c80a 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/CustomTypeTemplate.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/CustomTypeTemplate.kt @@ -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) } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/EnumTemplate.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/EnumTemplate.kt index 8d1c2235ece5..1c1779963366 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/EnumTemplate.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/EnumTemplate.kt @@ -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) } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ErrorTemplate.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ErrorTemplate.kt index 4760c03fd6cf..8c08e765feb7 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ErrorTemplate.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ErrorTemplate.kt @@ -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 } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Helpers.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Helpers.kt index 1fdbd3ffc038..ca9d98189eba 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Helpers.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/Helpers.kt @@ -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 { @@ -46,15 +46,15 @@ interface UniffiRustCallStatusErrorHandler { // synchronize itself // Call a rust function that returns a Result<>. Pass in the Error class companion that corresponds to the Err -private inline fun uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler, callback: (UniffiRustCallStatus) -> U): U { - var status = UniffiRustCallStatus(); +private inline fun uniffiRustCallWithError(errorHandler: UniffiRustCallStatusErrorHandler, 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 uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler, status: UniffiRustCallStatus) { +private fun uniffiCheckCallStatus(errorHandler: UniffiRustCallStatusErrorHandler, status: UniffiRustCallStatus) { if (status.isSuccess()) { return } else if (status.isError()) { @@ -83,7 +83,7 @@ object UniffiNullRustCallStatusErrorHandler: UniffiRustCallStatusErrorHandler uniffiRustCall(callback: (UniffiRustCallStatus) -> U): U { - return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback); + return uniffiRustCallWithError(UniffiNullRustCallStatusErrorHandler, callback) } internal inline fun uniffiTraitInterfaceCall( @@ -93,7 +93,7 @@ internal inline fun 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 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) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt index 62cac7a4d012..72fdbe564895 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/ObjectTemplate.kt @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt index 7acfdc886125..b2f909ef3a76 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/macros.kt @@ -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) %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/wrapper.kt b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/wrapper.kt index 2cdc72a5e2ec..8cf8132d10cf 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/wrapper.kt +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/templates/wrapper.kt @@ -5,7 +5,7 @@ @file:Suppress("NAME_SHADOWING") -package {{ config.package_name() }}; +package {{ config.package_name() }} // Common helper code. // diff --git a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs index 082401575155..5c7f0c9943e5 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/kotlin/test.rs @@ -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, diff --git a/third_party/rust/uniffi_bindgen/src/bindings/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/mod.rs index d39202bcf274..2d6cdc07fbdd 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/mod.rs @@ -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 { - 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 { - match value.to_str() { - None => bail!("Unreadable target language"), - Some(s) => s.try_into(), - } - } -} - -impl TryFrom for TargetLanguage { - type Error = anyhow::Error; - fn try_from(value: String) -> Result { - 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(()) -} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/custom.rs b/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/custom.rs index f735899f3dd3..0818e7198b8d 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/custom.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/custom.rs @@ -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 { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/mod.rs index 6a10a38e7ffa..b831274963de 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/mod.rs @@ -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> = Lazy::new(|| { // Config options to customize the generated python. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct Config { - cdylib_name: Option, + pub(super) cdylib_name: Option, #[serde(default)] custom_types: HashMap, #[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 { +pub fn generate_python_bindings(config: &Config, ci: &mut ComponentInterface) -> Result { 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, } 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; } @@ -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 { + 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 { + Ok(PythonCodeOracle.class_name(nm)) + } + pub(super) fn ffi_converter_name(as_ct: &impl AsCodeType) -> Result { 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 { - Ok(PythonCodeOracle.class_name(nm)) - } - - /// Get the idiomatic Python rendering of a function name. - pub fn fn_name(nm: &str) -> Result { - Ok(PythonCodeOracle.fn_name(nm)) - } - - /// Get the idiomatic Python rendering of a variable name. - pub fn var_name(nm: &str) -> Result { - Ok(PythonCodeOracle.var_name(nm)) - } - - /// Get the idiomatic Python rendering of an individual enum variant. - pub fn enum_variant_py(nm: &str) -> Result { - 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 { Ok(PythonCodeOracle.ffi_callback_name(nm)) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/python/mod.rs index 4b9dc8f609ca..ca598baf56ef 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/mod.rs @@ -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 { + 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>, + ) -> 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], + ) -> 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(()) + } } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Async.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Async.py index 26daa9ba5cf8..c80ac0c3f99c 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Async.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Async.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceImpl.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceImpl.py index 676f01177a1c..1009505d635b 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceImpl.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceImpl.py @@ -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)) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceRuntime.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceRuntime.py index d802c90fdecf..12d5532b8f14 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceRuntime.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceRuntime.py @@ -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 diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceTemplate.py index a41e58e635c9..3966f6ce3734 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CallbackInterfaceTemplate.py @@ -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() diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CustomType.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CustomType.py index f75a85dc2756..898ecb28f280 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CustomType.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/CustomType.py @@ -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 diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/EnumTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/EnumTemplate.py index d07dd1c44adb..cfbf972603c1 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/EnumTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/EnumTemplate.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ErrorTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ErrorTemplate.py index 0911ff559a52..9d3b30831d92 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ErrorTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ErrorTemplate.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ExternalTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ExternalTemplate.py index 6c0cee85ef3a..26e4639e1957 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ExternalTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ExternalTemplate.py @@ -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) }} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/HandleMap.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/HandleMap.py index f7c13cf74553..2d6630fab03b 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/HandleMap.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/HandleMap.py @@ -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) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Helpers.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Helpers.py index 5d4bcbba8997..1b1d27840db0 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Helpers.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Helpers.py @@ -32,11 +32,11 @@ class _UniffiRustCallStatus(ctypes.Structure): else: return "_UniffiRustCallStatus()" -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: diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py index 1929f9aad6fe..e5d0eba42354 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py @@ -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) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py index 18dca4743ade..86029beea6e8 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/ObjectTemplate.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Protocol.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Protocol.py index 3b7e93596aca..8e5012ddd4f0 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Protocol.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Protocol.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/README.md b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/README.md new file mode 100644 index 000000000000..60df4168a6c3 --- /dev/null +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/README.md @@ -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. diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RecordTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RecordTemplate.py index 0b5634eb526e..d778b90ebdb2 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RecordTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RecordTemplate.py @@ -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 diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RustBufferTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RustBufferTemplate.py index 44e0ba1001b2..5005bd1147df 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RustBufferTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/RustBufferTemplate.py @@ -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( diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/TopLevelFunctionTemplate.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/TopLevelFunctionTemplate.py index 230b9e853f83..7a6cb6d7c226 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/TopLevelFunctionTemplate.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/TopLevelFunctionTemplate.py @@ -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) %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Types.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Types.py index 4aaed253e018..29f66fe88683 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Types.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/Types.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/macros.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/macros.py index 6818a8c10708..1a47226bd05c 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/macros.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/macros.py @@ -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 -%} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/wrapper.py b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/wrapper.py index 1ccd6821c00b..4380041ad8d8 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/templates/wrapper.py +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/templates/wrapper.py @@ -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 %} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/python/test.rs b/third_party/rust/uniffi_bindgen/src/bindings/python/test.rs index 0c23140b3326..39dbc9c1365b 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/python/test.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/python/test.rs @@ -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, diff --git a/third_party/rust/uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs index 04841b459c9f..7608acd7c2e3 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/ruby/gen_ruby/mod.rs @@ -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, + pub(super) cdylib_name: Option, cdylib_path: Option, } @@ -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> { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/ruby/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/ruby/mod.rs index 6db89b9f0bf2..e8f3c5f77c0d 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/ruby/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/ruby/mod.rs @@ -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 { + 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>, + ) -> 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], + ) -> 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 { use askama::Template; RubyWrapper::new(config.clone(), ci) diff --git a/third_party/rust/uniffi_bindgen/src/bindings/ruby/test.rs b/third_party/rust/uniffi_bindgen/src/bindings/ruby/test.rs index 88f770b9dc32..47a3b68401fc 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/ruby/test.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/ruby/test.rs @@ -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, diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/custom.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/custom.rs index f4591b6eb67d..54aad5adcd55 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/custom.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/custom.rs @@ -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 { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs index 16c162512367..c81495a8c631 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/mod.rs @@ -10,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, - module_name: Option, + pub(super) module_name: Option, ffi_module_name: Option, ffi_module_filename: Option, generate_module_map: Option, @@ -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 { @@ -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 { - Ok(oracle().ffi_canonical_name(ffi_type)) - } - pub fn ffi_default_value(return_type: Option) -> Result { 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 { - Ok(oracle().enum_variant_name(nm)) + /// Like enum_variant_swift_quoted, but a class name. + pub fn error_variant_swift_quoted(nm: &str) -> Result { + 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 { - 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 { - 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)) } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/mod.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/mod.rs index bf17f38a4ead..27d2bcf0a3fd 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/mod.rs @@ -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, } -/// 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 { + 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>, + ) -> 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], + ) -> 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(()) + } } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Async.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Async.swift index e16f3108e1b6..c26518783f8b 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Async.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Async.swift @@ -9,7 +9,7 @@ fileprivate func uniffiRustCallAsync( completeFunc: (UInt64, UnsafeMutablePointer) -> 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() diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/CustomType.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/CustomType.swift index 504cadfc1d56..2137ceff9cbf 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/CustomType.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/CustomType.swift @@ -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) } diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ErrorTemplate.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ErrorTemplate.swift index 0702c477e940..cd4953d8e3e8 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ErrorTemplate.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ErrorTemplate.swift @@ -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) + } +} diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Helpers.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Helpers.swift index cfddf7b3139f..842b7d287cdb 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Helpers.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/Helpers.swift @@ -53,18 +53,19 @@ fileprivate extension RustCallStatus { } private func rustCall(_ callback: (UnsafeMutablePointer) -> T) throws -> T { - try makeRustCall(callback, errorHandler: nil) + let neverThrow: ((RustBuffer) throws -> Never)? = nil + return try makeRustCall(callback, errorHandler: neverThrow) } -private func rustCallWithError( - _ errorHandler: @escaping (RustBuffer) throws -> Error, +private func rustCallWithError( + _ errorHandler: @escaping (RustBuffer) throws -> E, _ callback: (UnsafeMutablePointer) -> T) throws -> T { try makeRustCall(callback, errorHandler: errorHandler) } -private func makeRustCall( +private func makeRustCall( _ callback: (UnsafeMutablePointer) -> T, - errorHandler: ((RustBuffer) throws -> Error)? + errorHandler: ((RustBuffer) throws -> E)? ) throws -> T { uniffiEnsureInitialized() var callStatus = RustCallStatus.init() @@ -73,9 +74,9 @@ private func makeRustCall( return returnedVal } -private func uniffiCheckCallStatus( +private func uniffiCheckCallStatus( callStatus: RustCallStatus, - errorHandler: ((RustBuffer) throws -> Error)? + errorHandler: ((RustBuffer) throws -> E)? ) throws { switch callStatus.code { case CALL_SUCCESS: diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ObjectTemplate.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ObjectTemplate.swift index 0c28bc4c0959..7a41d4949925 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ObjectTemplate.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/ObjectTemplate.swift @@ -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 }} { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/RustBufferTemplate.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/RustBufferTemplate.swift index a053334a3022..cf8eec4019ce 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/RustBufferTemplate.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/RustBufferTemplate.swift @@ -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 diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/wrapper.swift b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/wrapper.swift index 17fdde74e07a..1f459b0b8924 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/wrapper.swift +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/templates/wrapper.swift @@ -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 { diff --git a/third_party/rust/uniffi_bindgen/src/bindings/swift/test.rs b/third_party/rust/uniffi_bindgen/src/bindings/swift/test.rs index 195a77696b9b..9a2a5a7de99f 100644 --- a/third_party/rust/uniffi_bindgen/src/bindings/swift/test.rs +++ b/third_party/rust/uniffi_bindgen/src/bindings/swift/test.rs @@ -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, 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 { + fn new( + crate_name: &str, + cdylib_path: &Utf8Path, + cargo_metadata: Metadata, + out_dir: &Utf8Path, + ) -> Result { 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}"), diff --git a/third_party/rust/uniffi_bindgen/src/cargo_metadata.rs b/third_party/rust/uniffi_bindgen/src/cargo_metadata.rs new file mode 100644 index 000000000000..e304025f8fd4 --- /dev/null +++ b/third_party/rust/uniffi_bindgen/src/cargo_metadata.rs @@ -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, +} + +impl BindgenCrateConfigSupplier for CrateConfigSupplier { + fn get_toml(&self, crate_name: &str) -> anyhow::Result> { + 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 { + 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 for CrateConfigSupplier { + fn from(metadata: Metadata) -> Self { + let paths: HashMap = 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 } + } +} diff --git a/third_party/rust/uniffi_bindgen/src/interface/callbacks.rs b/third_party/rust/uniffi_bindgen/src/interface/callbacks.rs index f176a7a684d1..b0e978e8b40a 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/callbacks.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/callbacks.rs @@ -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() } diff --git a/third_party/rust/uniffi_bindgen/src/interface/enum_.rs b/third_party/rust/uniffi_bindgen/src/interface/enum_.rs index a666cc3605fc..0d66ce2985e5 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/enum_.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/enum_.rs @@ -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, pub(super) variants: Vec, - // 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, @@ -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 { - // 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 for Enum { + type Error = anyhow::Error; + + fn try_from(meta: uniffi_meta::EnumMetadata) -> Result { Ok(Self { name: meta.name, module_path: meta.module_path, @@ -279,7 +267,7 @@ impl Enum { .into_iter() .map(TryInto::try_into) .collect::>()?, - 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::>(), @@ -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, }; diff --git a/third_party/rust/uniffi_bindgen/src/interface/ffi.rs b/third_party/rust/uniffi_bindgen/src/interface/ffi.rs index a1dc29713a64..c0c1d33603a7 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/ffi.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/ffi.rs @@ -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), + RustBuffer(Option), /// 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 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 for FfiDefinition { diff --git a/third_party/rust/uniffi_bindgen/src/interface/function.rs b/third_party/rust/uniffi_bindgen/src/interface/function.rs index 8effc4c87665..69f4f153dc9f 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/function.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/function.rs @@ -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 } diff --git a/third_party/rust/uniffi_bindgen/src/interface/mod.rs b/third_party/rust/uniffi_bindgen/src/interface/mod.rs index 90a941637a58..ec61f20cd736 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/mod.rs @@ -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, }", diff --git a/third_party/rust/uniffi_bindgen/src/interface/object.rs b/third_party/rust/uniffi_bindgen/src/interface/object.rs index 2b86e54a4513..2a9ee0b907a3 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/object.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/object.rs @@ -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 } diff --git a/third_party/rust/uniffi_bindgen/src/interface/record.rs b/third_party/rust/uniffi_bindgen/src/interface/record.rs index e9a600418968..3af6495c99de 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/record.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/record.rs @@ -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() } diff --git a/third_party/rust/uniffi_bindgen/src/interface/universe.rs b/third_party/rust/uniffi_bindgen/src/interface/universe.rs index 70bc61f8a9fa..9a78b3bf34d8 100644 --- a/third_party/rust/uniffi_bindgen/src/interface/universe.rs +++ b/third_party/rust/uniffi_bindgen/src/interface/universe.rs @@ -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, // Named type definitions (including aliases). - type_definitions: HashMap, + pub(super) type_definitions: HashMap, // All the types in the universe, by canonical type name, in a well-defined order. - all_known_types: BTreeSet, + pub(super) all_known_types: BTreeSet, } impl TypeUniverse { diff --git a/third_party/rust/uniffi_bindgen/src/interface/visit_mut.rs b/third_party/rust/uniffi_bindgen/src/interface/visit_mut.rs new file mode 100644 index 000000000000..31d03ae0fc45 --- /dev/null +++ b/third_party/rust/uniffi_bindgen/src/interface/visit_mut.rs @@ -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(&mut self, visitor: &V) { + for type_ in self.types.type_definitions.values_mut() { + visitor.visit_type(type_); + } + + let mut all_known_types_altered: BTreeSet = 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 = 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 = 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 = BTreeMap::new(); + + for record in self.records.values() { + new_records.insert(record.name().to_string(), record.clone()); + } + + self.records = new_records; + } +} diff --git a/third_party/rust/uniffi_bindgen/src/lib.rs b/third_party/rust/uniffi_bindgen/src/lib.rs index dfc90b32a6c1..6d32bd4784db 100644 --- a/third_party/rust/uniffi_bindgen/src/lib.rs +++ b/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, } /// 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; + + /// 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>, + ) -> 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], ) -> 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, - 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 { + 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> { + 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 { + 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) -> 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( 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::(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( - crate_root: &Utf8Path, +fn overridden_config_value( + mut config: toml::value::Table, config_file_override: Option<&Utf8Path>, -) -> Result { - let mut config = load_toml_file(Some(crate_root.join("uniffi.toml").as_path())) - .context("default config")? - .unwrap_or(toml::value::Table::default()); - +) -> Result { 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. diff --git a/third_party/rust/uniffi_bindgen/src/library_mode.rs b/third_party/rust/uniffi_bindgen/src/library_mode.rs index c460c03d9f48..3a6a3f0133e4 100644 --- a/third_party/rust/uniffi_bindgen/src/library_mode.rs +++ b/third_party/rust/uniffi_bindgen/src/library_mode.rs @@ -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( library_path: &Utf8Path, crate_name: Option, binding_generator: &T, + config_supplier: &dyn BindgenCrateConfigSupplier, config_file_override: Option<&Utf8Path>, out_dir: &Utf8Path, try_format_code: bool, -) -> Result>> { - generate_external_bindings( - binding_generator, - library_path, - crate_name.clone(), - config_file_override, - out_dir, +) -> Result>> { + 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::>>()?; + + 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( - binding_generator: &T, - library_path: &Utf8Path, - crate_name: Option, - config_file_override: Option<&Utf8Path>, - out_dir: &Utf8Path, - try_format_code: bool, -) -> Result>> { - 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 { - 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( - 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>> { + config_supplier: &dyn BindgenCrateConfigSupplier, +) -> Result>> { 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( let mut udl_items: HashMap = 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( 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::(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 { - 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> { let udl_items = group .items @@ -233,10 +156,9 @@ fn load_udl_metadata( _ => None, }) .collect::>(); + // 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}"), } } diff --git a/third_party/rust/uniffi_bindgen/src/macro_metadata/ci.rs b/third_party/rust/uniffi_bindgen/src/macro_metadata/ci.rs index 69fad1980e90..0b414a621300 100644 --- a/third_party/rust/uniffi_bindgen/src/macro_metadata/ci.rs +++ b/third_party/rust/uniffi_bindgen/src/macro_metadata/ci.rs @@ -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 { diff --git a/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs b/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs index 7fd81831aaf6..9c410cc71418 100644 --- a/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs +++ b/third_party/rust/uniffi_bindgen/src/scaffolding/mod.rs @@ -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".into(), - Type::Timestamp => "std::time::SystemTime".into(), - Type::Duration => "std::time::Duration".into(), + Type::String => "::std::string::String".into(), + Type::Bytes => "::std::vec::Vec".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"), 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)? ), diff --git a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/EnumTemplate.rs b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/EnumTemplate.rs index f918ef2f3a55..20b845d51577 100644 --- a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/EnumTemplate.rs +++ b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/EnumTemplate.rs @@ -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() }} { diff --git a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ErrorTemplate.rs b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ErrorTemplate.rs index 64f48e233497..2529c7342110 100644 --- a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ErrorTemplate.rs +++ b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ErrorTemplate.rs @@ -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() }} { diff --git a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs index e752878af59b..f307f243a67f 100644 --- a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs +++ b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs @@ -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() %} diff --git a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/RecordTemplate.rs b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/RecordTemplate.rs index a7affdf7b84a..c612dafda9b0 100644 --- a/third_party/rust/uniffi_bindgen/src/scaffolding/templates/RecordTemplate.rs +++ b/third_party/rust/uniffi_bindgen/src/scaffolding/templates/RecordTemplate.rs @@ -2,7 +2,7 @@ // Forward work to `uniffi_macros` This keeps macro-based and UDL-based generated code consistent. #} -#[::uniffi::derive_record_for_udl] +#[::uniffi::udl_derive(Record)] struct r#{{ rec.name() }} { {%- for field in rec.fields() %} r#{{ field.name() }}: {{ field.as_type().borrow()|type_rs }}, diff --git a/third_party/rust/uniffi_build/.cargo-checksum.json b/third_party/rust/uniffi_build/.cargo-checksum.json index 5d78ca9d12b6..80b4e23108a1 100644 --- a/third_party/rust/uniffi_build/.cargo-checksum.json +++ b/third_party/rust/uniffi_build/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"a79595948b5661477a6fd0506fa0abae05d83d3f0a4c31f16c20c143f6236b42","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/lib.rs":"47ff3d1a18456164414af1c20cd5df129401e5257cc15552ecc39afed8970707"},"package":"1c59b65d59685ff3a10569287c6419f76487b4052ac52d5a0df38b2253d7f440"} \ No newline at end of file +{"files":{"Cargo.toml":"763bda508967d37c11093b34fa3d0e07deb0be3490aeb2aeb29350536340b579","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/lib.rs":"47ff3d1a18456164414af1c20cd5df129401e5257cc15552ecc39afed8970707"},"package":"e2b12684401d2a8508ca9c72a95bbc45906417e42fc80942abaf033bbf01aa33"} \ No newline at end of file diff --git a/third_party/rust/uniffi_build/Cargo.toml b/third_party/rust/uniffi_build/Cargo.toml index 887e12147f3b..6bbba299e6f7 100644 --- a/third_party/rust/uniffi_build/Cargo.toml +++ b/third_party/rust/uniffi_build/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_build" -version = "0.27.3" +version = "0.28.1" authors = ["Firefox Sync Team "] description = "a multi-language bindings generator for rust (build script helpers)" homepage = "https://mozilla.github.io/uniffi-rs" @@ -32,7 +32,7 @@ version = "1" version = "1.0.8" [dependencies.uniffi_bindgen] -version = "=0.27.3" +version = "=0.28.1" default-features = false [features] diff --git a/third_party/rust/uniffi_checksum_derive/.cargo-checksum.json b/third_party/rust/uniffi_checksum_derive/.cargo-checksum.json index fd63879c29d0..ddeb0fa975e0 100644 --- a/third_party/rust/uniffi_checksum_derive/.cargo-checksum.json +++ b/third_party/rust/uniffi_checksum_derive/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"efec1e1624f962fd264a0003ac8d40311c4af50f69d7ed537119ca74c73255a0","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/lib.rs":"44d2e2c595b14d33d16c71dfe4ef42ad0b9e010a878ee2ec49c2e929d60275ba"},"package":"d5c400339a9d1d17be34257d0b407e91d64af335e5b4fa49f4bf28467fc8d635"} \ No newline at end of file +{"files":{"Cargo.toml":"c9e328229de29d28389e431f6a5a5a4f43ab00bb0389163875939806bef20dcf","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/lib.rs":"3301ac9be2750c348f677c1fcf721daa37945901434d6cd6958d7926c987e4ea"},"package":"a22dbe67c1c957ac6e7611bdf605a6218aa86b0eebeb8be58b70ae85ad7d73dc"} \ No newline at end of file diff --git a/third_party/rust/uniffi_checksum_derive/Cargo.toml b/third_party/rust/uniffi_checksum_derive/Cargo.toml index 95f1fdf295cc..38c7bbbf8363 100644 --- a/third_party/rust/uniffi_checksum_derive/Cargo.toml +++ b/third_party/rust/uniffi_checksum_derive/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_checksum_derive" -version = "0.27.3" +version = "0.28.1" authors = ["Firefox Sync Team "] description = "a multi-language bindings generator for rust (checksum custom derive)" homepage = "https://mozilla.github.io/uniffi-rs" diff --git a/third_party/rust/uniffi_checksum_derive/src/lib.rs b/third_party/rust/uniffi_checksum_derive/src/lib.rs index e600982d083a..449183dedf86 100644 --- a/third_party/rust/uniffi_checksum_derive/src/lib.rs +++ b/third_party/rust/uniffi_checksum_derive/src/lib.rs @@ -108,14 +108,13 @@ pub fn checksum_derive(input: TokenStream) -> TokenStream { .fields .iter() .enumerate() - .filter_map(|(num, field)| { - (!has_ignore_attribute(&field.attrs)).then(|| match field.ident.as_ref() { - Some(ident) => quote! { Checksum::checksum(&self.#ident, state); }, - None => { - let i = Index::from(num); - quote! { Checksum::checksum(&self.#i, state); } - } - }) + .filter(|&(_num, field)| (!has_ignore_attribute(&field.attrs))) + .map(|(num, field)| match field.ident.as_ref() { + Some(ident) => quote! { Checksum::checksum(&self.#ident, state); }, + None => { + let i = Index::from(num); + quote! { Checksum::checksum(&self.#i, state); } + } }); quote! { #(#stmts)* diff --git a/third_party/rust/uniffi_core/.cargo-checksum.json b/third_party/rust/uniffi_core/.cargo-checksum.json index 2eb3e1abf803..8e390f6cec3c 100644 --- a/third_party/rust/uniffi_core/.cargo-checksum.json +++ b/third_party/rust/uniffi_core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"c2bc10be9bffda0a1b9ea884f39d6499fc5b4bc8acb32ec33842c67c8ad72305","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","release.toml":"b150796411fc6ff90b481218cb50f8ac7c07f5845aebdb8e17877d47e55b05b9","src/ffi/callbackinterface.rs":"f0184cf76bd86abb2815d260a87f85bd7060f5373ac6ef6f71955ece2a5075af","src/ffi/ffidefault.rs":"0db83fbcbc274c4c0daf7fb27833400568839b77a3496155840734c511d801e0","src/ffi/ffiserialize.rs":"d34312d09d8851c0fc356990d9f3a8a488ea9f6ab089901b1d0c42180ad06be4","src/ffi/foreignbytes.rs":"d2b46e1a6317aa64801b855e0d12af6bcdef118d8036603d11c3cdaf6f35fdfe","src/ffi/foreigncallbacks.rs":"2b820a34b78705f5debc302a25c64d515a4aa7b3bdade083f4c1cfa2803664ae","src/ffi/foreignfuture.rs":"673a7a44d27b88d5297dc6f2da507c9db4d22e6306d9ebc5439cba9c6720cbcb","src/ffi/handle.rs":"91f91469a81cb19edebb8bba433df62658cc66f6b54d5dc8520eb5793a85abd9","src/ffi/mod.rs":"e4d46229ccda04fa42496cb72b09d57936311a1ac1d82343293613e708644494","src/ffi/rustbuffer.rs":"9df75f156dc8ea9565ae320654cc8caab899e688e5414da4e4a43dfe74db9522","src/ffi/rustcalls.rs":"9754b01988983b47d8f0ef6d4e5675cee92ec4ddeb073236b9ccfcac2b12e3ca","src/ffi/rustfuture/future.rs":"426cd0ad3c8cf008a7052a7d89856b6c6d5053b94e24325f5666d0281a40ec7f","src/ffi/rustfuture/mod.rs":"44568267e591f5b37f77acfdd6e60ae55ce48ab0a17fd81af3aeb31baa3d53e6","src/ffi/rustfuture/scheduler.rs":"c6484fff14c04596df5f306f2090366435dcff92561d317fde1ea9c097a9576b","src/ffi/rustfuture/tests.rs":"211241fb484a3a103eb0418e7d295850ea021bcd583fa1488f5efc68f33d5ab8","src/ffi_converter_impls.rs":"397c813f2e765462d7a7be524e6ac75e813a91a8ffd11c7e7df05f853213f77b","src/ffi_converter_traits.rs":"24c8cf6ada9b2f63b265e62c0f9092d640e533d0d7234e9156f92c3d1902f430","src/lib.rs":"477a833a1e41b9e07f3a6f052c6b7f48d11930449ff22b5ff949c7eeaa3e80b9","src/metadata.rs":"83e463c377c0f501e58ac4eb5cc47c433c1473cecd47305fa89283e736b48d96","src/oneshot.rs":"8f1b7e87cc139d274cacef1a7ad6a9e9bf85423a140ad4e5b61e38be9c6e7bb6","src/panichook.rs":"9f49c7994a8e5489c1105c488bb3f8c5571bc5f813e7be90441eca15da5c9851"},"package":"a02e67ac9634b10da9e4aa63a29a7920b8f1395eafef1ea659b2dd76dda96906"} \ No newline at end of file +{"files":{"Cargo.toml":"842de64a0478e2872d4ac3f210580eecb832ce32c6c025eb7972ae5956d2ce83","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","release.toml":"b150796411fc6ff90b481218cb50f8ac7c07f5845aebdb8e17877d47e55b05b9","src/ffi/callbackinterface.rs":"ea6ffe37f743d8fc9d0286754bd19950b6c0168796a52686f07f1b7fe0ebf0f4","src/ffi/ffidefault.rs":"0db83fbcbc274c4c0daf7fb27833400568839b77a3496155840734c511d801e0","src/ffi/ffiserialize.rs":"f982b42730aeed292d03d2ec6cc10170619511805170180e6db37121b468b6ab","src/ffi/foreignbytes.rs":"d2b46e1a6317aa64801b855e0d12af6bcdef118d8036603d11c3cdaf6f35fdfe","src/ffi/foreigncallbacks.rs":"2b820a34b78705f5debc302a25c64d515a4aa7b3bdade083f4c1cfa2803664ae","src/ffi/foreignfuture.rs":"5c4a43d28831987dd108a863fcee166c85d7342304b435bdd0763919aad763fe","src/ffi/handle.rs":"466935e92bd15f63e594c47f862e9173be92ad765c1f7b283c1e7dcb5d2e20f2","src/ffi/mod.rs":"e4d46229ccda04fa42496cb72b09d57936311a1ac1d82343293613e708644494","src/ffi/rustbuffer.rs":"81b8fcc2f35098265e6137456030161abea40c33168b3cd8418609a1ae547854","src/ffi/rustcalls.rs":"8fd22eabe5a3a68dbfda43ce2739b13ece7d3c5c5cabdf4ecf820a89f155071a","src/ffi/rustfuture/future.rs":"1822ea14a3dff99a1621cf6a575b7a0c994e160911d0d1b869bdd5a9e35f97f5","src/ffi/rustfuture/mod.rs":"cbc5bac1b19745c4361df38dffe50599108abef5ca0f75b235194019a80d53fd","src/ffi/rustfuture/scheduler.rs":"c6484fff14c04596df5f306f2090366435dcff92561d317fde1ea9c097a9576b","src/ffi/rustfuture/tests.rs":"9815a87c01020b23bf9e668873f2b31aa4c0b3a01275fffcb934957883d4af4e","src/ffi_converter_impls.rs":"6454294f83e891b7e3c668ecde83d4b872def12bd6ea165b4594c63bcaf26389","src/ffi_converter_traits.rs":"6de4c0f4574a7a58a040bfc38b6b4d4e5a15209885f745295a338a497caefcb1","src/lib.rs":"0516914f329451e0c946d830afcfdaa9ecf640d8aa5ceed5784fec1faf994f5c","src/metadata.rs":"8766429c98246224bfddbcfc155d11057b2d2660393717dadd9839ebaf2b4f65","src/oneshot.rs":"8f1b7e87cc139d274cacef1a7ad6a9e9bf85423a140ad4e5b61e38be9c6e7bb6","src/panichook.rs":"9f49c7994a8e5489c1105c488bb3f8c5571bc5f813e7be90441eca15da5c9851"},"package":"5a0c35aaad30e3a9e6d4fe34e358d64dbc92ee09045b48591b05fc9f12e0905b"} \ No newline at end of file diff --git a/third_party/rust/uniffi_core/Cargo.toml b/third_party/rust/uniffi_core/Cargo.toml index dcc0afb9f278..340a5175a050 100644 --- a/third_party/rust/uniffi_core/Cargo.toml +++ b/third_party/rust/uniffi_core/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_core" -version = "0.27.3" +version = "0.28.1" authors = ["Firefox Sync Team "] description = "a multi-language bindings generator for rust (runtime support code)" homepage = "https://mozilla.github.io/uniffi-rs" diff --git a/third_party/rust/uniffi_core/src/ffi/callbackinterface.rs b/third_party/rust/uniffi_core/src/ffi/callbackinterface.rs index e7a4faab64b0..33db6f09285d 100644 --- a/third_party/rust/uniffi_core/src/ffi/callbackinterface.rs +++ b/third_party/rust/uniffi_core/src/ffi/callbackinterface.rs @@ -195,7 +195,7 @@ macro_rules! convert_unexpected_error { fn get_converter(&self) -> $crate::UnexpectedUniFFICallbackErrorConverterSpecialized; } - impl> GetConverterSpecialized for T { + impl> GetConverterSpecialized for T { fn get_converter(&self) -> $crate::UnexpectedUniFFICallbackErrorConverterSpecialized { $crate::UnexpectedUniFFICallbackErrorConverterSpecialized } diff --git a/third_party/rust/uniffi_core/src/ffi/ffiserialize.rs b/third_party/rust/uniffi_core/src/ffi/ffiserialize.rs index 570ebd5b11d1..edbeb512293b 100644 --- a/third_party/rust/uniffi_core/src/ffi/ffiserialize.rs +++ b/third_party/rust/uniffi_core/src/ffi/ffiserialize.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::{Handle, RustBuffer, RustCallStatus, RustCallStatusCode}; -use std::{mem::MaybeUninit, ptr::NonNull}; +use std::{mem::ManuallyDrop, ptr::NonNull}; /// FFIBuffer element /// @@ -81,7 +81,7 @@ pub trait FfiSerialize: Sized { fn write(buf: &mut &mut [FfiBufferElement], value: Self) { Self::put(buf, value); // Lifetime dance taken from `bytes::BufMut` - let (_, new_buf) = core::mem::take(buf).split_at_mut(Self::SIZE); + let (_, new_buf) = ::core::mem::take(buf).split_at_mut(Self::SIZE); *buf = new_buf; } } @@ -228,15 +228,13 @@ impl FfiSerialize for RustCallStatus { let code = unsafe { buf[0].i8 }; Self { code: RustCallStatusCode::try_from(code).unwrap_or(RustCallStatusCode::UnexpectedError), - error_buf: MaybeUninit::new(RustBuffer::get(&buf[1..])), + error_buf: ManuallyDrop::new(RustBuffer::get(&buf[1..])), } } fn put(buf: &mut [FfiBufferElement], value: Self) { buf[0].i8 = value.code as i8; - // Safety: This is okay even if the error buf is not initialized. It just means we'll be - // copying the garbage data. - unsafe { RustBuffer::put(&mut buf[1..], value.error_buf.assume_init()) } + RustBuffer::put(&mut buf[1..], ManuallyDrop::into_inner(value.error_buf)) } } @@ -277,9 +275,9 @@ mod test { rust_buffer.len(), rust_buffer.capacity(), ); - let handle = Handle::from_raw(101).unwrap(); - let rust_call_status = RustCallStatus::new(); - let rust_call_status_error_buf = unsafe { rust_call_status.error_buf.assume_init_ref() }; + let handle = unsafe { Handle::from_raw(101).unwrap() }; + let rust_call_status = RustCallStatus::default(); + let rust_call_status_error_buf = &rust_call_status.error_buf; let orig_rust_call_status_buffer_data = ( rust_call_status_error_buf.data_pointer(), rust_call_status_error_buf.len(), @@ -302,7 +300,6 @@ mod test { ::write(&mut buf_writer, rust_buffer); ::write(&mut buf_writer, rust_call_status); ::write(&mut buf_writer, handle); - #[allow(unknown_lints)] #[allow(clippy::needless_borrows_for_generic_args)] <() as FfiSerialize>::write(&mut buf_writer, ()); @@ -335,7 +332,7 @@ mod test { let rust_call_status2 = ::read(&mut buf_reader); assert_eq!(rust_call_status2.code, RustCallStatusCode::Success); - let rust_call_status2_error_buf = unsafe { rust_call_status2.error_buf.assume_init() }; + let rust_call_status2_error_buf = ManuallyDrop::into_inner(rust_call_status2.error_buf); assert_eq!( ( rust_call_status2_error_buf.data_pointer(), diff --git a/third_party/rust/uniffi_core/src/ffi/foreignfuture.rs b/third_party/rust/uniffi_core/src/ffi/foreignfuture.rs index 87d8b9a4e722..804beaef62e0 100644 --- a/third_party/rust/uniffi_core/src/ffi/foreignfuture.rs +++ b/third_party/rust/uniffi_core/src/ffi/foreignfuture.rs @@ -147,7 +147,7 @@ mod test { *data, ForeignFutureResult { return_value: >::lower(value), - call_status: RustCallStatus::new(), + call_status: RustCallStatus::default(), }, ); } diff --git a/third_party/rust/uniffi_core/src/ffi/handle.rs b/third_party/rust/uniffi_core/src/ffi/handle.rs index 8ee2f46c359d..8ca66a41ded7 100644 --- a/third_party/rust/uniffi_core/src/ffi/handle.rs +++ b/third_party/rust/uniffi_core/src/ffi/handle.rs @@ -12,7 +12,7 @@ /// For all currently supported architectures and hopefully any ones we add in the future: /// * 0 is an invalid value. /// * The lowest bit will always be set for foreign handles and never set for Rust ones (since the -/// leaked pointer will be aligned). +/// leaked pointer will be aligned to `size_of::>()` == `size_of::<*const T>()`). /// /// Rust handles are mainly managed is through the [crate::HandleAlloc] trait. #[derive(Copy, Clone, Default, Debug, PartialEq, Eq)] @@ -28,7 +28,9 @@ impl Handle { self.0 as *const T } - pub fn from_raw(raw: u64) -> Option { + /// # Safety + /// The raw value must be a valid handle as described above. + pub unsafe fn from_raw(raw: u64) -> Option { if raw == 0 { None } else { diff --git a/third_party/rust/uniffi_core/src/ffi/rustbuffer.rs b/third_party/rust/uniffi_core/src/ffi/rustbuffer.rs index 72e94faaa590..9c718aa6117b 100644 --- a/third_party/rust/uniffi_core/src/ffi/rustbuffer.rs +++ b/third_party/rust/uniffi_core/src/ffi/rustbuffer.rs @@ -78,13 +78,10 @@ impl RustBuffer { /// Creates a `RustBuffer` from its constituent fields. /// - /// This is intended mainly as an internal convenience function and should not - /// be used outside of this module. - /// /// # Safety /// /// You must ensure that the raw parts uphold the documented invariants of this class. - pub unsafe fn from_raw_parts(data: *mut u8, len: u64, capacity: u64) -> Self { + pub(crate) unsafe fn from_raw_parts(data: *mut u8, len: u64, capacity: u64) -> Self { Self { capacity, len, @@ -94,7 +91,7 @@ impl RustBuffer { /// Get the current length of the buffer, as a `usize`. /// - /// This is mostly a helper function to convert the `i32` length field + /// This is mostly a helper function to convert the `u64` length field /// into a `usize`, which is what Rust code usually expects. /// /// # Panics @@ -130,7 +127,7 @@ impl RustBuffer { /// /// # Panics /// - /// Panics if the requested size is too large to fit in an `i32`, and + /// Panics if the requested size is too large to fit in an `u64`, and /// hence would risk incompatibility with some foreign-language code. pub fn new_with_size(size: u64) -> Self { Self::from_vec(vec![0u8; size as usize]) @@ -143,7 +140,7 @@ impl RustBuffer { /// /// # Panics /// - /// Panics if the vector's length or capacity are too large to fit in an `i32`, + /// Panics if the vector's length or capacity are too large to fit in an `u64`, /// and hence would risk incompatibility with some foreign-language code. pub fn from_vec(v: Vec) -> Self { let capacity = u64::try_from(v.capacity()).expect("buffer capacity cannot fit into a u64."); diff --git a/third_party/rust/uniffi_core/src/ffi/rustcalls.rs b/third_party/rust/uniffi_core/src/ffi/rustcalls.rs index 91d3fe24726d..c4cd1ac03a20 100644 --- a/third_party/rust/uniffi_core/src/ffi/rustcalls.rs +++ b/third_party/rust/uniffi_core/src/ffi/rustcalls.rs @@ -12,7 +12,7 @@ //! exception use crate::{FfiDefault, Lower, RustBuffer, UniFfiTag}; -use std::mem::MaybeUninit; +use std::mem::ManuallyDrop; use std::panic; /// Represents the success/error of a rust call @@ -42,52 +42,43 @@ use std::panic; #[repr(C)] pub struct RustCallStatus { pub code: RustCallStatusCode, - // code is signed because unsigned types are experimental in Kotlin - pub error_buf: MaybeUninit, - // error_buf is MaybeUninit to avoid dropping the value that the consumer code sends in: - // - Consumers should send in a zeroed out RustBuffer. In this case dropping is a no-op and - // avoiding the drop is a small optimization. - // - If consumers pass in invalid data, then we should avoid trying to drop it. In - // particular, we don't want to try to free any data the consumer has allocated. - // - // `MaybeUninit` requires unsafe code, since we are preventing rust from dropping the value. - // To use this safely we need to make sure that no code paths set this twice, since that will - // leak the first `RustBuffer`. -} - -impl RustCallStatus { - pub fn new() -> Self { - Self { - code: RustCallStatusCode::Success, - error_buf: MaybeUninit::new(RustBuffer::new()), - } - } - - pub fn cancelled() -> Self { - Self { - code: RustCallStatusCode::Cancelled, - error_buf: MaybeUninit::new(RustBuffer::new()), - } - } - - pub fn error(message: impl Into) -> Self { - Self { - code: RustCallStatusCode::UnexpectedError, - error_buf: MaybeUninit::new(>::lower(message.into())), - } - } + // error_buf is owned by the foreign side. + // - Whatever we are passed, we must never free. This however implies we must be passed + // an empty `RustBuffer` otherwise it would leak when we replace it with our own. + // - On error we will set it to a `RustBuffer` we expect the foreign side to free. + // We assume initialization, which means we can use `ManuallyDrop` instead of + // `MaybeUninit`, which avoids unsafe code and clarifies ownership. + // We must take care to not set this twice to avoid leaking the first `RustBuffer`. + pub error_buf: ManuallyDrop, } impl Default for RustCallStatus { fn default() -> Self { Self { code: RustCallStatusCode::Success, - error_buf: MaybeUninit::uninit(), + error_buf: Default::default(), + } + } +} + +impl RustCallStatus { + pub fn cancelled() -> Self { + Self { + code: RustCallStatusCode::Cancelled, + error_buf: Default::default(), + } + } + + pub fn error(message: impl Into) -> Self { + Self { + code: RustCallStatusCode::UnexpectedError, + error_buf: ManuallyDrop::new(>::lower(message.into())), } } } /// Result of a FFI call to a Rust function +/// Value is signed to avoid Kotlin's experimental unsigned types. #[repr(i8)] #[derive(Debug, PartialEq, Eq)] pub enum RustCallStatusCode { @@ -120,6 +111,29 @@ impl TryFrom for RustCallStatusCode { } } +/// Error type for Rust scaffolding calls +/// +/// This enum represents the fact that there are two ways for a scaffolding call to fail: +/// - Expected errors (the Rust function returned an `Err` value). +/// - Unexpected errors (there was a failure calling the Rust function, for example the failure to +/// lift the arguments). +pub enum RustCallError { + /// The Rust function returned an `Err` value. + /// + /// The associated value is the serialized `Err` value. + Error(RustBuffer), + /// There was a failure to call the Rust function, for example a failure to lift the arguments. + /// + /// The associated value is a message string for the error. + InternalError(String), +} + +/// Error when trying to lift arguments to pass to the scaffolding call +pub struct LiftArgsError { + pub arg_name: &'static str, + pub error: anyhow::Error, +} + /// Handle a scaffolding calls /// /// `callback` is responsible for making the actual Rust call and returning a special result type: @@ -141,7 +155,7 @@ impl TryFrom for RustCallStatusCode { /// - `FfiDefault::ffi_default()` is returned, although foreign code should ignore this value pub fn rust_call(out_status: &mut RustCallStatus, callback: F) -> R where - F: panic::UnwindSafe + FnOnce() -> Result, + F: panic::UnwindSafe + FnOnce() -> Result, R: FfiDefault, { rust_call_with_out_status(out_status, callback).unwrap_or_else(R::ffi_default) @@ -158,7 +172,7 @@ pub(crate) fn rust_call_with_out_status( callback: F, ) -> Option where - F: panic::UnwindSafe + FnOnce() -> Result, + F: panic::UnwindSafe + FnOnce() -> Result, { let result = panic::catch_unwind(|| { crate::panichook::ensure_setup(); @@ -169,13 +183,14 @@ where // initializes it to [RustCallStatusCode::Success] Ok(Ok(v)) => Some(v), // Callback returned an Err. - Ok(Err(buf)) => { + Ok(Err(RustCallError::Error(buf))) => { out_status.code = RustCallStatusCode::Error; - unsafe { - // Unsafe because we're setting the `MaybeUninit` value, see above for safety - // invariants. - out_status.error_buf.as_mut_ptr().write(buf); - } + *out_status.error_buf = buf; + None + } + Ok(Err(RustCallError::InternalError(msg))) => { + out_status.code = RustCallStatusCode::UnexpectedError; + *out_status.error_buf = >::lower(msg); None } // Callback panicked @@ -196,11 +211,9 @@ where >::lower(message) })); if let Ok(buf) = message_result { - unsafe { - // Unsafe because we're setting the `MaybeUninit` value, see above for safety - // invariants. - out_status.error_buf.as_mut_ptr().write(buf); - } + // If this was ever set twice we'd leak the old value - but because this is the only + // place where it is set, and this is only called once, no leaks should exist in practice. + *out_status.error_buf = buf; } // Ignore the error case. We've done all that we can at this point. In the bindings // code, we handle this by checking if `error_buf` still has an empty `RustBuffer` and @@ -214,53 +227,58 @@ where mod test { use super::*; use crate::{test_util::TestError, Lift, LowerReturn}; - - fn create_call_status() -> RustCallStatus { - RustCallStatus { - code: RustCallStatusCode::Success, - error_buf: MaybeUninit::new(RustBuffer::new()), - } - } - - fn test_callback(a: u8) -> Result { - match a { - 0 => Ok(100), - 1 => Err(TestError("Error".to_owned())), - x => panic!("Unexpected value: {x}"), - } - } + use anyhow::anyhow; #[test] fn test_rust_call() { - let mut status = create_call_status(); + // Successful call + let mut status = RustCallStatus::default(); let return_value = rust_call(&mut status, || { - as LowerReturn>::lower_return(test_callback(0)) + as LowerReturn>::lower_return(Ok(100)) }); assert_eq!(status.code, RustCallStatusCode::Success); assert_eq!(return_value, 100); + // Successful call that returns an Err value + let mut status = RustCallStatus::default(); rust_call(&mut status, || { - as LowerReturn>::lower_return(test_callback(1)) + as LowerReturn>::lower_return(Err(TestError( + "Error".into(), + ))) }); assert_eq!(status.code, RustCallStatusCode::Error); - unsafe { - assert_eq!( - >::try_lift(status.error_buf.assume_init()).unwrap(), - TestError("Error".to_owned()) - ); - } + assert_eq!( + >::try_lift(ManuallyDrop::into_inner(status.error_buf)) + .unwrap(), + TestError("Error".to_owned()) + ); - let mut status = create_call_status(); + // Internal error while trying to make the call + let mut status = RustCallStatus::default(); rust_call(&mut status, || { - as LowerReturn>::lower_return(test_callback(2)) + as LowerReturn>::handle_failed_lift(LiftArgsError { + arg_name: "foo", + error: anyhow!("invalid handle"), + }) }); assert_eq!(status.code, RustCallStatusCode::UnexpectedError); - unsafe { - assert_eq!( - >::try_lift(status.error_buf.assume_init()).unwrap(), - "Unexpected value: 2" - ); - } + assert_eq!( + >::try_lift(ManuallyDrop::into_inner(status.error_buf)) + .unwrap(), + "Failed to convert arg 'foo': invalid handle" + ); + + // Panic inside the call + let mut status = RustCallStatus::default(); + rust_call(&mut status, || -> Result { + panic!("I crashed") + }); + assert_eq!(status.code, RustCallStatusCode::UnexpectedError); + assert_eq!( + >::try_lift(ManuallyDrop::into_inner(status.error_buf)) + .unwrap(), + "I crashed" + ); } } diff --git a/third_party/rust/uniffi_core/src/ffi/rustfuture/future.rs b/third_party/rust/uniffi_core/src/ffi/rustfuture/future.rs index 93c34e7543c4..ee468ffb9787 100644 --- a/third_party/rust/uniffi_core/src/ffi/rustfuture/future.rs +++ b/third_party/rust/uniffi_core/src/ffi/rustfuture/future.rs @@ -86,13 +86,13 @@ use std::{ }; use super::{RustFutureContinuationCallback, RustFuturePoll, Scheduler}; -use crate::{rust_call_with_out_status, FfiDefault, LowerReturn, RustCallStatus}; +use crate::{rust_call_with_out_status, FfiDefault, LiftArgsError, LowerReturn, RustCallStatus}; /// Wraps the actual future we're polling struct WrappedFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { @@ -106,7 +106,7 @@ where impl WrappedFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { @@ -139,7 +139,8 @@ where // case below and we will never poll the future again. panic::AssertUnwindSafe(|| match pinned.poll(context) { Poll::Pending => Ok(Poll::Pending), - Poll::Ready(v) => T::lower_return(v).map(Poll::Ready), + Poll::Ready(Ok(v)) => T::lower_return(v).map(Poll::Ready), + Poll::Ready(Err(e)) => T::handle_failed_lift(e).map(Poll::Ready), }), ); match result { @@ -185,7 +186,7 @@ where unsafe impl Send for WrappedFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { @@ -195,7 +196,7 @@ where pub(super) struct RustFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { @@ -211,7 +212,7 @@ where impl RustFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { @@ -263,7 +264,7 @@ where impl Wake for RustFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { @@ -298,7 +299,7 @@ pub trait RustFutureFfi: Send + Sync { impl RustFutureFfi for RustFuture where // See rust_future_new for an explanation of these trait bounds - F: Future + Send + 'static, + F: Future> + Send + 'static, T: LowerReturn + Send + 'static, UT: Send + 'static, { diff --git a/third_party/rust/uniffi_core/src/ffi/rustfuture/mod.rs b/third_party/rust/uniffi_core/src/ffi/rustfuture/mod.rs index 3d3505e5ef11..01202c5752f2 100644 --- a/third_party/rust/uniffi_core/src/ffi/rustfuture/mod.rs +++ b/third_party/rust/uniffi_core/src/ffi/rustfuture/mod.rs @@ -12,7 +12,7 @@ use scheduler::*; #[cfg(test)] mod tests; -use crate::{derive_ffi_traits, Handle, HandleAlloc, LowerReturn, RustCallStatus}; +use crate::{derive_ffi_traits, Handle, HandleAlloc, LiftArgsError, LowerReturn, RustCallStatus}; /// Result code for [rust_future_poll]. This is passed to the continuation function. #[repr(i8)] @@ -42,7 +42,7 @@ where // since it will move between threads for an indeterminate amount of time as the foreign // executor calls polls it and the Rust executor wakes it. It does not need to by `Sync`, // since we synchronize all access to the values. - F: Future + Send + 'static, + F: Future> + Send + 'static, // T is the output of the Future. It needs to implement [LowerReturn]. Also it must be Send + // 'static for the same reason as F. T: LowerReturn + Send + 'static, diff --git a/third_party/rust/uniffi_core/src/ffi/rustfuture/tests.rs b/third_party/rust/uniffi_core/src/ffi/rustfuture/tests.rs index 886ee27c7154..6bd9b6c93e08 100644 --- a/third_party/rust/uniffi_core/src/ffi/rustfuture/tests.rs +++ b/third_party/rust/uniffi_core/src/ffi/rustfuture/tests.rs @@ -1,6 +1,7 @@ use once_cell::sync::OnceCell; use std::{ future::Future, + mem::ManuallyDrop, panic, pin::Pin, sync::{Arc, Mutex}, @@ -12,7 +13,7 @@ use crate::{test_util::TestError, Lift, RustBuffer, RustCallStatusCode}; // Sender/Receiver pair that we use for testing struct Channel { - result: Option>, + result: Option, LiftArgsError>>, waker: Option, } @@ -28,7 +29,21 @@ impl Sender { fn send(&self, value: Result) { let mut inner = self.0.lock().unwrap(); - if inner.result.replace(value).is_some() { + if inner.result.replace(Ok(value)).is_some() { + panic!("value already sent"); + } + if let Some(waker) = &inner.waker { + waker.wake_by_ref(); + } + } + + fn send_lift_args_error(&self, arg_name: &'static str, error: anyhow::Error) { + let mut inner = self.0.lock().unwrap(); + if inner + .result + .replace(Err(LiftArgsError { arg_name, error })) + .is_some() + { panic!("value already sent"); } if let Some(waker) = &inner.waker { @@ -40,12 +55,15 @@ impl Sender { struct Receiver(Arc>); impl Future for Receiver { - type Output = Result; + type Output = Result, LiftArgsError>; - fn poll(self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + context: &mut Context<'_>, + ) -> Poll, LiftArgsError>> { let mut inner = self.0.lock().unwrap(); - match &inner.result { - Some(v) => Poll::Ready(v.clone()), + match inner.result.take() { + Some(v) => Poll::Ready(v), None => { inner.waker = Some(context.waker().clone()); Poll::Pending @@ -126,15 +144,36 @@ fn test_error() { let (_, call_status) = complete(rust_future); assert_eq!(call_status.code, RustCallStatusCode::Error); - unsafe { - assert_eq!( - >::try_lift_from_rust_buffer( - call_status.error_buf.assume_init() - ) - .unwrap(), - TestError::from("Something went wrong"), - ) - } + assert_eq!( + >::try_lift_from_rust_buffer(ManuallyDrop::into_inner( + call_status.error_buf + )) + .unwrap(), + TestError::from("Something went wrong"), + ) +} + +#[test] +fn test_lift_args_error() { + let (sender, rust_future) = channel(); + + let continuation_result = poll(&rust_future); + assert_eq!(continuation_result.get(), None); + sender.send_lift_args_error("arg0", anyhow::anyhow!("Invalid handle")); + assert_eq!(continuation_result.get(), Some(&RustFuturePoll::MaybeReady)); + + let continuation_result = poll(&rust_future); + assert_eq!(continuation_result.get(), Some(&RustFuturePoll::Ready)); + + let (_, call_status) = complete(rust_future); + assert_eq!(call_status.code, RustCallStatusCode::UnexpectedError); + assert_eq!( + >::try_lift(ManuallyDrop::into_inner( + call_status.error_buf + )) + .unwrap(), + "Failed to convert arg 'arg0': Invalid handle", + ) } // Once `complete` is called, the inner future should be released, even if wakers still hold a @@ -200,11 +239,11 @@ fn test_wake_during_poll() { if first_time { first_time = false; // Wake the future while we are in the middle of polling it - ctx.waker().clone().wake(); + ctx.waker().wake_by_ref(); Poll::Pending } else { // The second time we're polled, we're ready - Poll::Ready("All done".to_owned()) + Poll::Ready(Ok("All done".to_owned())) } }); let rust_future: Arc> = RustFuture::new(future, crate::UniFfiTag); diff --git a/third_party/rust/uniffi_core/src/ffi_converter_impls.rs b/third_party/rust/uniffi_core/src/ffi_converter_impls.rs index aec093154ab8..714fce16ba24 100644 --- a/third_party/rust/uniffi_core/src/ffi_converter_impls.rs +++ b/third_party/rust/uniffi_core/src/ffi_converter_impls.rs @@ -23,8 +23,9 @@ /// "UT" means an arbitrary `UniFfiTag` type. use crate::{ check_remaining, derive_ffi_traits, ffi_converter_rust_buffer_lift_and_lower, metadata, - ConvertError, FfiConverter, Lift, LiftRef, LiftReturn, Lower, LowerReturn, MetadataBuffer, - Result, RustBuffer, UnexpectedUniFFICallbackError, + ConvertError, FfiConverter, Lift, LiftArgsError, LiftRef, LiftReturn, Lower, LowerError, + LowerReturn, MetadataBuffer, Result, RustBuffer, RustCallError, TypeId, + UnexpectedUniFFICallbackError, }; use anyhow::bail; use bytes::buf::{Buf, BufMut}; @@ -32,7 +33,7 @@ use paste::paste; use std::{ collections::HashMap, convert::TryFrom, - error::Error, + fmt::{Debug, Display}, sync::Arc, time::{Duration, SystemTime}, }; @@ -270,9 +271,6 @@ unsafe impl> Lower for Option { fn lower(obj: Option) -> RustBuffer { Self::lower_into_rust_buffer(obj) } - - const TYPE_ID_META: MetadataBuffer = - MetadataBuffer::from_code(metadata::codes::TYPE_OPTION).concat(T::TYPE_ID_META); } unsafe impl> Lift for Option { @@ -290,7 +288,9 @@ unsafe impl> Lift for Option { fn try_lift(buf: RustBuffer) -> Result> { Self::try_lift_from_rust_buffer(buf) } +} +impl> TypeId for Option { const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_OPTION).concat(T::TYPE_ID_META); } @@ -320,9 +320,6 @@ unsafe impl> Lower for Vec { fn lower(obj: Vec) -> RustBuffer { Self::lower_into_rust_buffer(obj) } - - const TYPE_ID_META: MetadataBuffer = - MetadataBuffer::from_code(metadata::codes::TYPE_VEC).concat(T::TYPE_ID_META); } /// Support for associative arrays via the FFI - `record` in UDL. @@ -346,7 +343,9 @@ unsafe impl> Lift for Vec { fn try_lift(buf: RustBuffer) -> Result> { Self::try_lift_from_rust_buffer(buf) } +} +impl> TypeId for Vec { const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_VEC).concat(T::TYPE_ID_META); } @@ -371,10 +370,6 @@ where fn lower(obj: HashMap) -> RustBuffer { Self::lower_into_rust_buffer(obj) } - - const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_HASH_MAP) - .concat(K::TYPE_ID_META) - .concat(V::TYPE_ID_META); } unsafe impl Lift for HashMap @@ -399,7 +394,13 @@ where fn try_lift(buf: RustBuffer) -> Result> { Self::try_lift_from_rust_buffer(buf) } +} +impl TypeId for HashMap +where + K: TypeId + std::hash::Hash + Eq, + V: TypeId, +{ const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_HASH_MAP) .concat(K::TYPE_ID_META) .concat(V::TYPE_ID_META); @@ -425,14 +426,17 @@ derive_ffi_traits!(blanket SystemTime); // Note that this means we don't get specialized return handling. For example, if we could return // an `Option>` we would always return that type directly and never throw. derive_ffi_traits!(impl LowerReturn for Option where Option: Lower); +derive_ffi_traits!(impl LowerError for Option where Option: Lower); derive_ffi_traits!(impl LiftReturn for Option where Option: Lift); derive_ffi_traits!(impl LiftRef for Option where Option: Lift); derive_ffi_traits!(impl LowerReturn for Vec where Vec: Lower); +derive_ffi_traits!(impl LowerError for Vec where Vec: Lower); derive_ffi_traits!(impl LiftReturn for Vec where Vec: Lift); derive_ffi_traits!(impl LiftRef for Vec where Vec: Lift); derive_ffi_traits!(impl LowerReturn for HashMap where HashMap: Lower); +derive_ffi_traits!(impl LowerError for HashMap where HashMap: Lower); derive_ffi_traits!(impl LiftReturn for HashMap where HashMap: Lift); derive_ffi_traits!(impl LiftRef for HashMap where HashMap: Lift); @@ -440,19 +444,19 @@ derive_ffi_traits!(impl LiftRef for HashMap where HashMap Lower for Arc where Arc: FfiConverter, T: ?Sized); derive_ffi_traits!(impl Lift for Arc where Arc: FfiConverter, T: ?Sized); derive_ffi_traits!(impl LowerReturn for Arc where Arc: Lower, T: ?Sized); +derive_ffi_traits!(impl LowerError for Arc where Arc: Lower, T: ?Sized); derive_ffi_traits!(impl LiftReturn for Arc where Arc: Lift, T: ?Sized); derive_ffi_traits!(impl LiftRef for Arc where Arc: Lift, T: ?Sized); +derive_ffi_traits!(impl TypeId for Arc where Arc: FfiConverter, T: ?Sized); // Implement LowerReturn/LiftReturn for the unit type (void returns) unsafe impl LowerReturn for () { type ReturnType = (); - fn lower_return(_: ()) -> Result { + fn lower_return(_: ()) -> Result { Ok(()) } - - const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_UNIT); } unsafe impl LiftReturn for () { @@ -461,7 +465,9 @@ unsafe impl LiftReturn for () { fn try_lift_successful_return(_: ()) -> Result { Ok(()) } +} +impl TypeId for () { const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_UNIT); } @@ -471,27 +477,26 @@ unsafe impl LiftReturn for () { unsafe impl LowerReturn for Result where R: LowerReturn, - E: Lower + Error + Send + Sync + 'static, + E: LowerError + Display + Debug + Send + Sync + 'static, { type ReturnType = R::ReturnType; - fn lower_return(v: Self) -> Result { + fn lower_return(v: Self) -> Result { match v { Ok(r) => R::lower_return(r), - Err(e) => Err(E::lower_into_rust_buffer(e)), + Err(e) => Err(RustCallError::Error(E::lower_error(e))), } } - fn handle_failed_lift(arg_name: &str, err: anyhow::Error) -> Self { - match err.downcast::() { - Ok(actual_error) => Err(actual_error), - Err(ohno) => panic!("Failed to convert arg '{arg_name}': {ohno}"), + fn handle_failed_lift(error: LiftArgsError) -> Result { + match error.error.downcast::() { + Ok(downcast) => Err(RustCallError::Error(E::lower_error(downcast))), + Err(e) => { + let msg = format!("Failed to convert arg '{}': {e}", error.arg_name); + Err(RustCallError::InternalError(msg)) + } } } - - const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_RESULT) - .concat(R::TYPE_ID_META) - .concat(E::TYPE_ID_META); } unsafe impl LiftReturn for Result @@ -519,7 +524,13 @@ where fn handle_callback_unexpected_error(e: UnexpectedUniFFICallbackError) -> Self { Err(E::try_convert_unexpected_callback_error(e).unwrap_or_else(|e| panic!("{e}"))) } +} +impl TypeId for Result +where + R: TypeId, + E: TypeId, +{ const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_RESULT) .concat(R::TYPE_ID_META) .concat(E::TYPE_ID_META); diff --git a/third_party/rust/uniffi_core/src/ffi_converter_traits.rs b/third_party/rust/uniffi_core/src/ffi_converter_traits.rs index 4e7b9e06fa80..8362bfdb26cf 100644 --- a/third_party/rust/uniffi_core/src/ffi_converter_traits.rs +++ b/third_party/rust/uniffi_core/src/ffi_converter_traits.rs @@ -9,20 +9,24 @@ //! proc-macro generated code. The goal is to allow the proc-macros to go from a type name to the //! correct function for a given FFI operation. //! -//! The traits form a sort-of tree structure from general to specific: +//! The main traits form a sort-of tree structure from general to specific: //! ```ignore //! -//! [FfiConverter] -//! | -//! ----------------------------- -//! | | -//! [Lower] [Lift] -//! | | -//! | -------------- -//! | | | -//! [LowerReturn] [LiftRef] [LiftReturn] +//! [FfiConverter] +//! | +//! ----------------------------------------- +//! | | +//! [Lower] [Lift] +//! | | +//! ----------------- -------------- +//! | | | | +//! [LowerReturn] [LowerError] [LiftRef] [LiftReturn] //! ``` //! +//! There's also: +//! - [TypeId], which is implemented for all types that implement any of the above traits. +//! - [ConvertError], which is implement for errors that can be used in callback interfaces. +//! //! The `derive_ffi_traits` macro can be used to derive the specific traits from the general ones. //! Here's the main ways we implement these traits: //! @@ -39,21 +43,21 @@ //! //! ## Safety //! -//! All traits are unsafe (implementing it requires `unsafe impl`) because we can't guarantee +//! Most traits are unsafe (implementing it requires `unsafe impl`) because we can't guarantee //! that it's safe to pass your type out to foreign-language code and back again. Buggy //! implementations of this trait might violate some assumptions made by the generated code, //! or might not match with the corresponding code in the generated foreign-language bindings. //! These traits should not be used directly, only in generated code, and the generated code should //! have fixture tests to test that everything works correctly together. -use std::{borrow::Borrow, sync::Arc}; +use std::{borrow::Borrow, mem::ManuallyDrop, sync::Arc}; use anyhow::bail; use bytes::Buf; use crate::{ - FfiDefault, Handle, MetadataBuffer, Result, RustBuffer, RustCallStatus, RustCallStatusCode, - UnexpectedUniFFICallbackError, + FfiDefault, Handle, LiftArgsError, MetadataBuffer, Result, RustBuffer, RustCallError, + RustCallStatus, RustCallStatusCode, UnexpectedUniFFICallbackError, }; /// Generalized FFI conversions @@ -128,8 +132,6 @@ pub unsafe trait FfiConverter: Sized { fn try_read(buf: &mut &[u8]) -> Result; /// Type ID metadata, serialized into a [MetadataBuffer]. - /// - /// If a type implements multiple FFI traits, `TYPE_ID_META` must be the same for all of them. const TYPE_ID_META: MetadataBuffer; } @@ -217,8 +219,6 @@ pub unsafe trait Lift: Sized { n => bail!("junk data left in buffer after lifting (count: {n})",), } } - - const TYPE_ID_META: MetadataBuffer; } /// Lower Rust values to pass them to the foreign code @@ -249,13 +249,11 @@ pub unsafe trait Lower: Sized { Self::write(obj, &mut buf); RustBuffer::from_vec(buf) } - - const TYPE_ID_META: MetadataBuffer; } /// Return Rust values to the foreign code /// -/// This is usually derived from [Lift], but we special case types like `Result<>` and `()`. +/// This is usually derived from [Lower], but we special case types like `Result<>` and `()`. /// /// ## Safety /// @@ -271,25 +269,50 @@ pub unsafe trait LowerReturn: Sized { /// When derived, it's the same as `FfiType`. type ReturnType: FfiDefault; + /// Lower the return value from an scaffolding call + /// + /// Returns values that [rust_call] expects: + /// + /// - Ok(v) for `Ok` returns and non-result returns, where v is the lowered return value + /// - `Err(RustCallError::Error(buf))` for `Err` returns where `buf` is serialized error value. + fn lower_return(v: Self) -> Result; + + /// Lower the return value for failed argument lifts + /// + /// This is called when we fail to make a scaffolding call, because of an error lifting an + /// argument. It should return a value that [rust_call] expects: + /// + /// - By default, this is `Err(RustCallError::InternalError(msg))` where `msg` is message + /// describing the failed lift. + /// - For Result types, if we can downcast the error to the `Err` value, then return + /// `Err(RustCallError::Error(buf))`. This results in better exception throws on the foreign + /// side. + fn handle_failed_lift(error: LiftArgsError) -> Result { + let LiftArgsError { arg_name, error } = error; + Err(RustCallError::InternalError(format!( + "Failed to convert arg '{arg_name}': {error}" + ))) + } +} + +/// Return Rust error values +/// +/// This is implemented for types that can be the `E` param in `Result`. +/// It's is usually derived from [Lower], but we sometimes special case it. +/// +/// ## Safety +/// +/// All traits are unsafe (implementing it requires `unsafe impl`) because we can't guarantee +/// that it's safe to pass your type out to foreign-language code and back again. Buggy +/// implementations of this trait might violate some assumptions made by the generated code, +/// or might not match with the corresponding code in the generated foreign-language bindings. +/// These traits should not be used directly, only in generated code, and the generated code should +/// have fixture tests to test that everything works correctly together. +pub unsafe trait LowerError: Sized { /// Lower this value for scaffolding function return /// - /// This method converts values into the `Result<>` type that [rust_call] expects. For - /// successful calls, return `Ok(lower_return)`. For errors that should be translated into - /// thrown exceptions on the foreign code, serialize the error into a RustBuffer and return - /// `Err(buf)` - fn lower_return(obj: Self) -> Result; - - /// If possible, get a serialized error for failed argument lifts - /// - /// By default, we just panic and let `rust_call` handle things. However, for `Result<_, E>` - /// returns, if the anyhow error can be downcast to `E`, then serialize that and return it. - /// This results in the foreign code throwing a "normal" exception, rather than an unexpected - /// exception. - fn handle_failed_lift(arg_name: &str, e: anyhow::Error) -> Self { - panic!("Failed to convert arg '{arg_name}': {e}") - } - - const TYPE_ID_META: MetadataBuffer; + /// Lower the type into a RustBuffer. `RustCallStatus.error_buf` will be set to this. + fn lower_error(obj: Self) -> RustBuffer; } /// Return foreign values to Rust @@ -323,12 +346,12 @@ pub unsafe trait LiftReturn: Sized { Self::handle_callback_unexpected_error(UnexpectedUniFFICallbackError::new(e)) }), RustCallStatusCode::Error => { - Self::lift_error(unsafe { call_status.error_buf.assume_init() }) + Self::lift_error(ManuallyDrop::into_inner(call_status.error_buf)) } _ => { - let e = >::try_lift(unsafe { - call_status.error_buf.assume_init() - }) + let e = >::try_lift( + ManuallyDrop::into_inner(call_status.error_buf), + ) .unwrap_or_else(|e| format!("(Error lifting message: {e}")); Self::handle_callback_unexpected_error(UnexpectedUniFFICallbackError::new(e)) } @@ -355,8 +378,6 @@ pub unsafe trait LiftReturn: Sized { fn handle_callback_unexpected_error(e: UnexpectedUniFFICallbackError) -> Self { panic!("Callback interface failure: {e}") } - - const TYPE_ID_META: MetadataBuffer; } /// Lift references @@ -377,6 +398,14 @@ pub unsafe trait LiftRef { type LiftType: Lift + Borrow; } +/// Type ID metadata +/// +/// This is used to build up more complex metadata. For example, the `MetadataBuffer` for function +/// signatures includes a copy of this metadata for each argument and return type. +pub trait TypeId { + const TYPE_ID_META: MetadataBuffer; +} + pub trait ConvertError: Sized { fn try_convert_unexpected_callback_error(e: UnexpectedUniFFICallbackError) -> Result; } @@ -427,18 +456,24 @@ pub unsafe trait HandleAlloc: Send + Sync { /// This creates a new handle from an existing one. /// It's used when the foreign code wants to pass back an owned handle and still keep a copy /// for themselves. - fn clone_handle(handle: Handle) -> Handle; + /// # Safety + /// The handle must be valid. + unsafe fn clone_handle(handle: Handle) -> Handle; /// Get a clone of the `Arc<>` using a "borrowed" handle. /// - /// Take care that the handle can not be destroyed between when it's passed and when + /// # Safety + /// The handle must be valid. Take care that the handle can + /// not be destroyed between when it's passed and when /// `get_arc()` is called. #1797 is a cautionary tale. - fn get_arc(handle: Handle) -> Arc { + unsafe fn get_arc(handle: Handle) -> Arc { Self::consume_handle(Self::clone_handle(handle)) } /// Consume a handle, getting back the initial `Arc<>` - fn consume_handle(handle: Handle) -> Arc; + /// # Safety + /// The handle must be valid. + unsafe fn consume_handle(handle: Handle) -> Arc; } /// Derive FFI traits @@ -465,18 +500,22 @@ macro_rules! derive_ffi_traits { $crate::derive_ffi_traits!(impl Lower for $ty); $crate::derive_ffi_traits!(impl Lift for $ty); $crate::derive_ffi_traits!(impl LowerReturn for $ty); + $crate::derive_ffi_traits!(impl LowerError for $ty); $crate::derive_ffi_traits!(impl LiftReturn for $ty); $crate::derive_ffi_traits!(impl LiftRef for $ty); $crate::derive_ffi_traits!(impl ConvertError for $ty); + $crate::derive_ffi_traits!(impl TypeId for $ty); }; (local $ty:ty) => { $crate::derive_ffi_traits!(impl Lower for $ty); $crate::derive_ffi_traits!(impl Lift for $ty); $crate::derive_ffi_traits!(impl LowerReturn for $ty); + $crate::derive_ffi_traits!(impl LowerError for $ty); $crate::derive_ffi_traits!(impl LiftReturn for $ty); $crate::derive_ffi_traits!(impl LiftRef for $ty); $crate::derive_ffi_traits!(impl ConvertError for $ty); + $crate::derive_ffi_traits!(impl TypeId for $ty); }; (impl $(<$($generic:ident),*>)? $(::uniffi::)? Lower<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { @@ -491,8 +530,6 @@ macro_rules! derive_ffi_traits { fn write(obj: Self, buf: &mut ::std::vec::Vec) { >::write(obj, buf) } - - const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; } }; @@ -508,8 +545,6 @@ macro_rules! derive_ffi_traits { fn try_read(buf: &mut &[u8]) -> $crate::deps::anyhow::Result { >::try_read(buf) } - - const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; } }; @@ -518,11 +553,18 @@ macro_rules! derive_ffi_traits { { type ReturnType = >::FfiType; - fn lower_return(obj: Self) -> $crate::deps::anyhow::Result { - Ok(>::lower(obj)) + fn lower_return(v: Self) -> $crate::deps::anyhow::Result { + ::std::result::Result::Ok(>::lower(v)) } + } + }; - const TYPE_ID_META: $crate::MetadataBuffer =>::TYPE_ID_META; + (impl $(<$($generic:ident),*>)? $(::uniffi::)? LowerError<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { + unsafe impl $(<$($generic),*>)* $crate::LowerError<$ut> for $ty $(where $($where)*)* + { + fn lower_error(obj: Self) -> $crate::RustBuffer { + >::lower_into_rust_buffer(obj) + } } }; @@ -534,8 +576,6 @@ macro_rules! derive_ffi_traits { fn try_lift_successful_return(v: Self::ReturnType) -> $crate::Result { >::try_lift(v) } - - const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; } }; @@ -569,22 +609,25 @@ macro_rules! derive_ffi_traits { $crate::Handle::from_pointer(::std::sync::Arc::into_raw(::std::sync::Arc::new(value))) } - fn clone_handle(handle: $crate::Handle) -> $crate::Handle { - unsafe { - ::std::sync::Arc::<::std::sync::Arc>::increment_strong_count(handle.as_pointer::<::std::sync::Arc>()); - } + unsafe fn clone_handle(handle: $crate::Handle) -> $crate::Handle { + ::std::sync::Arc::<::std::sync::Arc>::increment_strong_count(handle.as_pointer::<::std::sync::Arc>()); handle } - fn consume_handle(handle: $crate::Handle) -> ::std::sync::Arc { - unsafe { - ::std::sync::Arc::::clone( - &std::sync::Arc::<::std::sync::Arc::>::from_raw(handle.as_pointer::<::std::sync::Arc>()) - ) - } + unsafe fn consume_handle(handle: $crate::Handle) -> ::std::sync::Arc { + ::std::sync::Arc::::clone( + &std::sync::Arc::<::std::sync::Arc::>::from_raw(handle.as_pointer::<::std::sync::Arc>()) + ) } } }; + + (impl $(<$($generic:ident),*>)? $(::uniffi::)? TypeId<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { + impl $(<$($generic),*>)* $crate::TypeId<$ut> for $ty $(where $($where)*)* + { + const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; + } + }; } unsafe impl HandleAlloc for T { @@ -592,12 +635,12 @@ unsafe impl HandleAlloc for T { Handle::from_pointer(Arc::into_raw(value)) } - fn clone_handle(handle: Handle) -> Handle { - unsafe { Arc::increment_strong_count(handle.as_pointer::()) }; + unsafe fn clone_handle(handle: Handle) -> Handle { + Arc::increment_strong_count(handle.as_pointer::()); handle } - fn consume_handle(handle: Handle) -> Arc { - unsafe { Arc::from_raw(handle.as_pointer()) } + unsafe fn consume_handle(handle: Handle) -> Arc { + Arc::from_raw(handle.as_pointer()) } } diff --git a/third_party/rust/uniffi_core/src/lib.rs b/third_party/rust/uniffi_core/src/lib.rs index de6cff8a66e0..2d55006ba76c 100644 --- a/third_party/rust/uniffi_core/src/lib.rs +++ b/third_party/rust/uniffi_core/src/lib.rs @@ -49,7 +49,7 @@ pub use ffi::ffiserialize::FfiBufferElement; pub use ffi::*; pub use ffi_converter_traits::{ ConvertError, FfiConverter, FfiConverterArc, HandleAlloc, Lift, LiftRef, LiftReturn, Lower, - LowerReturn, + LowerError, LowerReturn, TypeId, }; pub use metadata::*; @@ -176,7 +176,7 @@ macro_rules! ffi_converter_rust_buffer_lift_and_lower { let mut buf = vec.as_slice(); let value = >::try_read(&mut buf)?; match $crate::deps::bytes::Buf::remaining(&buf) { - 0 => Ok(value), + 0 => ::std::result::Result::Ok(value), n => $crate::deps::anyhow::bail!( "junk data left in buffer after lifting (count: {n})", ), diff --git a/third_party/rust/uniffi_core/src/metadata.rs b/third_party/rust/uniffi_core/src/metadata.rs index dc61a1bfcbc7..d6b22093ade2 100644 --- a/third_party/rust/uniffi_core/src/metadata.rs +++ b/third_party/rust/uniffi_core/src/metadata.rs @@ -173,15 +173,6 @@ impl MetadataBuffer { self.concat_value(value as u8) } - // Option - pub const fn concat_option_bool(self, value: Option) -> Self { - self.concat_value(match value { - None => 0, - Some(false) => 1, - Some(true) => 2, - }) - } - // Concatenate a string to this buffer. The maximum string length is 255 bytes. For longer strings, // use `concat_long_str()`. // diff --git a/third_party/rust/uniffi_macros/.cargo-checksum.json b/third_party/rust/uniffi_macros/.cargo-checksum.json index d7d49c568d52..45de207080f7 100644 --- a/third_party/rust/uniffi_macros/.cargo-checksum.json +++ b/third_party/rust/uniffi_macros/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"32636b759af83af70f08c4573c101f0467eb8469c318d08dcfbc4578fe456660","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/custom.rs":"36cd6c2eeb8efdc34e59dff634a22e79471ab17f49ceb0f131da5f144313f7e4","src/default.rs":"77466ac54da69094bcdccc5927d0980b1e9dd0095647ca825830673c48847a53","src/enum_.rs":"afe0a6534d8e7f68047e3f1afad9369d5d5650f4c7555e8d4173f24126c715ba","src/error.rs":"30168378da9a23e6530ffe68647bf6618d07a0aaa236d5009137a922798a0e88","src/export.rs":"42c5e784c1dccc796c8b6ea29c2dc1811e48a531488a3ed0e2a59330778a7e41","src/export/attributes.rs":"c848f8c309c4cf7a168f038834752dc4816b5c853768d7c331ea4cd5ce0841b7","src/export/callback_interface.rs":"794b0665dc7eb02ea854c61c8bb2781e0b4ac1de646d95a8fd7791f770f2e6e3","src/export/item.rs":"4e86875692c2d2993fde12e78dbde2cbffa5675ede143577d5620126401efe05","src/export/scaffolding.rs":"03abb762391f67b43bec89dae8f57b54b014133193a8337436f4129de51fb987","src/export/trait_interface.rs":"f07f9908ee28661de4586d89b693f3d93dae5e5cba8a089eff25f20bbf6b373b","src/export/utrait.rs":"b55533d3eef8262944d3c0d9a3a9cba0615d2d5af8608f0919abc7699989e2a8","src/fnsig.rs":"5e434a1cc87166c5245424bb14e896eb766bf680d4d50d4b8536852f91487d7c","src/lib.rs":"a28bbfd2d1dc835306ff6072f75761bb6b3a158477bba966057776c527fe6d70","src/object.rs":"5419ed64c8120aef811a77c2205f58a7a537bdf34ae04f9c92dd3aaa176eed39","src/record.rs":"29072542cc2f3e027bd7c59b45ba913458f8213d1b2b33bc70d140baa98fcdc8","src/setup_scaffolding.rs":"173fdc916967d54bd6532def16d12e5bb85467813a46a031d3338b77625756bb","src/test.rs":"1673f282bb35d6b0740ad0e5f11826c2852d7a0db29604c2258f457415b537e8","src/util.rs":"d1b7b80d0bcc43b7794cd2dbdd89194f84b098343f9e0a3f1843e91c95e1ded3"},"package":"b6f08d5592c669b80a8af5066027098bebec4b4af17a9b8b299bac5f518ab89e"} \ No newline at end of file +{"files":{"Cargo.toml":"c4309008a3a1c8ba72dbaa015b346ffe46efa2e84e23d7a9d9838e04950f5fe1","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/custom.rs":"e5753c73aff42af13a17ddcd5d8e723c988a32bcb764a03bd5a6653612adc647","src/default.rs":"77466ac54da69094bcdccc5927d0980b1e9dd0095647ca825830673c48847a53","src/derive.rs":"3e34ce065c61a76c461fc9241f2a0fade57469623b6744c872389a3e8508f964","src/enum_.rs":"de3807662071222877a1abc4aad9cd04bfa16850f1e36a18f078addfed73e775","src/error.rs":"6d1a9946fbe587622bdb7ad3eabde4bdceac64d542fb686a7031f4a1ded5b55c","src/export.rs":"b8ed2bb98487a7b8b87597a3922ce1641aad786f6d53ecd46956d3f4582b6745","src/export/attributes.rs":"29835ea10f0399c98490ab6396e840baa293ab7fa9986c65e637961345df2900","src/export/callback_interface.rs":"fae7786c85a436fff79492e9ec7b7fba0fac5241d08c7f60b279f4e845916adc","src/export/item.rs":"5523c1afd7c270689acadf60a7e013b2503dbfa28dd2e984fc3c3ab3532b2a3f","src/export/scaffolding.rs":"acd8004544324ac407074ba51053c3ecc98069876718435f78a582397f860fc4","src/export/trait_interface.rs":"245a42e59988d0e895e914310e7e2a24b315f8a440da5177bb5d33ff35cba2bd","src/export/utrait.rs":"9547c8efefd2997f7d56b5d8b08b54b68abac492e205fbfeeb189276f96f4b99","src/ffiops.rs":"f377367435d649a180318648325acd683ace8ae41c0c6a4243e0d578c0fab2ae","src/fnsig.rs":"2d117c24cdb794667787f7de59930f3d49a4bdb105c1a8e443b94a7d84e6d59c","src/lib.rs":"d7d1255ea9075350f785dd5e439334792282fcfb1dbb7cd00b908d5ea3216924","src/object.rs":"d9c53f0639a3b5a3d2d04e4f4b03b5fb62818cfcc08adfb942bb756867390794","src/record.rs":"9d8cc3fe9ef44ff2554b90fdd4b0b9e647a75f6d1002145c4a4291f7cdff20f4","src/setup_scaffolding.rs":"2ab0b934046e9a17ebe0c82041033e398e12dd0f2bd5d7bfbb26def6e0476f69","src/test.rs":"6de5c5719f0ece8b2fb5a3cf838628e8c733f623f31838cb4ee670ca03ebb0de","src/util.rs":"5c14930838c638ecceff39e738969c94f3e6d5d6c994e3fd43a7a9162a81c4d9"},"package":"db66474c5c61b0f7afc3b4995fecf9b72b340daa5ca0ef3da7778d75eb5482ea"} \ No newline at end of file diff --git a/third_party/rust/uniffi_macros/Cargo.toml b/third_party/rust/uniffi_macros/Cargo.toml index c7a602e3ac6a..9847e9f56843 100644 --- a/third_party/rust/uniffi_macros/Cargo.toml +++ b/third_party/rust/uniffi_macros/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_macros" -version = "0.27.3" +version = "0.28.1" authors = ["Firefox Sync Team "] description = "a multi-language bindings generator for rust (convenience macros)" homepage = "https://mozilla.github.io/uniffi-rs" @@ -61,11 +61,11 @@ features = [ version = "0.5.9" [dependencies.uniffi_build] -version = "=0.27.3" +version = "=0.28.1" optional = true [dependencies.uniffi_meta] -version = "=0.27.3" +version = "=0.28.1" [features] default = [] diff --git a/third_party/rust/uniffi_macros/src/custom.rs b/third_party/rust/uniffi_macros/src/custom.rs index 9d8e5acde61c..991a74f30589 100644 --- a/third_party/rust/uniffi_macros/src/custom.rs +++ b/third_party/rust/uniffi_macros/src/custom.rs @@ -2,7 +2,10 @@ * 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::util::{derive_all_ffi_traits, ident_to_string, mod_path, tagged_impl_header}; +use crate::{ + ffiops, + util::{derive_all_ffi_traits, ident_to_string, mod_path, tagged_impl_header}, +}; use proc_macro2::{Ident, TokenStream}; use quote::quote; use syn::Path; @@ -18,6 +21,14 @@ pub(crate) fn expand_ffi_converter_custom_type( let derive_ffi_traits = derive_all_ffi_traits(ident, udl_mode); let name = ident_to_string(ident); let mod_path = mod_path()?; + let from_custom = quote! { <#ident as crate::UniffiCustomTypeConverter>::from_custom }; + let into_custom = quote! { <#ident as crate::UniffiCustomTypeConverter>::into_custom }; + let lower_type = ffiops::lower_type(builtin); + let lower = ffiops::lower(builtin); + let write = ffiops::write(builtin); + let try_lift = ffiops::try_lift(builtin); + let try_read = ffiops::try_read(builtin); + let type_id_meta = ffiops::type_id_meta(builtin); Ok(quote! { #[automatically_derived] @@ -25,27 +36,27 @@ pub(crate) fn expand_ffi_converter_custom_type( // Note: the builtin type needs to implement both `Lower` and `Lift'. We use the // `Lower` trait to get the associated type `FfiType` and const `TYPE_ID_META`. These // can't differ between `Lower` and `Lift`. - type FfiType = <#builtin as ::uniffi::Lower>::FfiType; + type FfiType = #lower_type; fn lower(obj: #ident ) -> Self::FfiType { - <#builtin as ::uniffi::Lower>::lower(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj)) + #lower(#from_custom(obj)) } - fn try_lift(v: Self::FfiType) -> uniffi::Result<#ident> { - <#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift>::try_lift(v)?) + fn try_lift(v: Self::FfiType) -> ::uniffi::Result<#ident> { + #into_custom(#try_lift(v)?) } fn write(obj: #ident, buf: &mut Vec) { - <#builtin as ::uniffi::Lower>::write(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj), buf); + #write(#from_custom(obj), buf); } - fn try_read(buf: &mut &[u8]) -> uniffi::Result<#ident> { - <#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift>::try_read(buf)?) + fn try_read(buf: &mut &[u8]) -> ::uniffi::Result<#ident> { + #into_custom(#try_read(buf)?) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_CUSTOM) .concat_str(#mod_path) .concat_str(#name) - .concat(<#builtin as ::uniffi::Lower>::TYPE_ID_META); + .concat(#type_id_meta); } #derive_ffi_traits @@ -64,6 +75,7 @@ pub(crate) fn expand_ffi_converter_custom_newtype( Ok(quote! { #ffi_converter + #[allow(non_camel_case_types)] #type_converter }) } @@ -73,8 +85,8 @@ fn custom_ffi_type_converter(ident: &Ident, builtin: &Path) -> syn::Result uniffi::Result { - Ok(#ident(val)) + fn into_custom(val: Self::Builtin) -> ::uniffi::Result { + ::std::result::Result::Ok(#ident(val)) } fn from_custom(obj: Self) -> Self::Builtin { diff --git a/third_party/rust/uniffi_macros/src/derive.rs b/third_party/rust/uniffi_macros/src/derive.rs new file mode 100644 index 000000000000..571b5e88a520 --- /dev/null +++ b/third_party/rust/uniffi_macros/src/derive.rs @@ -0,0 +1,119 @@ +/* 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/. */ + +//! General handling for the derive and udl_derive macros + +use crate::util::kw; +use proc_macro2::{Ident, Span, TokenStream}; +use quote::{quote, ToTokens}; +use syn::{ + parse::{Parse, ParseStream}, + DeriveInput, +}; + +pub fn expand_derive( + kind: DeriveKind, + input: DeriveInput, + options: DeriveOptions, +) -> syn::Result { + match kind { + DeriveKind::Record(_) => crate::record::expand_record(input, options), + DeriveKind::Object(_) => crate::object::expand_object(input, options), + DeriveKind::Enum(_) => crate::enum_::expand_enum(input, options), + DeriveKind::Error(_) => crate::error::expand_error(input, options), + } +} + +pub enum DeriveKind { + Record(kw::Record), + Enum(kw::Enum), + Error(kw::Error), + Object(kw::Object), +} + +impl Parse for DeriveKind { + fn parse(input: ParseStream<'_>) -> syn::Result { + let lookahead = input.lookahead1(); + if lookahead.peek(kw::Record) { + Ok(Self::Record(input.parse()?)) + } else if lookahead.peek(kw::Enum) { + Ok(Self::Enum(input.parse()?)) + } else if lookahead.peek(kw::Error) { + Ok(Self::Error(input.parse()?)) + } else if lookahead.peek(kw::Object) { + Ok(Self::Object(input.parse()?)) + } else { + Err(lookahead.error()) + } + } +} + +pub struct DeriveOptions { + /// Should we implement FFI traits for the local UniFfiTag only? + pub local_tag: bool, + /// Should we generate metadata symbols? + pub generate_metadata: bool, +} + +/// default() is used to construct a DeriveOptions for a regular `derive` invocation +impl Default for DeriveOptions { + fn default() -> Self { + Self { + local_tag: false, + generate_metadata: true, + } + } +} + +impl DeriveOptions { + /// Construct DeriveOptions for `udl_derive` + pub fn udl_derive() -> Self { + Self { + local_tag: true, + generate_metadata: false, + } + } + + /// Generate the impl header for a FFI trait + /// + /// This will output something like `impl FfiConverter for #type`. The caller is + /// responsible for providing the body if the impl block. + pub fn ffi_impl_header(&self, trait_name: &str, ident: &impl ToTokens) -> TokenStream { + let trait_name = Ident::new(trait_name, Span::call_site()); + if self.local_tag { + quote! { impl ::uniffi::#trait_name for #ident } + } else { + quote! { impl ::uniffi::#trait_name for #ident } + } + } + + /// Generate a call to `derive_ffi_traits!` that will derive all the FFI traits + pub fn derive_all_ffi_traits(&self, ty: &Ident) -> TokenStream { + if self.local_tag { + quote! { ::uniffi::derive_ffi_traits!(local #ty); } + } else { + quote! { ::uniffi::derive_ffi_traits!(blanket #ty); } + } + } + + /// Generate a call to `derive_ffi_traits!` that will derive some of the FFI traits + pub fn derive_ffi_traits(&self, ty: impl ToTokens, trait_names: &[&str]) -> TokenStream { + let trait_idents = trait_names + .iter() + .map(|name| Ident::new(name, Span::call_site())); + if self.local_tag { + quote! { + #( + ::uniffi::derive_ffi_traits!(impl #trait_idents for #ty); + )* + } + } else { + quote! { + #( + ::uniffi::derive_ffi_traits!(impl #trait_idents for #ty); + )* + } + } + } +} diff --git a/third_party/rust/uniffi_macros/src/enum_.rs b/third_party/rust/uniffi_macros/src/enum_.rs index fd98da31299b..b17b5ba63979 100644 --- a/third_party/rust/uniffi_macros/src/enum_.rs +++ b/third_party/rust/uniffi_macros/src/enum_.rs @@ -1,69 +1,137 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; use syn::{ - parse::{Parse, ParseStream}, - spanned::Spanned, - Attribute, Data, DataEnum, DeriveInput, Expr, Index, Lit, Variant, + parse::ParseStream, spanned::Spanned, Attribute, Data, DataEnum, DeriveInput, Expr, Index, Lit, + Variant, }; -use crate::util::{ - create_metadata_items, derive_all_ffi_traits, either_attribute_arg, extract_docstring, - ident_to_string, kw, mod_path, parse_comma_separated, tagged_impl_header, - try_metadata_value_from_usize, try_read_field, AttributeSliceExt, UniffiAttributeArgs, +use crate::{ + ffiops, + util::{ + create_metadata_items, either_attribute_arg, extract_docstring, ident_to_string, kw, + mod_path, try_metadata_value_from_usize, try_read_field, AttributeSliceExt, + UniffiAttributeArgs, + }, + DeriveOptions, }; +use uniffi_meta::EnumShape; -fn extract_repr(attrs: &[Attribute]) -> syn::Result> { - let mut result = None; - for attr in attrs { - if attr.path().is_ident("repr") { - attr.parse_nested_meta(|meta| { - result = match meta.path.get_ident() { - Some(i) => { - let s = i.to_string(); - match s.as_str() { - "u8" | "u16" | "u32" | "u64" | "usize" | "i8" | "i16" | "i32" - | "i64" | "isize" => Some(i.clone()), - // while the default repr for an enum is `isize` we don't apply that default here. - _ => None, - } - } - _ => None, - }; - Ok(()) - })? - } - } - Ok(result) +/// Stores parsed data from the Derive Input for the enum. +pub struct EnumItem { + ident: Ident, + enum_: DataEnum, + docstring: String, + discr_type: Option, + non_exhaustive: bool, + attr: EnumAttr, } -pub fn expand_enum( - input: DeriveInput, - // Attributes from #[derive_error_for_udl()], if we are in udl mode - attr_from_udl_mode: Option, - udl_mode: bool, -) -> syn::Result { - let enum_ = match input.data { - Data::Enum(e) => e, - _ => { - return Err(syn::Error::new( - Span::call_site(), - "This derive must only be used on enums", - )) - } - }; - let ident = &input.ident; - let docstring = extract_docstring(&input.attrs)?; - let discr_type = extract_repr(&input.attrs)?; - let mut attr: EnumAttr = input.attrs.parse_uniffi_attr_args()?; - if let Some(attr_from_udl_mode) = attr_from_udl_mode { - attr = attr.merge(attr_from_udl_mode)?; +impl EnumItem { + pub fn new(input: DeriveInput) -> syn::Result { + let enum_ = match input.data { + Data::Enum(e) => e, + _ => { + return Err(syn::Error::new( + Span::call_site(), + "This derive must only be used on enums", + )) + } + }; + Ok(Self { + enum_, + ident: input.ident, + docstring: extract_docstring(&input.attrs)?, + discr_type: Self::extract_repr(&input.attrs)?, + non_exhaustive: Self::extract_non_exhaustive(&input.attrs), + attr: input.attrs.parse_uniffi_attr_args()?, + }) } - let ffi_converter_impl = enum_ffi_converter_impl(ident, &enum_, udl_mode, &attr); - let meta_static_var = (!udl_mode).then(|| { - enum_meta_static_var(ident, docstring, discr_type, &enum_, &attr) - .unwrap_or_else(syn::Error::into_compile_error) - }); + pub fn extract_repr(attrs: &[Attribute]) -> syn::Result> { + let mut result = None; + for attr in attrs { + if attr.path().is_ident("repr") { + attr.parse_nested_meta(|meta| { + result = match meta.path.get_ident() { + Some(i) => { + let s = i.to_string(); + match s.as_str() { + "u8" | "u16" | "u32" | "u64" | "usize" | "i8" | "i16" | "i32" + | "i64" | "isize" => Some(i.clone()), + // while the default repr for an enum is `isize` we don't apply that default here. + _ => None, + } + } + _ => None, + }; + Ok(()) + })? + } + } + Ok(result) + } + + pub fn extract_non_exhaustive(attrs: &[Attribute]) -> bool { + attrs.iter().any(|a| a.path().is_ident("non_exhaustive")) + } + + pub fn check_attributes_valid_for_enum(&self) -> syn::Result<()> { + if let Some(flat_error) = &self.attr.flat_error { + return Err(syn::Error::new( + flat_error.span(), + "flat_error not allowed for non-error enums", + )); + } + if let Some(with_try_read) = &self.attr.with_try_read { + return Err(syn::Error::new( + with_try_read.span(), + "with_try_read not allowed for non-error enums", + )); + } + Ok(()) + } + + pub fn ident(&self) -> &Ident { + &self.ident + } + + pub fn enum_(&self) -> &DataEnum { + &self.enum_ + } + + pub fn is_non_exhaustive(&self) -> bool { + self.non_exhaustive + } + + pub fn docstring(&self) -> &str { + self.docstring.as_str() + } + + pub fn discr_type(&self) -> Option<&Ident> { + self.discr_type.as_ref() + } + + pub fn name(&self) -> String { + ident_to_string(&self.ident) + } + + pub fn is_flat_error(&self) -> bool { + self.attr.flat_error.is_some() + } + + pub fn generate_error_try_read(&self) -> bool { + self.attr.with_try_read.is_some() + } +} + +pub fn expand_enum(input: DeriveInput, options: DeriveOptions) -> syn::Result { + let item = EnumItem::new(input)?; + item.check_attributes_valid_for_enum()?; + let ffi_converter_impl = enum_ffi_converter_impl(&item, &options); + + let meta_static_var = options + .generate_metadata + .then(|| enum_meta_static_var(&item).unwrap_or_else(syn::Error::into_compile_error)); Ok(quote! { #ffi_converter_impl @@ -71,51 +139,40 @@ pub fn expand_enum( }) } -pub(crate) fn enum_ffi_converter_impl( - ident: &Ident, - enum_: &DataEnum, - udl_mode: bool, - attr: &EnumAttr, -) -> TokenStream { +pub(crate) fn enum_ffi_converter_impl(item: &EnumItem, options: &DeriveOptions) -> TokenStream { enum_or_error_ffi_converter_impl( - ident, - enum_, - udl_mode, - attr, + item, + options, quote! { ::uniffi::metadata::codes::TYPE_ENUM }, ) } pub(crate) fn rich_error_ffi_converter_impl( - ident: &Ident, - enum_: &DataEnum, - udl_mode: bool, - attr: &EnumAttr, + item: &EnumItem, + options: &DeriveOptions, ) -> TokenStream { enum_or_error_ffi_converter_impl( - ident, - enum_, - udl_mode, - attr, + item, + options, quote! { ::uniffi::metadata::codes::TYPE_ENUM }, ) } fn enum_or_error_ffi_converter_impl( - ident: &Ident, - enum_: &DataEnum, - udl_mode: bool, - attr: &EnumAttr, + item: &EnumItem, + options: &DeriveOptions, metadata_type_code: TokenStream, ) -> TokenStream { - let name = ident_to_string(ident); - let impl_spec = tagged_impl_header("FfiConverter", ident, udl_mode); - let derive_ffi_traits = derive_all_ffi_traits(ident, udl_mode); + let name = item.name(); + let ident = item.ident(); + let impl_spec = options.ffi_impl_header("FfiConverter", ident); + let derive_ffi_traits = options.derive_all_ffi_traits(ident); let mod_path = match mod_path() { Ok(p) => p, Err(e) => return e.into_compile_error(), }; - let mut write_match_arms: Vec<_> = enum_ + let mut write_match_arms: Vec<_> = item + .enum_() .variants .iter() .enumerate() @@ -134,10 +191,8 @@ fn enum_or_error_ffi_converter_impl( let idx = Index::from(i + 1); let write_fields = std::iter::zip(v.fields.iter(), field_idents.iter()).map(|(f, ident)| { - let ty = &f.ty; - quote! { - <#ty as ::uniffi::Lower>::write(#ident, buf); - } + let write = ffiops::write(&f.ty); + quote! { #write(#ident, buf); } }); let is_tuple = v.fields.iter().any(|f| f.ident.is_none()); let fields = if is_tuple { @@ -154,16 +209,16 @@ fn enum_or_error_ffi_converter_impl( } }) .collect(); - if attr.non_exhaustive.is_some() { + if item.is_non_exhaustive() { write_match_arms.push(quote! { - _ => panic!("Unexpected variant in non-exhaustive enum"), + _ => ::std::panic!("Unexpected variant in non-exhaustive enum"), }) } let write_impl = quote! { match obj { #(#write_match_arms)* } }; - let try_read_match_arms = enum_.variants.iter().enumerate().map(|(i, v)| { + let try_read_match_arms = item.enum_().variants.iter().enumerate().map(|(i, v)| { let idx = Index::from(i + 1); let v_ident = &v.ident; let is_tuple = v.fields.iter().any(|f| f.ident.is_none()); @@ -179,11 +234,11 @@ fn enum_or_error_ffi_converter_impl( } } }); - let error_format_string = format!("Invalid {ident} enum value: {{}}"); + let error_format_string = format!("Invalid {name} enum value: {{}}"); let try_read_impl = quote! { ::uniffi::check_remaining(buf, 4)?; - Ok(match ::uniffi::deps::bytes::Buf::get_i32(buf) { + ::std::result::Result::Ok(match ::uniffi::deps::bytes::Buf::get_i32(buf) { #(#try_read_match_arms)* v => ::uniffi::deps::anyhow::bail!(#error_format_string, v), }) @@ -211,28 +266,27 @@ fn enum_or_error_ffi_converter_impl( } } -pub(crate) fn enum_meta_static_var( - ident: &Ident, - docstring: String, - discr_type: Option, - enum_: &DataEnum, - attr: &EnumAttr, -) -> syn::Result { - let name = ident_to_string(ident); +pub(crate) fn enum_meta_static_var(item: &EnumItem) -> syn::Result { + let name = item.name(); let module_path = mod_path()?; - let non_exhaustive = attr.non_exhaustive.is_some(); + let non_exhaustive = item.is_non_exhaustive(); + let docstring = item.docstring(); + let shape = EnumShape::Enum.as_u8(); let mut metadata_expr = quote! { ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::ENUM) .concat_str(#module_path) .concat_str(#name) - .concat_option_bool(None) // forced_flatness + .concat_value(#shape) }; - metadata_expr.extend(match discr_type { + metadata_expr.extend(match item.discr_type() { None => quote! { .concat_bool(false) }, - Some(t) => quote! { .concat_bool(true).concat(<#t as ::uniffi::Lower>::TYPE_ID_META) } + Some(t) => { + let type_id_meta = ffiops::type_id_meta(t); + quote! { .concat_bool(true).concat(#type_id_meta) } + } }); - metadata_expr.extend(variant_metadata(enum_)?); + metadata_expr.extend(variant_metadata(item)?); metadata_expr.extend(quote! { .concat_bool(#non_exhaustive) .concat_long_str(#docstring) @@ -296,7 +350,8 @@ fn variant_value(v: &Variant) -> syn::Result { }) } -pub fn variant_metadata(enum_: &DataEnum) -> syn::Result> { +pub fn variant_metadata(item: &EnumItem) -> syn::Result> { + let enum_ = item.enum_(); let variants_len = try_metadata_value_from_usize(enum_.variants.len(), "UniFFI limits enums to 256 variants")?; std::iter::once(Ok(quote! { .concat_value(#variants_len) })) @@ -315,12 +370,12 @@ pub fn variant_metadata(enum_: &DataEnum) -> syn::Result> { let name = ident_to_string(&v.ident); let value_tokens = variant_value(v)?; let docstring = extract_docstring(&v.attrs)?; - let field_types = v.fields.iter().map(|f| &f.ty); let field_docstrings = v .fields .iter() .map(|f| extract_docstring(&f.attrs)) .collect::>>()?; + let field_type_id_metas = v.fields.iter().map(|f| ffiops::type_id_meta(&f.ty)); Ok(quote! { .concat_str(#name) @@ -328,7 +383,7 @@ pub fn variant_metadata(enum_: &DataEnum) -> syn::Result> { .concat_value(#fields_len) #( .concat_str(#field_names) - .concat(<#field_types as ::uniffi::Lower>::TYPE_ID_META) + .concat(#field_type_id_metas) // field defaults not yet supported for enums .concat_bool(false) .concat_long_str(#field_docstrings) @@ -339,25 +394,31 @@ pub fn variant_metadata(enum_: &DataEnum) -> syn::Result> { .collect() } -#[derive(Default)] +/// Handle #[uniffi(...)] attributes for enums +#[derive(Clone, Default)] pub struct EnumAttr { - pub non_exhaustive: Option, -} - -// So ErrorAttr can be used with `parse_macro_input!` -impl Parse for EnumAttr { - fn parse(input: ParseStream<'_>) -> syn::Result { - parse_comma_separated(input) - } + // All of these attributes are only relevant for errors, but they're defined here so that we + // can reuse EnumItem for errors. + pub flat_error: Option, + pub with_try_read: Option, } impl UniffiAttributeArgs for EnumAttr { fn parse_one(input: ParseStream<'_>) -> syn::Result { let lookahead = input.lookahead1(); - if lookahead.peek(kw::non_exhaustive) { + if lookahead.peek(kw::flat_error) { Ok(Self { - non_exhaustive: input.parse()?, + flat_error: input.parse()?, + ..Self::default() }) + } else if lookahead.peek(kw::with_try_read) { + Ok(Self { + with_try_read: input.parse()?, + ..Self::default() + }) + } else if lookahead.peek(kw::handle_unknown_callback_error) { + // Not used anymore, but still allowed + Ok(Self::default()) } else { Err(lookahead.error()) } @@ -365,7 +426,8 @@ impl UniffiAttributeArgs for EnumAttr { fn merge(self, other: Self) -> syn::Result { Ok(Self { - non_exhaustive: either_attribute_arg(self.non_exhaustive, other.non_exhaustive)?, + flat_error: either_attribute_arg(self.flat_error, other.flat_error)?, + with_try_read: either_attribute_arg(self.with_try_read, other.with_try_read)?, }) } } diff --git a/third_party/rust/uniffi_macros/src/error.rs b/third_party/rust/uniffi_macros/src/error.rs index 804b43800332..39e3deca9333 100644 --- a/third_party/rust/uniffi_macros/src/error.rs +++ b/third_party/rust/uniffi_macros/src/error.rs @@ -1,47 +1,27 @@ -use proc_macro2::{Ident, Span, TokenStream}; +use proc_macro2::TokenStream; use quote::quote; -use syn::{ - parse::{Parse, ParseStream}, - Data, DataEnum, DeriveInput, Index, -}; +use syn::{DeriveInput, Index}; +use uniffi_meta::EnumShape; use crate::{ - enum_::{rich_error_ffi_converter_impl, variant_metadata, EnumAttr}, + enum_::{rich_error_ffi_converter_impl, variant_metadata, EnumItem}, + ffiops, util::{ - chain, create_metadata_items, derive_ffi_traits, either_attribute_arg, extract_docstring, - ident_to_string, kw, mod_path, parse_comma_separated, tagged_impl_header, - try_metadata_value_from_usize, AttributeSliceExt, UniffiAttributeArgs, + chain, create_metadata_items, extract_docstring, ident_to_string, mod_path, + try_metadata_value_from_usize, AttributeSliceExt, }, + DeriveOptions, }; -pub fn expand_error( - input: DeriveInput, - // Attributes from #[derive_error_for_udl()], if we are in udl mode - attr_from_udl_mode: Option, - udl_mode: bool, -) -> syn::Result { - let enum_ = match input.data { - Data::Enum(e) => e, - _ => { - return Err(syn::Error::new( - Span::call_site(), - "This derive currently only supports enums", - )); - } - }; - let ident = &input.ident; - let docstring = extract_docstring(&input.attrs)?; - let mut attr: ErrorAttr = input.attrs.parse_uniffi_attr_args()?; - if let Some(attr_from_udl_mode) = attr_from_udl_mode { - attr = attr.merge(attr_from_udl_mode)?; - } - let ffi_converter_impl = error_ffi_converter_impl(ident, &enum_, &attr, udl_mode)?; - let meta_static_var = (!udl_mode).then(|| { - error_meta_static_var(ident, docstring, &enum_, &attr) - .unwrap_or_else(syn::Error::into_compile_error) - }); +pub fn expand_error(input: DeriveInput, options: DeriveOptions) -> syn::Result { + let enum_item = EnumItem::new(input)?; + let ffi_converter_impl = error_ffi_converter_impl(&enum_item, &options)?; + let meta_static_var = options + .generate_metadata + .then(|| error_meta_static_var(&enum_item).unwrap_or_else(syn::Error::into_compile_error)); - let variant_errors: TokenStream = enum_ + let variant_errors: TokenStream = enum_item + .enum_() .variants .iter() .flat_map(|variant| { @@ -63,16 +43,11 @@ pub fn expand_error( }) } -fn error_ffi_converter_impl( - ident: &Ident, - enum_: &DataEnum, - attr: &ErrorAttr, - udl_mode: bool, -) -> syn::Result { - Ok(if attr.flat.is_some() { - flat_error_ffi_converter_impl(ident, enum_, udl_mode, attr) +fn error_ffi_converter_impl(item: &EnumItem, options: &DeriveOptions) -> syn::Result { + Ok(if item.is_flat_error() { + flat_error_ffi_converter_impl(item, options) } else { - rich_error_ffi_converter_impl(ident, enum_, udl_mode, &attr.clone().try_into()?) + rich_error_ffi_converter_impl(item, options) }) } @@ -80,39 +55,45 @@ fn error_ffi_converter_impl( // // These are errors where we only lower the to_string() value, rather than any associated data. // We lower the to_string() value unconditionally, whether the enum has associated data or not. -fn flat_error_ffi_converter_impl( - ident: &Ident, - enum_: &DataEnum, - udl_mode: bool, - attr: &ErrorAttr, -) -> TokenStream { - let name = ident_to_string(ident); - let lower_impl_spec = tagged_impl_header("Lower", ident, udl_mode); - let lift_impl_spec = tagged_impl_header("Lift", ident, udl_mode); - let derive_ffi_traits = derive_ffi_traits(ident, udl_mode, &["ConvertError"]); +fn flat_error_ffi_converter_impl(item: &EnumItem, options: &DeriveOptions) -> TokenStream { + let name = item.name(); + let ident = item.ident(); + let lower_impl_spec = options.ffi_impl_header("Lower", ident); + let lift_impl_spec = options.ffi_impl_header("Lift", ident); + let type_id_impl_spec = options.ffi_impl_header("TypeId", ident); + let derive_ffi_traits = options.derive_ffi_traits(ident, &["LowerError", "ConvertError"]); let mod_path = match mod_path() { Ok(p) => p, Err(e) => return e.into_compile_error(), }; let lower_impl = { - let mut match_arms: Vec<_> = enum_.variants.iter().enumerate().map(|(i, v)| { - let v_ident = &v.ident; - let idx = Index::from(i + 1); + let mut match_arms: Vec<_> = item + .enum_() + .variants + .iter() + .enumerate() + .map(|(i, v)| { + let v_ident = &v.ident; + let idx = Index::from(i + 1); + let write_string = ffiops::write(quote! { ::std::string::String }); - quote! { - Self::#v_ident { .. } => { - ::uniffi::deps::bytes::BufMut::put_i32(buf, #idx); - <::std::string::String as ::uniffi::Lower>::write(error_msg, buf); + quote! { + Self::#v_ident { .. } => { + ::uniffi::deps::bytes::BufMut::put_i32(buf, #idx); + #write_string(error_msg, buf); + } } - } - }).collect(); - if attr.non_exhaustive.is_some() { + }) + .collect(); + if item.is_non_exhaustive() { match_arms.push(quote! { - _ => panic!("Unexpected variant in non-exhaustive enum"), + _ => ::std::panic!("Unexpected variant in non-exhaustive enum"), }) } + let lower = ffiops::lower_into_rust_buffer(quote! { Self }); + quote! { #[automatically_derived] unsafe #lower_impl_spec { @@ -124,18 +105,14 @@ fn flat_error_ffi_converter_impl( } fn lower(obj: Self) -> ::uniffi::RustBuffer { - >::lower_into_rust_buffer(obj) + #lower(obj) } - - const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_ENUM) - .concat_str(#mod_path) - .concat_str(#name); } } }; - let lift_impl = if attr.with_try_read.is_some() { - let match_arms = enum_.variants.iter().enumerate().map(|(i, v)| { + let lift_impl = if item.generate_error_try_read() { + let match_arms = item.enum_().variants.iter().enumerate().map(|(i, v)| { let v_ident = &v.ident; let idx = Index::from(i + 1); @@ -143,25 +120,23 @@ fn flat_error_ffi_converter_impl( #idx => Self::#v_ident, } }); + let try_lift = ffiops::try_lift_from_rust_buffer(quote! { Self }); quote! { #[automatically_derived] unsafe #lift_impl_spec { type FfiType = ::uniffi::RustBuffer; fn try_read(buf: &mut &[::std::primitive::u8]) -> ::uniffi::deps::anyhow::Result { - Ok(match ::uniffi::deps::bytes::Buf::get_i32(buf) { + ::std::result::Result::Ok(match ::uniffi::deps::bytes::Buf::get_i32(buf) { #(#match_arms)* v => ::uniffi::deps::anyhow::bail!("Invalid #ident enum value: {}", v), }) } fn try_lift(v: ::uniffi::RustBuffer) -> ::uniffi::deps::anyhow::Result { - >::try_lift_from_rust_buffer(v) + #try_lift(v) } - - const TYPE_ID_META: ::uniffi::MetadataBuffer = >::TYPE_ID_META; } - } } else { quote! { @@ -177,14 +152,12 @@ fn flat_error_ffi_converter_impl( type FfiType = ::uniffi::RustBuffer; fn try_read(buf: &mut &[::std::primitive::u8]) -> ::uniffi::deps::anyhow::Result { - panic!("Can't lift flat errors") + ::std::panic!("Can't lift flat errors") } fn try_lift(v: ::uniffi::RustBuffer) -> ::uniffi::deps::anyhow::Result { - panic!("Can't lift flat errors") + ::std::panic!("Can't lift flat errors") } - - const TYPE_ID_META: ::uniffi::MetadataBuffer = >::TYPE_ID_META; } } }; @@ -192,31 +165,36 @@ fn flat_error_ffi_converter_impl( quote! { #lower_impl #lift_impl + + #[automatically_derived] + #type_id_impl_spec { + const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_ENUM) + .concat_str(#mod_path) + .concat_str(#name); + } + #derive_ffi_traits } } -pub(crate) fn error_meta_static_var( - ident: &Ident, - docstring: String, - enum_: &DataEnum, - attr: &ErrorAttr, -) -> syn::Result { - let name = ident_to_string(ident); +pub(crate) fn error_meta_static_var(item: &EnumItem) -> syn::Result { + let name = item.name(); let module_path = mod_path()?; - let flat = attr.flat.is_some(); - let non_exhaustive = attr.non_exhaustive.is_some(); + let non_exhaustive = item.is_non_exhaustive(); + let docstring = item.docstring(); + let flat = item.is_flat_error(); + let shape = EnumShape::Error { flat }.as_u8(); let mut metadata_expr = quote! { ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::ENUM) .concat_str(#module_path) .concat_str(#name) - .concat_option_bool(Some(#flat)) + .concat_value(#shape) .concat_bool(false) // discr_type: None }; if flat { - metadata_expr.extend(flat_error_variant_metadata(enum_)?) + metadata_expr.extend(flat_error_variant_metadata(item)?) } else { - metadata_expr.extend(variant_metadata(enum_)?); + metadata_expr.extend(variant_metadata(item)?); } metadata_expr.extend(quote! { .concat_bool(#non_exhaustive) @@ -225,7 +203,8 @@ pub(crate) fn error_meta_static_var( Ok(create_metadata_items("error", &name, metadata_expr, None)) } -pub fn flat_error_variant_metadata(enum_: &DataEnum) -> syn::Result> { +pub fn flat_error_variant_metadata(item: &EnumItem) -> syn::Result> { + let enum_ = item.enum_(); let variants_len = try_metadata_value_from_usize(enum_.variants.len(), "UniFFI limits enums to 256 variants")?; std::iter::once(Ok(quote! { .concat_value(#variants_len) })) @@ -239,74 +218,3 @@ pub fn flat_error_variant_metadata(enum_: &DataEnum) -> syn::Result, - pub with_try_read: Option, - pub non_exhaustive: Option, -} - -impl UniffiAttributeArgs for ErrorAttr { - fn parse_one(input: ParseStream<'_>) -> syn::Result { - let lookahead = input.lookahead1(); - if lookahead.peek(kw::flat_error) { - Ok(Self { - flat: input.parse()?, - ..Self::default() - }) - } else if lookahead.peek(kw::with_try_read) { - Ok(Self { - with_try_read: input.parse()?, - ..Self::default() - }) - } else if lookahead.peek(kw::non_exhaustive) { - Ok(Self { - non_exhaustive: input.parse()?, - ..Self::default() - }) - } else if lookahead.peek(kw::handle_unknown_callback_error) { - // Not used anymore, but still allowed - Ok(Self::default()) - } else { - Err(lookahead.error()) - } - } - - fn merge(self, other: Self) -> syn::Result { - Ok(Self { - flat: either_attribute_arg(self.flat, other.flat)?, - with_try_read: either_attribute_arg(self.with_try_read, other.with_try_read)?, - non_exhaustive: either_attribute_arg(self.non_exhaustive, other.non_exhaustive)?, - }) - } -} - -// So ErrorAttr can be used with `parse_macro_input!` -impl Parse for ErrorAttr { - fn parse(input: ParseStream<'_>) -> syn::Result { - parse_comma_separated(input) - } -} - -impl TryFrom for EnumAttr { - type Error = syn::Error; - - fn try_from(error_attr: ErrorAttr) -> Result { - if error_attr.flat.is_some() { - Err(syn::Error::new( - Span::call_site(), - "flat attribute not valid for rich enum errors", - )) - } else if error_attr.with_try_read.is_some() { - Err(syn::Error::new( - Span::call_site(), - "with_try_read attribute not valid for rich enum errors", - )) - } else { - Ok(EnumAttr { - non_exhaustive: error_attr.non_exhaustive, - }) - } - } -} diff --git a/third_party/rust/uniffi_macros/src/export.rs b/third_party/rust/uniffi_macros/src/export.rs index 41657a639e42..3843544b21d4 100644 --- a/third_party/rust/uniffi_macros/src/export.rs +++ b/third_party/rust/uniffi_macros/src/export.rs @@ -20,7 +20,7 @@ use self::{ }, }; use crate::util::{ident_to_string, mod_path}; -pub use attributes::{DefaultMap, ExportFnArgs, ExportedImplFnArgs}; +pub use attributes::{AsyncRuntime, DefaultMap, ExportFnArgs}; pub use callback_interface::ffi_converter_callback_interface_impl; // TODO(jplatte): Ensure no generics, … @@ -42,7 +42,7 @@ pub(crate) fn expand_export( match metadata { ExportItem::Function { sig, args } => { - gen_fn_scaffolding(sig, &args.async_runtime, udl_mode) + gen_fn_scaffolding(sig, args.async_runtime.as_ref(), udl_mode) } ExportItem::Impl { items, @@ -65,10 +65,14 @@ pub(crate) fn expand_export( .into_iter() .map(|item| match item { ImplItem::Constructor(sig) => { - gen_constructor_scaffolding(sig, &args.async_runtime, udl_mode) + let async_runtime = + sig.async_runtime.clone().or(args.async_runtime.clone()); + gen_constructor_scaffolding(sig, async_runtime.as_ref(), udl_mode) } ImplItem::Method(sig) => { - gen_method_scaffolding(sig, &args.async_runtime, udl_mode) + let async_runtime = + sig.async_runtime.clone().or(args.async_runtime.clone()); + gen_method_scaffolding(sig, async_runtime.as_ref(), udl_mode) } }) .collect::>()?; diff --git a/third_party/rust/uniffi_macros/src/export/attributes.rs b/third_party/rust/uniffi_macros/src/export/attributes.rs index be7e8902e440..ce6387da615e 100644 --- a/third_party/rust/uniffi_macros/src/export/attributes.rs +++ b/third_party/rust/uniffi_macros/src/export/attributes.rs @@ -10,7 +10,8 @@ use quote::ToTokens; use syn::{ parenthesized, parse::{Parse, ParseStream}, - Attribute, Ident, LitStr, Meta, PathArguments, PathSegment, Token, + punctuated::Punctuated, + Attribute, Ident, LitStr, Meta, Path, PathArguments, PathSegment, Token, }; use uniffi_meta::UniffiTraitDiscriminants; @@ -71,6 +72,9 @@ impl UniffiAttributeArgs for ExportTraitArgs { } } +/// Attribute arguments for function +/// +/// This includes top-level functions, constructors, and methods. #[derive(Clone, Default)] pub struct ExportFnArgs { pub(crate) async_runtime: Option, @@ -110,7 +114,7 @@ impl UniffiAttributeArgs for ExportFnArgs { } else { Err(syn::Error::new( input.span(), - format!("uniffi::export attribute `{input}` is not supported here."), + format!("attribute `{input}` is not supported here."), )) } } @@ -211,7 +215,7 @@ impl UniffiAttributeArgs for ExportStructArgs { } #[derive(Clone)] -pub(crate) enum AsyncRuntime { +pub enum AsyncRuntime { Tokio(LitStr), } @@ -236,112 +240,100 @@ impl ToTokens for AsyncRuntime { } } -/// Arguments for function inside an impl block -/// -/// This stores the parsed arguments for `uniffi::constructor` and `uniffi::method` -#[derive(Clone, Default)] -pub struct ExportedImplFnArgs { - pub(crate) name: Option, - pub(crate) defaults: DefaultMap, -} - -impl Parse for ExportedImplFnArgs { - fn parse(input: ParseStream<'_>) -> syn::Result { - parse_comma_separated(input) - } -} - -impl UniffiAttributeArgs for ExportedImplFnArgs { - fn parse_one(input: ParseStream<'_>) -> syn::Result { - let lookahead = input.lookahead1(); - if lookahead.peek(kw::name) { - let _: kw::name = input.parse()?; - let _: Token![=] = input.parse()?; - let name = Some(input.parse::()?.value()); - Ok(Self { - name, - ..Self::default() - }) - } else if lookahead.peek(kw::default) { - Ok(Self { - defaults: DefaultMap::parse(input)?, - ..Self::default() - }) - } else { - Err(syn::Error::new( - input.span(), - format!("uniffi::constructor/method attribute `{input}` is not supported here."), - )) - } - } - - fn merge(self, other: Self) -> syn::Result { - Ok(Self { - name: either_attribute_arg(self.name, other.name)?, - defaults: self.defaults.merge(other.defaults), - }) - } -} - #[derive(Default)] pub(super) struct ExportedImplFnAttributes { pub constructor: bool, - pub args: ExportedImplFnArgs, + pub args: ExportFnArgs, } impl ExportedImplFnAttributes { pub fn new(attrs: &[Attribute]) -> syn::Result { let mut this = Self::default(); for attr in attrs { - let segs = &attr.path().segments; + let path = attr.path(); - let fst = segs - .first() - .expect("attributes have at least one path segment"); - if fst.ident != "uniffi" { - continue; - } - ensure_no_path_args(fst)?; - - let args = match &attr.meta { - Meta::List(_) => attr.parse_args::()?, - _ => Default::default(), - }; - this.args = args; - - if segs.len() != 2 { - return Err(syn::Error::new_spanned( - segs, - "unsupported uniffi attribute", - )); - } - let snd = &segs[1]; - ensure_no_path_args(snd)?; - - match snd.ident.to_string().as_str() { - "constructor" => { - if this.constructor { - return Err(syn::Error::new_spanned( - attr, - "duplicate constructor attribute", - )); + if is_uniffi_path(path) { + this.process_path(path, attr, &attr.meta)?; + } else if is_cfg_attr(attr) { + if let Ok(nested) = + attr.parse_args_with(Punctuated::::parse_terminated) + { + for meta in &nested { + if let Meta::Path(path) = meta { + this.process_path(path, attr, meta)? + } } - this.constructor = true; - } - "method" => { - if this.constructor { - return Err(syn::Error::new_spanned( - attr, - "confused constructor/method attributes", - )); - } - } - _ => return Err(syn::Error::new_spanned(snd, "unknown uniffi attribute")), + }; } } Ok(this) } + + fn process_path(&mut self, path: &Path, attr: &Attribute, meta: &Meta) -> syn::Result<()> { + let segs = &path.segments; + + let fst = segs + .first() + .expect("attributes have at least one path segment"); + + if fst.ident != "uniffi" { + return Ok(()); + } + ensure_no_path_args(fst)?; + + let args = match meta { + Meta::List(_) => attr.parse_args::()?, + _ => Default::default(), + }; + self.args = args; + + if segs.len() != 2 { + return Err(syn::Error::new_spanned( + segs, + "unsupported uniffi attribute", + )); + } + let snd = &segs[1]; + ensure_no_path_args(snd)?; + + match snd.ident.to_string().as_str() { + "constructor" => { + if self.constructor { + return Err(syn::Error::new_spanned( + attr, + "duplicate constructor attribute", + )); + } + self.constructor = true; + } + "method" => { + if self.constructor { + return Err(syn::Error::new_spanned( + attr, + "confused constructor/method attributes", + )); + } + } + _ => return Err(syn::Error::new_spanned(snd, "unknown uniffi attribute")), + } + + Ok(()) + } +} + +fn is_uniffi_path(path: &Path) -> bool { + path.segments + .first() + .map(|segment| segment.ident == "uniffi") + .unwrap_or(false) +} + +fn is_cfg_attr(attr: &Attribute) -> bool { + attr.meta + .path() + .get_ident() + .is_some_and(|ident| *ident == "cfg_attr") } fn ensure_no_path_args(seg: &PathSegment) -> syn::Result<()> { diff --git a/third_party/rust/uniffi_macros/src/export/callback_interface.rs b/third_party/rust/uniffi_macros/src/export/callback_interface.rs index fe145384ec73..23009712e1d1 100644 --- a/third_party/rust/uniffi_macros/src/export/callback_interface.rs +++ b/third_party/rust/uniffi_macros/src/export/callback_interface.rs @@ -4,6 +4,7 @@ use crate::{ export::ImplItem, + ffiops, fnsig::{FnKind, FnSignature, ReceiverArg}, util::{ create_metadata_items, derive_ffi_traits, ident_to_string, mod_path, tagged_impl_header, @@ -44,33 +45,32 @@ pub(super) fn trait_impl( }) .collect::>>()?; - let vtable_fields = methods.iter() - .map(|sig| { - let ident = &sig.ident; - let param_names = sig.scaffolding_param_names(); - let param_types = sig.scaffolding_param_types(); - let lift_return = sig.lift_return_impl(); - if !sig.is_async { - quote! { - #ident: extern "C" fn( - uniffi_handle: u64, - #(#param_names: #param_types,)* - uniffi_out_return: &mut #lift_return::ReturnType, - uniffi_out_call_status: &mut ::uniffi::RustCallStatus, - ), - } - } else { - quote! { - #ident: extern "C" fn( - uniffi_handle: u64, - #(#param_names: #param_types,)* - uniffi_future_callback: ::uniffi::ForeignFutureCallback<#lift_return::ReturnType>, - uniffi_callback_data: u64, - uniffi_out_return: &mut ::uniffi::ForeignFuture, - ), - } + let vtable_fields = methods.iter().map(|sig| { + let ident = &sig.ident; + let param_names = sig.scaffolding_param_names(); + let param_types = sig.scaffolding_param_types(); + let lift_return_type = ffiops::lift_return_type(&sig.return_ty); + if !sig.is_async { + quote! { + #ident: extern "C" fn( + uniffi_handle: u64, + #(#param_names: #param_types,)* + uniffi_out_return: &mut #lift_return_type, + uniffi_out_call_status: &mut ::uniffi::RustCallStatus, + ), } - }); + } else { + quote! { + #ident: extern "C" fn( + uniffi_handle: u64, + #(#param_names: #param_types,)* + uniffi_future_callback: ::uniffi::ForeignFutureCallback<#lift_return_type>, + uniffi_callback_data: u64, + uniffi_out_return: &mut ::uniffi::ForeignFuture, + ), + } + } + }); let trait_impl_methods = methods .iter() @@ -135,11 +135,13 @@ pub fn ffi_converter_callback_interface_impl( let dyn_trait = quote! { dyn #trait_ident }; let box_dyn_trait = quote! { ::std::boxed::Box<#dyn_trait> }; let lift_impl_spec = tagged_impl_header("Lift", &box_dyn_trait, udl_mode); + let type_id_impl_spec = tagged_impl_header("TypeId", &box_dyn_trait, udl_mode); let derive_ffi_traits = derive_ffi_traits(&box_dyn_trait, udl_mode, &["LiftRef", "LiftReturn"]); let mod_path = match mod_path() { Ok(p) => p, Err(e) => return e.into_compile_error(), }; + let try_lift_self = ffiops::try_lift(quote! { Self }); quote! { #[doc(hidden)] @@ -148,15 +150,19 @@ pub fn ffi_converter_callback_interface_impl( type FfiType = u64; fn try_lift(v: Self::FfiType) -> ::uniffi::deps::anyhow::Result { - Ok(::std::boxed::Box::new(<#trait_impl_ident>::new(v))) + ::std::result::Result::Ok(::std::boxed::Box::new(<#trait_impl_ident>::new(v))) } fn try_read(buf: &mut &[u8]) -> ::uniffi::deps::anyhow::Result { - use uniffi::deps::bytes::Buf; + use ::uniffi::deps::bytes::Buf; ::uniffi::check_remaining(buf, 8)?; - >::try_lift(buf.get_u64()) + #try_lift_self(buf.get_u64()) } + } + #[doc(hidden)] + #[automatically_derived] + #type_id_impl_spec { const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code( ::uniffi::metadata::codes::TYPE_CALLBACK_INTERFACE, ) @@ -204,21 +210,22 @@ fn gen_method_impl(sig: &FnSignature, vtable_cell: &Ident) -> syn::Result #return_ty { let vtable = #vtable_cell.get(); - let mut uniffi_call_status = ::uniffi::RustCallStatus::new(); - let mut uniffi_return_value: #lift_return::ReturnType = ::uniffi::FfiDefault::ffi_default(); + let mut uniffi_call_status: ::uniffi::RustCallStatus = ::std::default::Default::default(); + let mut uniffi_return_value: #lift_return_type = ::uniffi::FfiDefault::ffi_default(); (vtable.#ident)(self.handle, #(#lower_exprs,)* &mut uniffi_return_value, &mut uniffi_call_status); - #lift_return::lift_foreign_return(uniffi_return_value, uniffi_call_status) + #lift_foreign_return(uniffi_return_value, uniffi_call_status) } }) } else { @@ -256,7 +263,7 @@ pub(super) fn metadata_items( iter::once(Ok(callback_interface_items)) .chain(items.iter().map(|item| match item { - ImplItem::Method(sig) => sig.metadata_items_for_callback_interface(), + ImplItem::Method(sig) => sig.metadata_items(), _ => unreachable!("traits have no constructors"), })) .collect() diff --git a/third_party/rust/uniffi_macros/src/export/item.rs b/third_party/rust/uniffi_macros/src/export/item.rs index da3c9455c888..990fc9fecdfd 100644 --- a/third_party/rust/uniffi_macros/src/export/item.rs +++ b/third_party/rust/uniffi_macros/src/export/item.rs @@ -8,8 +8,7 @@ use proc_macro2::{Ident, Span}; use quote::ToTokens; use super::attributes::{ - ExportFnArgs, ExportImplArgs, ExportStructArgs, ExportTraitArgs, ExportedImplFnArgs, - ExportedImplFnAttributes, + ExportFnArgs, ExportImplArgs, ExportStructArgs, ExportTraitArgs, ExportedImplFnAttributes, }; use crate::util::extract_docstring; use uniffi_meta::UniffiTraitDiscriminants; @@ -170,7 +169,7 @@ impl ExportItem { ImplItem::Method(FnSignature::new_trait_method( self_ident.clone(), tim.sig, - ExportedImplFnArgs::default(), + ExportFnArgs::default(), i as u32, docstring, )?) diff --git a/third_party/rust/uniffi_macros/src/export/scaffolding.rs b/third_party/rust/uniffi_macros/src/export/scaffolding.rs index 1d7c02b2a49f..bc45648723a5 100644 --- a/third_party/rust/uniffi_macros/src/export/scaffolding.rs +++ b/third_party/rust/uniffi_macros/src/export/scaffolding.rs @@ -7,11 +7,14 @@ use quote::quote; use std::iter; use super::attributes::AsyncRuntime; -use crate::fnsig::{FnKind, FnSignature}; +use crate::{ + ffiops, + fnsig::{FnKind, FnSignature}, +}; pub(super) fn gen_fn_scaffolding( sig: FnSignature, - ar: &Option, + ar: Option<&AsyncRuntime>, udl_mode: bool, ) -> syn::Result { if sig.receiver.is_some() { @@ -41,7 +44,7 @@ pub(super) fn gen_fn_scaffolding( pub(super) fn gen_constructor_scaffolding( sig: FnSignature, - ar: &Option, + ar: Option<&AsyncRuntime>, udl_mode: bool, ) -> syn::Result { if sig.receiver.is_some() { @@ -63,7 +66,7 @@ pub(super) fn gen_constructor_scaffolding( pub(super) fn gen_method_scaffolding( sig: FnSignature, - ar: &Option, + ar: Option<&AsyncRuntime>, udl_mode: bool, ) -> syn::Result { let scaffolding_func = if sig.receiver.is_none() { @@ -128,34 +131,38 @@ impl ScaffoldingBits { udl_mode: bool, ) -> Self { let ident = &sig.ident; - let lift_impl = if is_trait { - quote! { - <::std::sync::Arc as ::uniffi::Lift> - } + let self_type = if is_trait { + quote! { ::std::sync::Arc } } else { - quote! { - <::std::sync::Arc<#self_ident> as ::uniffi::Lift> - } + quote! { ::std::sync::Arc<#self_ident> } }; + let lift_type = ffiops::lift_type(&self_type); + let try_lift = ffiops::try_lift(&self_type); let try_lift_self = if is_trait { // For trait interfaces we need to special case this. Trait interfaces normally lift // foreign trait impl pointers. However, for a method call, we want to lift a Rust // pointer. quote! { { - let boxed_foreign_arc = unsafe { Box::from_raw(uniffi_self_lowered as *mut ::std::sync::Arc) }; + let boxed_foreign_arc = unsafe { + ::std::boxed::Box::from_raw( + uniffi_self_lowered as *mut ::std::sync::Arc, + ) + }; // Take a clone for our own use. - Ok(*boxed_foreign_arc) + ::std::result::Result::Ok(*boxed_foreign_arc) } } } else { - quote! { #lift_impl::try_lift(uniffi_self_lowered) } + quote! { #try_lift(uniffi_self_lowered) } }; let lift_closure = sig.lift_closure(Some(quote! { match #try_lift_self { - Ok(v) => v, - Err(e) => return Err(("self", e)) + ::std::result::Result::Ok(v) => v, + ::std::result::Result::Err(e) => { + return ::std::result::Result::Err(("self", e)); + } } })); let call_params = sig.rust_call_params(true); @@ -171,7 +178,7 @@ impl ScaffoldingBits { param_names: iter::once(quote! { uniffi_self_lowered }) .chain(sig.scaffolding_param_names()) .collect(), - param_types: iter::once(quote! { #lift_impl::FfiType }) + param_types: iter::once(quote! { #lift_type }) .chain(sig.scaffolding_param_types()) .collect(), lift_closure, @@ -210,7 +217,7 @@ impl ScaffoldingBits { /// `rust_fn` is the Rust function to call. pub(super) fn gen_ffi_function( sig: &FnSignature, - ar: &Option, + ar: Option<&AsyncRuntime>, udl_mode: bool, ) -> syn::Result { let ScaffoldingBits { @@ -241,36 +248,32 @@ pub(super) fn gen_ffi_function( let ffi_ident = sig.scaffolding_fn_ident()?; let name = &sig.name; let return_ty = &sig.return_ty; - let return_impl = &sig.lower_return_impl(); + let ffi_return_ty = ffiops::lower_return_type(return_ty); + let lower_return = ffiops::lower_return(return_ty); + let handle_failed_lift = ffiops::lower_return_handle_failed_lift(return_ty); Ok(if !sig.is_async { - let scaffolding_fn_ffi_buffer_version = ffi_buffer_scaffolding_fn( - &ffi_ident, - "e! { <#return_ty as ::uniffi::LowerReturn>::ReturnType }, - ¶m_types, - true, - ); + let scaffolding_fn_ffi_buffer_version = + ffi_buffer_scaffolding_fn(&ffi_ident, &ffi_return_ty, ¶m_types, true); quote! { #[doc(hidden)] #[no_mangle] #vis extern "C" fn #ffi_ident( #(#param_names: #param_types,)* call_status: &mut ::uniffi::RustCallStatus, - ) -> #return_impl::ReturnType { + ) -> #ffi_return_ty { ::uniffi::deps::log::debug!(#name); let uniffi_lift_args = #lift_closure; ::uniffi::rust_call(call_status, || { - #return_impl::lower_return( - match uniffi_lift_args() { - Ok(uniffi_args) => { - let uniffi_result = #rust_fn_call; - #convert_result - } - Err((arg_name, anyhow_error)) => { - #return_impl::handle_failed_lift(arg_name, anyhow_error) - }, + match uniffi_lift_args() { + ::std::result::Result::Ok(uniffi_args) => { + let uniffi_result = #rust_fn_call; + #lower_return(#convert_result) } - ) + ::std::result::Result::Err((arg_name, error)) => { + #handle_failed_lift(::uniffi::LiftArgsError { arg_name, error} ) + }, + } }) } @@ -289,26 +292,21 @@ pub(super) fn gen_ffi_function( #[no_mangle] pub extern "C" fn #ffi_ident(#(#param_names: #param_types,)*) -> ::uniffi::Handle { ::uniffi::deps::log::debug!(#name); - let uniffi_lift_args = #lift_closure; - match uniffi_lift_args() { - Ok(uniffi_args) => { - ::uniffi::rust_future_new::<_, #return_ty, _>( - async move { + let uniffi_lifted_args = (#lift_closure)(); + ::uniffi::rust_future_new::<_, #return_ty, _>( + async move { + match uniffi_lifted_args { + ::std::result::Result::Ok(uniffi_args) => { let uniffi_result = #future_expr.await; - #convert_result + Ok(#convert_result) + } + ::std::result::Result::Err((arg_name, error)) => { + Err(::uniffi::LiftArgsError { arg_name, error }) }, - crate::UniFfiTag - ) + } }, - Err((arg_name, anyhow_error)) => { - ::uniffi::rust_future_new::<_, #return_ty, _>( - async move { - #return_impl::handle_failed_lift(arg_name, anyhow_error) - }, - crate::UniFfiTag, - ) - }, - } + crate::UniFfiTag + ) } #scaffolding_fn_ffi_buffer_version @@ -337,7 +335,7 @@ fn ffi_buffer_scaffolding_fn( ) { let mut arg_buf = unsafe { ::std::slice::from_raw_parts(arg_ptr, ::uniffi::ffi_buffer_size!(#(#type_list),*)) }; let mut return_buf = unsafe { ::std::slice::from_raw_parts_mut(return_ptr, ::uniffi::ffi_buffer_size!(#return_type, ::uniffi::RustCallStatus)) }; - let mut out_status = ::uniffi::RustCallStatus::default(); + let mut out_status: ::uniffi::RustCallStatus = ::std::default::Default::default(); let return_value = #fn_ident( #( diff --git a/third_party/rust/uniffi_macros/src/export/trait_interface.rs b/third_party/rust/uniffi_macros/src/export/trait_interface.rs index 83587ae386c3..18d01a5d385d 100644 --- a/third_party/rust/uniffi_macros/src/export/trait_interface.rs +++ b/third_party/rust/uniffi_macros/src/export/trait_interface.rs @@ -11,6 +11,7 @@ use crate::{ export::{ attributes::ExportTraitArgs, callback_interface, gen_method_scaffolding, item::ImplItem, }, + ffiops, object::interface_meta_static_var, util::{ident_to_string, tagged_impl_header}, }; @@ -53,10 +54,14 @@ pub(super) fn gen_trait_scaffolding( ptr: *const ::std::ffi::c_void, call_status: &mut ::uniffi::RustCallStatus ) -> *const ::std::ffi::c_void { - uniffi::rust_call(call_status, || { - let ptr = ptr as *mut std::sync::Arc; - let arc = unsafe { ::std::sync::Arc::clone(&*ptr) }; - Ok(::std::boxed::Box::into_raw(::std::boxed::Box::new(arc)) as *const ::std::ffi::c_void) + ::uniffi::rust_call(call_status, || { + let ptr = ptr as *mut ::std::sync::Arc; + let arc: ::std::sync::Arc<_> = unsafe { ::std::clone::Clone::clone(&*ptr) }; + ::std::result::Result::Ok( + ::std::boxed::Box::into_raw( + ::std::boxed::Box::new(arc), + ) as *const ::std::ffi::c_void + ) }) } @@ -73,10 +78,14 @@ pub(super) fn gen_trait_scaffolding( ptr: *const ::std::ffi::c_void, call_status: &mut ::uniffi::RustCallStatus ) { - uniffi::rust_call(call_status, || { - assert!(!ptr.is_null()); - drop(unsafe { ::std::boxed::Box::from_raw(ptr as *mut std::sync::Arc) }); - Ok(()) + ::uniffi::rust_call(call_status, || { + ::std::assert!(!ptr.is_null()); + ::std::mem::drop(unsafe { + ::std::boxed::Box::from_raw( + ptr as *mut ::std::sync::Arc, + ) + }); + ::std::result::Result::Ok(()) }); } }; @@ -84,7 +93,7 @@ pub(super) fn gen_trait_scaffolding( let impl_tokens: TokenStream = items .into_iter() .map(|item| match item { - ImplItem::Method(sig) => gen_method_scaffolding(sig, &None, udl_mode), + ImplItem::Method(sig) => gen_method_scaffolding(sig, None, udl_mode), _ => unreachable!("traits have no constructors"), }) .collect::>()?; @@ -95,7 +104,7 @@ pub(super) fn gen_trait_scaffolding( } else { ObjectImpl::Trait }; - interface_meta_static_var(&self_ident, imp, mod_path, docstring) + interface_meta_static_var(&self_ident, imp, mod_path, docstring.as_str()) .unwrap_or_else(syn::Error::into_compile_error) }); let ffi_converter_tokens = ffi_converter(mod_path, &self_ident, udl_mode, with_foreign); @@ -122,14 +131,16 @@ pub(crate) fn ffi_converter( let trait_impl_ident = callback_interface::trait_impl_ident(&trait_name); quote! { fn try_lift(v: Self::FfiType) -> ::uniffi::deps::anyhow::Result<::std::sync::Arc> { - Ok(::std::sync::Arc::new(<#trait_impl_ident>::new(v as u64))) + ::std::result::Result::Ok(::std::sync::Arc::new(<#trait_impl_ident>::new(v as u64))) } } } else { quote! { fn try_lift(v: Self::FfiType) -> ::uniffi::deps::anyhow::Result<::std::sync::Arc> { unsafe { - Ok(*::std::boxed::Box::from_raw(v as *mut ::std::sync::Arc)) + ::std::result::Result::Ok( + *::std::boxed::Box::from_raw(v as *mut ::std::sync::Arc), + ) } } } @@ -139,13 +150,17 @@ pub(crate) fn ffi_converter( } else { quote! { ::uniffi::metadata::codes::TYPE_TRAIT_INTERFACE } }; + let lower_self = ffiops::lower(quote! { ::std::sync::Arc }); + let try_lift_self = ffiops::try_lift(quote! { ::std::sync::Arc }); quote! { // All traits must be `Sync + Send`. The generated scaffolding will fail to compile // if they are not, but unfortunately it fails with an unactionably obscure error message. // By asserting the requirement explicitly, we help Rust produce a more scrutable error message // and thus help the user debug why the requirement isn't being met. - uniffi::deps::static_assertions::assert_impl_all!(dyn #trait_ident: ::core::marker::Sync, ::core::marker::Send); + ::uniffi::deps::static_assertions::assert_impl_all!( + dyn #trait_ident: ::core::marker::Sync, ::core::marker::Send + ); unsafe #impl_spec { type FfiType = *const ::std::os::raw::c_void; @@ -156,19 +171,18 @@ pub(crate) fn ffi_converter( #try_lift - fn write(obj: ::std::sync::Arc, buf: &mut Vec) { + fn write(obj: ::std::sync::Arc, buf: &mut ::std::vec::Vec) { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); ::uniffi::deps::bytes::BufMut::put_u64( buf, - >::lower(obj) as u64, + #lower_self(obj) as ::std::primitive::u64, ); } fn try_read(buf: &mut &[u8]) -> ::uniffi::Result<::std::sync::Arc> { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); ::uniffi::check_remaining(buf, 8)?; - >::try_lift( - ::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) + #try_lift_self(::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(#metadata_code) diff --git a/third_party/rust/uniffi_macros/src/export/utrait.rs b/third_party/rust/uniffi_macros/src/export/utrait.rs index 9007ae2c56ba..6e133cedbd34 100644 --- a/third_party/rust/uniffi_macros/src/export/utrait.rs +++ b/third_party/rust/uniffi_macros/src/export/utrait.rs @@ -7,7 +7,7 @@ use quote::quote; use syn::ext::IdentExt; use super::gen_ffi_function; -use crate::export::ExportedImplFnArgs; +use crate::export::ExportFnArgs; use crate::fnsig::FnSignature; use crate::util::extract_docstring; use uniffi_meta::UniffiTraitDiscriminants; @@ -103,14 +103,14 @@ pub(crate) fn expand_uniffi_trait_export( let method_eq = quote! { fn uniffi_trait_eq_eq(&self, other: &#self_ident) -> bool { use ::std::cmp::PartialEq; - uniffi::deps::static_assertions::assert_impl_all!(#self_ident: PartialEq); // This object has a trait method which requires `PartialEq` be implemented. + ::uniffi::deps::static_assertions::assert_impl_all!(#self_ident: PartialEq); // This object has a trait method which requires `PartialEq` be implemented. PartialEq::eq(self, other) } }; let method_ne = quote! { fn uniffi_trait_eq_ne(&self, other: &#self_ident) -> bool { use ::std::cmp::PartialEq; - uniffi::deps::static_assertions::assert_impl_all!(#self_ident: PartialEq); // This object has a trait method which requires `PartialEq` be implemented. + ::uniffi::deps::static_assertions::assert_impl_all!(#self_ident: PartialEq); // This object has a trait method which requires `PartialEq` be implemented. PartialEq::ne(self, other) } }; @@ -165,17 +165,17 @@ fn process_uniffi_trait_method( &FnSignature::new_method( self_ident.clone(), item.sig.clone(), - ExportedImplFnArgs::default(), + ExportFnArgs::default(), docstring.clone(), )?, - &None, + None, udl_mode, )?; // metadata for the method, which will be packed inside metadata for the trait. let method_meta = FnSignature::new_method( self_ident.clone(), item.sig, - ExportedImplFnArgs::default(), + ExportFnArgs::default(), docstring, )? .metadata_expr()?; diff --git a/third_party/rust/uniffi_macros/src/ffiops.rs b/third_party/rust/uniffi_macros/src/ffiops.rs new file mode 100644 index 000000000000..f43befd812e9 --- /dev/null +++ b/third_party/rust/uniffi_macros/src/ffiops.rs @@ -0,0 +1,122 @@ +/* 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/. */ + +//! Functions, types and expressions to handle FFI operations. +//! +//! This module leverages the various traits defined in `uniffi_core::ffi_converter_traits` to provide functionality to the rest of `uniffi_macros`. +//! Keeping this layer separate makes it easier to handle changes to those traits. +//! See `uniffi_core::ffi_converter_traits` for the meaning of these functions. + +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; + +// Lower type +pub fn lower_type(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lower>::FfiType + } +} + +// Lower function +pub fn lower(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lower>::lower + } +} + +// Lift type +pub fn lift_type(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lift>::FfiType + } +} + +// Lift function +pub fn try_lift(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lift>::try_lift + } +} + +/// Write function +pub fn write(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lower>::write + } +} + +/// Read function +pub fn try_read(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lift>::try_read + } +} + +/// Lower return type +pub fn lower_return_type(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::LowerReturn>::ReturnType + } +} + +/// Lower return function +pub fn lower_return(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::LowerReturn>::lower_return + } +} + +/// Lower error function +pub fn lower_error(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::LowerError>::lower_error + } +} + +/// Lift return type +pub fn lift_return_type(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::LiftReturn>::ReturnType + } +} + +/// Lift foreign return function +pub fn lift_foreign_return(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::LiftReturn>::lift_foreign_return + } +} + +/// Handle failed lift function +pub fn lower_return_handle_failed_lift(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::LowerReturn>::handle_failed_lift + } +} + +/// LiftRef type +pub fn lift_ref_type(ty: impl ToTokens) -> TokenStream { + quote! { <#ty as ::uniffi::LiftRef>::LiftType } +} + +/// Lower into rust buffer function +pub fn lower_into_rust_buffer(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lower>::lower_into_rust_buffer + } +} + +/// Lift from rust buffer function +pub fn try_lift_from_rust_buffer(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::Lift>::try_lift_from_rust_buffer + } +} + +/// Expression for the TYPE_ID_META value for a type +pub fn type_id_meta(ty: impl ToTokens) -> TokenStream { + quote! { + <#ty as ::uniffi::TypeId>::TYPE_ID_META + } +} diff --git a/third_party/rust/uniffi_macros/src/fnsig.rs b/third_party/rust/uniffi_macros/src/fnsig.rs index 9c591252077d..19774dc3bac5 100644 --- a/third_party/rust/uniffi_macros/src/fnsig.rs +++ b/third_party/rust/uniffi_macros/src/fnsig.rs @@ -4,7 +4,8 @@ use crate::{ default::{default_value_metadata_calls, DefaultValue}, - export::{DefaultMap, ExportFnArgs, ExportedImplFnArgs}, + export::{AsyncRuntime, DefaultMap, ExportFnArgs}, + ffiops, util::{create_metadata_items, ident_to_string, mod_path, try_metadata_value_from_usize}, }; use proc_macro2::{Span, TokenStream}; @@ -20,6 +21,7 @@ pub(crate) struct FnSignature { // The foreign name for this function, usually == ident. pub name: String, pub is_async: bool, + pub async_runtime: Option, pub receiver: Option, pub args: Vec, pub return_ty: TokenStream, @@ -36,51 +38,38 @@ impl FnSignature { args: ExportFnArgs, docstring: String, ) -> syn::Result { - Self::new(FnKind::Function, sig, args.name, args.defaults, docstring) + Self::new(FnKind::Function, sig, args, docstring) } pub(crate) fn new_method( self_ident: Ident, sig: syn::Signature, - args: ExportedImplFnArgs, + args: ExportFnArgs, docstring: String, ) -> syn::Result { - Self::new( - FnKind::Method { self_ident }, - sig, - args.name, - args.defaults, - docstring, - ) + Self::new(FnKind::Method { self_ident }, sig, args, docstring) } pub(crate) fn new_constructor( self_ident: Ident, sig: syn::Signature, - args: ExportedImplFnArgs, + args: ExportFnArgs, docstring: String, ) -> syn::Result { - Self::new( - FnKind::Constructor { self_ident }, - sig, - args.name, - args.defaults, - docstring, - ) + Self::new(FnKind::Constructor { self_ident }, sig, args, docstring) } pub(crate) fn new_trait_method( self_ident: Ident, sig: syn::Signature, - args: ExportedImplFnArgs, + args: ExportFnArgs, index: u32, docstring: String, ) -> syn::Result { Self::new( FnKind::TraitMethod { self_ident, index }, sig, - args.name, - args.defaults, + args, docstring, ) } @@ -88,8 +77,7 @@ impl FnSignature { pub(crate) fn new( kind: FnKind, sig: syn::Signature, - name: Option, - mut defaults: DefaultMap, + mut export_fn_args: ExportFnArgs, docstring: String, ) -> syn::Result { let span = sig.span(); @@ -104,7 +92,7 @@ impl FnSignature { let mut input_iter = sig .inputs .into_iter() - .map(|a| Arg::new(a, &mut defaults)) + .map(|a| Arg::new(a, &mut export_fn_args.defaults)) .peekable(); let receiver = input_iter @@ -127,20 +115,30 @@ impl FnSignature { }) .collect::>>()?; - if let Some(ident) = defaults.idents().first() { + if let Some(ident) = export_fn_args.defaults.idents().first() { return Err(syn::Error::new( ident.span(), format!("Unknown default argument: {}", ident), )); } + if !is_async && export_fn_args.async_runtime.is_some() { + return Err(syn::Error::new( + export_fn_args.async_runtime.span(), + "Function not async".to_string(), + )); + } + Ok(Self { kind, span, mod_path: mod_path()?, - name: name.unwrap_or_else(|| ident_to_string(&ident)), + name: export_fn_args + .name + .unwrap_or_else(|| ident_to_string(&ident)), ident, is_async, + async_runtime: export_fn_args.async_runtime, receiver, args, return_ty: output, @@ -149,20 +147,6 @@ impl FnSignature { }) } - pub fn lower_return_impl(&self) -> TokenStream { - let return_ty = &self.return_ty; - quote! { - <#return_ty as ::uniffi::LowerReturn> - } - } - - pub fn lift_return_impl(&self) -> TokenStream { - let return_ty = &self.return_ty; - quote! { - <#return_ty as ::uniffi::LiftReturn> - } - } - /// Generate a closure that tries to lift all arguments into a tuple. /// /// The closure moves all scaffolding arguments into itself and returns: @@ -171,18 +155,20 @@ impl FnSignature { pub fn lift_closure(&self, self_lift: Option) -> TokenStream { let arg_lifts = self.args.iter().map(|arg| { let ident = &arg.ident; - let lift_impl = arg.lift_impl(); + let try_lift = ffiops::try_lift(&arg.ty); let name = &arg.name; quote! { - match #lift_impl::try_lift(#ident) { - Ok(v) => v, - Err(e) => return Err((#name, e)), + match #try_lift(#ident) { + ::std::result::Result::Ok(v) => v, + ::std::result::Result::Err(e) => { + return ::std::result::Result::Err((#name, e)) + } } } }); let all_lifts = self_lift.into_iter().chain(arg_lifts); quote! { - move || Ok(( + move || ::std::result::Result::Ok(( #(#all_lifts,)* )) } @@ -238,10 +224,7 @@ impl FnSignature { } pub fn scaffolding_param_types(&self) -> impl Iterator + '_ { - self.args.iter().map(|a| { - let lift_impl = a.lift_impl(); - quote! { #lift_impl::FfiType } - }) + self.args.iter().map(|a| ffiops::lift_type(&a.ty)) } /// Generate metadata items for this function @@ -266,6 +249,8 @@ impl FnSignature { .map(NamedArg::arg_metadata) .collect::>>()?; + let type_id_meta = ffiops::type_id_meta(return_ty); + match &self.kind { FnKind::Function => Ok(quote! { ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::FUNC) @@ -274,7 +259,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(#type_id_meta) .concat_long_str(#docstring) }), @@ -288,7 +273,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(#type_id_meta) .concat_long_str(#docstring) }) } @@ -304,7 +289,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(#type_id_meta) .concat_long_str(#docstring) }) } @@ -319,7 +304,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(#type_id_meta) .concat_long_str(#docstring) }) } @@ -368,69 +353,6 @@ impl FnSignature { } } - /// Generate metadata items for callback interfaces - /// - /// Unfortunately, most of this is duplicate code from [Self::metadata_items] and - /// [Self::metadata_expr]. However, one issue with that code is that it needs to assume if the - /// arguments are being lifted vs lowered in order to get TYPE_ID_META. That code uses - /// `::TYPE_ID_META` for arguments and `::TYPE_ID_META` for - /// return types, which works for accidental/historical reasons. - /// - /// The one exception is callback interfaces (#1947), which are handled by this method. - /// - /// TODO: fix the metadata system so that this is not needed. - pub(crate) fn metadata_items_for_callback_interface(&self) -> syn::Result { - let Self { - name, - return_ty, - is_async, - mod_path, - docstring, - .. - } = &self; - match &self.kind { - FnKind::TraitMethod { - self_ident, index, .. - } => { - let object_name = ident_to_string(self_ident); - let args_len = try_metadata_value_from_usize( - // Use param_lifts to calculate this instead of sig.inputs to avoid counting any self - // params - self.args.len(), - "UniFFI limits functions to 256 arguments", - )?; - let arg_metadata_calls = self - .args - .iter() - .map(NamedArg::arg_metadata) - .collect::>>()?; - let metadata_expr = quote! { - ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TRAIT_METHOD) - .concat_str(#mod_path) - .concat_str(#object_name) - .concat_u32(#index) - .concat_str(#name) - .concat_bool(#is_async) - .concat_value(#args_len) - #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LiftReturn>::TYPE_ID_META) - .concat_long_str(#docstring) - }; - Ok(create_metadata_items( - "method", - &format!("{object_name}_{name}"), - metadata_expr, - Some(self.checksum_symbol_name()), - )) - } - - // This should never happen and indicates an error in the internal code - _ => panic!( - "metadata_items_for_callback_interface can only be called with `TraitMethod` sigs" - ), - } - } - pub(crate) fn checksum_symbol_name(&self) -> String { let name = &self.name; match &self.kind { @@ -516,7 +438,7 @@ impl NamedArg { let inner = &r.elem; Self { name: ident_to_string(&ident), - ty: quote! { <#inner as ::uniffi::LiftRef>::LiftType }, + ty: ffiops::lift_ref_type(inner), ref_type: Some(*inner.clone()), default: defaults.remove(&ident), ident, @@ -532,16 +454,6 @@ impl NamedArg { }) } - pub(crate) fn lift_impl(&self) -> TokenStream { - let ty = &self.ty; - quote! { <#ty as ::uniffi::Lift> } - } - - pub(crate) fn lower_impl(&self) -> TokenStream { - let ty = &self.ty; - quote! { <#ty as ::uniffi::Lower> } - } - /// Generate the parameter for this Arg pub(crate) fn param(&self) -> TokenStream { let ident = &self.ident; @@ -551,11 +463,11 @@ impl NamedArg { pub(crate) fn arg_metadata(&self) -> syn::Result { let name = &self.name; - let lift_impl = self.lift_impl(); + let type_id_meta = ffiops::type_id_meta(&self.ty); let default_calls = default_value_metadata_calls(&self.default)?; Ok(quote! { .concat_str(#name) - .concat(#lift_impl::TYPE_ID_META) + .concat(#type_id_meta) #default_calls }) } diff --git a/third_party/rust/uniffi_macros/src/lib.rs b/third_party/rust/uniffi_macros/src/lib.rs index 929400c885f1..289740b1c8e3 100644 --- a/third_party/rust/uniffi_macros/src/lib.rs +++ b/third_party/rust/uniffi_macros/src/lib.rs @@ -17,9 +17,11 @@ use syn::{ mod custom; mod default; +mod derive; mod enum_; mod error; mod export; +mod ffiops; mod fnsig; mod object; mod record; @@ -28,8 +30,8 @@ mod test; mod util; use self::{ - enum_::expand_enum, error::expand_error, export::expand_export, object::expand_object, - record::expand_record, + derive::DeriveOptions, enum_::expand_enum, error::expand_error, export::expand_export, + object::expand_object, record::expand_record, }; struct CustomTypeInfo { @@ -106,28 +108,28 @@ fn do_export(attr_args: TokenStream, input: TokenStream, udl_mode: bool) -> Toke #[proc_macro_derive(Record, attributes(uniffi))] pub fn derive_record(input: TokenStream) -> TokenStream { - expand_record(parse_macro_input!(input), false) + expand_record(parse_macro_input!(input), DeriveOptions::default()) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(Enum)] pub fn derive_enum(input: TokenStream) -> TokenStream { - expand_enum(parse_macro_input!(input), None, false) + expand_enum(parse_macro_input!(input), DeriveOptions::default()) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(Object)] pub fn derive_object(input: TokenStream) -> TokenStream { - expand_object(parse_macro_input!(input), false) + expand_object(parse_macro_input!(input), DeriveOptions::default()) .unwrap_or_else(syn::Error::into_compile_error) .into() } #[proc_macro_derive(Error, attributes(uniffi))] pub fn derive_error(input: TokenStream) -> TokenStream { - expand_error(parse_macro_input!(input), None, false) + expand_error(parse_macro_input!(input), DeriveOptions::default()) .unwrap_or_else(syn::Error::into_compile_error) .into() } @@ -153,28 +155,11 @@ pub fn custom_newtype(tokens: TokenStream) -> TokenStream { .into() } -// == derive_for_udl and export_for_udl == +// Derive items for UDL mode // -// The Askama templates generate placeholder items wrapped with these attributes. The goal is to -// have all scaffolding generation go through the same code path. -// -// The one difference is that derive-style attributes are not allowed inside attribute macro -// inputs. Instead, we take the attributes from the macro invocation itself. -// -// Instead of: -// -// ``` -// #[derive(Error) -// #[uniffi(flat_error]) -// enum { .. } -// ``` -// -// We have: -// -// ``` -// #[derive_error_for_udl(flat_error)] -// enum { ... } -// ``` +// The Askama templates generate placeholder items wrapped with the `#[udl_derive()]` +// attribute. The macro code then generates derived items based on the input. This system ensures +// that the same code path is used for UDL-based code and proc-macros. // // # Differences between UDL-mode and normal mode // @@ -198,47 +183,21 @@ pub fn custom_newtype(tokens: TokenStream) -> TokenStream { // // With proc-macros this system isn't so natural. Instead, we create a blanket implementation // for all UT and support for remote types is still TODO. - #[doc(hidden)] #[proc_macro_attribute] -pub fn derive_record_for_udl(_attrs: TokenStream, input: TokenStream) -> TokenStream { - expand_record(syn::parse_macro_input!(input), true) - .unwrap_or_else(syn::Error::into_compile_error) - .into() -} - -#[doc(hidden)] -#[proc_macro_attribute] -pub fn derive_enum_for_udl(attrs: TokenStream, input: TokenStream) -> TokenStream { - expand_enum( - syn::parse_macro_input!(input), - Some(syn::parse_macro_input!(attrs)), - true, +pub fn udl_derive(attrs: TokenStream, input: TokenStream) -> TokenStream { + derive::expand_derive( + parse_macro_input!(attrs), + parse_macro_input!(input), + DeriveOptions::udl_derive(), ) .unwrap_or_else(syn::Error::into_compile_error) .into() } -#[doc(hidden)] -#[proc_macro_attribute] -pub fn derive_error_for_udl(attrs: TokenStream, input: TokenStream) -> TokenStream { - expand_error( - syn::parse_macro_input!(input), - Some(syn::parse_macro_input!(attrs)), - true, - ) - .unwrap_or_else(syn::Error::into_compile_error) - .into() -} - -#[doc(hidden)] -#[proc_macro_attribute] -pub fn derive_object_for_udl(_attrs: TokenStream, input: TokenStream) -> TokenStream { - expand_object(syn::parse_macro_input!(input), true) - .unwrap_or_else(syn::Error::into_compile_error) - .into() -} - +// Generate export items for UDL mode +// +// This works similarly to `udl_derive`, but for #[export]. #[doc(hidden)] #[proc_macro_attribute] pub fn export_for_udl(attrs: TokenStream, input: TokenStream) -> TokenStream { diff --git a/third_party/rust/uniffi_macros/src/object.rs b/third_party/rust/uniffi_macros/src/object.rs index 6bcc07a14e07..0907bbfd3bf3 100644 --- a/third_party/rust/uniffi_macros/src/object.rs +++ b/third_party/rust/uniffi_macros/src/object.rs @@ -2,16 +2,45 @@ use proc_macro2::{Ident, Span, TokenStream}; use quote::quote; use syn::DeriveInput; -use crate::util::{ - create_metadata_items, extract_docstring, ident_to_string, mod_path, tagged_impl_header, +use crate::{ + ffiops, + util::{create_metadata_items, extract_docstring, ident_to_string, mod_path}, + DeriveOptions, }; use uniffi_meta::ObjectImpl; -pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result { +/// Stores parsed data from the Derive Input for the struct/enum. +struct ObjectItem { + ident: Ident, + docstring: String, +} + +impl ObjectItem { + fn new(input: DeriveInput) -> syn::Result { + Ok(Self { + ident: input.ident, + docstring: extract_docstring(&input.attrs)?, + }) + } + + fn ident(&self) -> &Ident { + &self.ident + } + + fn name(&self) -> String { + ident_to_string(&self.ident) + } + + fn docstring(&self) -> &str { + self.docstring.as_str() + } +} + +pub fn expand_object(input: DeriveInput, options: DeriveOptions) -> syn::Result { let module_path = mod_path()?; - let ident = &input.ident; - let docstring = extract_docstring(&input.attrs)?; - let name = ident_to_string(ident); + let object = ObjectItem::new(input)?; + let name = object.name(); + let ident = object.ident(); let clone_fn_ident = Ident::new( &uniffi_meta::clone_fn_symbol_name(&module_path, &name), Span::call_site(), @@ -20,11 +49,16 @@ pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result syn::Result *const ::std::ffi::c_void { - uniffi::rust_call(call_status, || { + ::uniffi::rust_call(call_status, || { unsafe { ::std::sync::Arc::increment_strong_count(ptr) }; - Ok(ptr) + ::std::result::Result::Ok(ptr) }) } @@ -45,13 +79,13 @@ pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result(); unsafe { ::std::sync::Arc::decrement_strong_count(ptr); } - Ok(()) + ::std::result::Result::Ok(()) }); } @@ -60,22 +94,34 @@ pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result TokenStream { - let name = ident_to_string(ident); - let impl_spec = tagged_impl_header("FfiConverterArc", ident, udl_mode); - let lower_return_impl_spec = tagged_impl_header("LowerReturn", ident, udl_mode); - let lift_ref_impl_spec = tagged_impl_header("LiftRef", ident, udl_mode); +fn interface_impl(object: &ObjectItem, options: &DeriveOptions) -> TokenStream { + let name = object.name(); + let ident = object.ident(); + let impl_spec = options.ffi_impl_header("FfiConverterArc", ident); + let lower_return_impl_spec = options.ffi_impl_header("LowerReturn", ident); + let lower_error_impl_spec = options.ffi_impl_header("LowerError", ident); + let type_id_impl_spec = options.ffi_impl_header("TypeId", ident); + let lift_ref_impl_spec = options.ffi_impl_header("LiftRef", ident); let mod_path = match mod_path() { Ok(p) => p, Err(e) => return e.into_compile_error(), }; + let arc_self_type = quote! { ::std::sync::Arc }; + let lower_arc = ffiops::lower(&arc_self_type); + let type_id_meta_arc = ffiops::type_id_meta(&arc_self_type); + let try_lift_arc = ffiops::try_lift(&arc_self_type); + let lower_return_type_arc = ffiops::lower_return_type(&arc_self_type); + let lower_return_arc = ffiops::lower_return(&arc_self_type); + let lower_error_arc = ffiops::lower_error(&arc_self_type); quote! { // All Object structs must be `Sync + Send`. The generated scaffolding will fail to compile // if they are not, but unfortunately it fails with an unactionably obscure error message. // By asserting the requirement explicitly, we help Rust produce a more scrutable error message // and thus help the user debug why the requirement isn't being met. - uniffi::deps::static_assertions::assert_impl_all!(#ident: ::core::marker::Sync, ::core::marker::Send); + ::uniffi::deps::static_assertions::assert_impl_all!( + #ident: ::core::marker::Sync, ::core::marker::Send + ); #[doc(hidden)] #[automatically_derived] @@ -104,7 +150,7 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream { /// When lifting, we receive an owned `Arc` that the foreign language code cloned. fn try_lift(v: Self::FfiType) -> ::uniffi::Result<::std::sync::Arc> { let v = v as *const #ident; - Ok(unsafe { ::std::sync::Arc::::from_raw(v) }) + ::std::result::Result::Ok(unsafe { ::std::sync::Arc::::from_raw(v) }) } /// When writing as a field of a complex structure, make a clone and transfer ownership @@ -115,9 +161,9 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream { /// Safety: when freeing the resulting pointer, the foreign-language code must /// call the destructor function specific to the type `T`. Calling the destructor /// function for other types may lead to undefined behaviour. - fn write(obj: ::std::sync::Arc, buf: &mut Vec) { + fn write(obj: ::std::sync::Arc, buf: &mut ::std::vec::Vec) { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); - ::uniffi::deps::bytes::BufMut::put_u64(buf, >::lower(obj) as u64); + ::uniffi::deps::bytes::BufMut::put_u64(buf, #lower_arc(obj) as ::std::primitive::u64); } /// When reading as a field of a complex structure, we receive a "borrow" of the `Arc` @@ -128,7 +174,7 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream { fn try_read(buf: &mut &[u8]) -> ::uniffi::Result<::std::sync::Arc> { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); ::uniffi::check_remaining(buf, 8)?; - >::try_lift(::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) + #try_lift_arc(::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_INTERFACE) @@ -137,18 +183,26 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream { } unsafe #lower_return_impl_spec { - type ReturnType = >::FfiType; + type ReturnType = #lower_return_type_arc; - fn lower_return(obj: Self) -> ::std::result::Result { - Ok(>::lower(::std::sync::Arc::new(obj))) + fn lower_return(obj: Self) -> ::std::result::Result { + #lower_return_arc(::std::sync::Arc::new(obj)) } + } - const TYPE_ID_META: ::uniffi::MetadataBuffer = >::TYPE_ID_META; + unsafe #lower_error_impl_spec { + fn lower_error(obj: Self) -> ::uniffi::RustBuffer { + #lower_error_arc(::std::sync::Arc::new(obj)) + } } unsafe #lift_ref_impl_spec { type LiftType = ::std::sync::Arc; } + + #type_id_impl_spec { + const TYPE_ID_META: ::uniffi::MetadataBuffer = #type_id_meta_arc; + } } } @@ -156,7 +210,7 @@ pub(crate) fn interface_meta_static_var( ident: &Ident, imp: ObjectImpl, module_path: &str, - docstring: String, + docstring: &str, ) -> syn::Result { let name = ident_to_string(ident); let code = match imp { diff --git a/third_party/rust/uniffi_macros/src/record.rs b/third_party/rust/uniffi_macros/src/record.rs index 41f5d016aceb..74629d1915cf 100644 --- a/third_party/rust/uniffi_macros/src/record.rs +++ b/third_party/rust/uniffi_macros/src/record.rs @@ -4,35 +4,67 @@ use syn::{parse::ParseStream, Data, DataStruct, DeriveInput, Field, Token}; use crate::{ default::{default_value_metadata_calls, DefaultValue}, + ffiops, util::{ - create_metadata_items, derive_all_ffi_traits, either_attribute_arg, extract_docstring, - ident_to_string, kw, mod_path, tagged_impl_header, try_metadata_value_from_usize, - try_read_field, AttributeSliceExt, UniffiAttributeArgs, + create_metadata_items, either_attribute_arg, extract_docstring, ident_to_string, kw, + mod_path, try_metadata_value_from_usize, try_read_field, AttributeSliceExt, + UniffiAttributeArgs, }, + DeriveOptions, }; -pub fn expand_record(input: DeriveInput, udl_mode: bool) -> syn::Result { +/// Stores parsed data from the Derive Input for the struct. +struct RecordItem { + ident: Ident, + record: DataStruct, + docstring: String, +} + +impl RecordItem { + fn new(input: DeriveInput) -> syn::Result { + let record = match input.data { + Data::Struct(s) => s, + _ => { + return Err(syn::Error::new( + Span::call_site(), + "This derive must only be used on structs", + )); + } + }; + Ok(Self { + ident: input.ident, + record, + docstring: extract_docstring(&input.attrs)?, + }) + } + + fn ident(&self) -> &Ident { + &self.ident + } + + fn name(&self) -> String { + ident_to_string(&self.ident) + } + + fn struct_(&self) -> &DataStruct { + &self.record + } + + fn docstring(&self) -> &str { + self.docstring.as_str() + } +} + +pub fn expand_record(input: DeriveInput, options: DeriveOptions) -> syn::Result { if let Some(e) = input.attrs.uniffi_attr_args_not_allowed_here() { return Err(e); } - let record = match input.data { - Data::Struct(s) => s, - _ => { - return Err(syn::Error::new( - Span::call_site(), - "This derive must only be used on structs", - )); - } - }; - - let ident = &input.ident; - let docstring = extract_docstring(&input.attrs)?; - let ffi_converter = record_ffi_converter_impl(ident, &record, udl_mode) - .unwrap_or_else(syn::Error::into_compile_error); - let meta_static_var = (!udl_mode).then(|| { - record_meta_static_var(ident, docstring, &record) - .unwrap_or_else(syn::Error::into_compile_error) - }); + let record = RecordItem::new(input)?; + let ffi_converter = + record_ffi_converter_impl(&record, &options).unwrap_or_else(syn::Error::into_compile_error); + let meta_static_var = options + .generate_metadata + .then(|| record_meta_static_var(&record).unwrap_or_else(syn::Error::into_compile_error)); Ok(quote! { #ffi_converter @@ -40,17 +72,17 @@ pub fn expand_record(input: DeriveInput, udl_mode: bool) -> syn::Result syn::Result { - let impl_spec = tagged_impl_header("FfiConverter", ident, udl_mode); - let derive_ffi_traits = derive_all_ffi_traits(ident, udl_mode); + let ident = record.ident(); + let impl_spec = options.ffi_impl_header("FfiConverter", ident); + let derive_ffi_traits = options.derive_all_ffi_traits(ident); let name = ident_to_string(ident); let mod_path = mod_path()?; - let write_impl: TokenStream = record.fields.iter().map(write_field).collect(); - let try_read_fields: TokenStream = record.fields.iter().map(try_read_field).collect(); + let write_impl: TokenStream = record.struct_().fields.iter().map(write_field).collect(); + let try_read_fields: TokenStream = record.struct_().fields.iter().map(try_read_field).collect(); Ok(quote! { #[automatically_derived] @@ -62,7 +94,7 @@ pub(crate) fn record_ffi_converter_impl( } fn try_read(buf: &mut &[::std::primitive::u8]) -> ::uniffi::deps::anyhow::Result { - Ok(Self { #try_read_fields }) + ::std::result::Result::Ok(Self { #try_read_fields }) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_RECORD) @@ -76,10 +108,9 @@ pub(crate) fn record_ffi_converter_impl( fn write_field(f: &Field) -> TokenStream { let ident = &f.ident; - let ty = &f.ty; - + let write = ffiops::write(&f.ty); quote! { - <#ty as ::uniffi::Lower>::write(obj.#ident, buf); + #write(obj.#ident, buf); } } @@ -105,17 +136,17 @@ impl UniffiAttributeArgs for FieldAttributeArguments { } } -pub(crate) fn record_meta_static_var( - ident: &Ident, - docstring: String, - record: &DataStruct, -) -> syn::Result { - let name = ident_to_string(ident); +fn record_meta_static_var(record: &RecordItem) -> syn::Result { + let name = record.name(); + let docstring = record.docstring(); let module_path = mod_path()?; - let fields_len = - try_metadata_value_from_usize(record.fields.len(), "UniFFI limits structs to 256 fields")?; + let fields_len = try_metadata_value_from_usize( + record.struct_().fields.len(), + "UniFFI limits structs to 256 fields", + )?; let concat_fields: TokenStream = record + .struct_() .fields .iter() .map(|f| { @@ -125,14 +156,14 @@ pub(crate) fn record_meta_static_var( let name = ident_to_string(f.ident.as_ref().unwrap()); let docstring = extract_docstring(&f.attrs)?; - let ty = &f.ty; let default = default_value_metadata_calls(&attrs.default)?; + let type_id_meta = ffiops::type_id_meta(&f.ty); // Note: fields need to implement both `Lower` and `Lift` to be used in a record. The // TYPE_ID_META should be the same for both traits. Ok(quote! { .concat_str(#name) - .concat(<#ty as ::uniffi::Lower>::TYPE_ID_META) + .concat(#type_id_meta) #default .concat_long_str(#docstring) }) diff --git a/third_party/rust/uniffi_macros/src/setup_scaffolding.rs b/third_party/rust/uniffi_macros/src/setup_scaffolding.rs index c82e9389bb61..83bb5ce83b67 100644 --- a/third_party/rust/uniffi_macros/src/setup_scaffolding.rs +++ b/third_party/rust/uniffi_macros/src/setup_scaffolding.rs @@ -36,7 +36,7 @@ pub fn setup_scaffolding(namespace: String) -> Result { #[allow(clippy::missing_safety_doc, missing_docs)] #[doc(hidden)] #[no_mangle] - pub extern "C" fn #ffi_contract_version_ident() -> u32 { + pub extern "C" fn #ffi_contract_version_ident() -> ::std::primitive::u32 { #UNIFFI_CONTRACT_VERSION } @@ -45,13 +45,15 @@ pub fn setup_scaffolding(namespace: String) -> Result { /// /// See `uniffi_bindgen::macro_metadata` for how this is used. - const #namespace_const_ident: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::NAMESPACE) - .concat_str(#module_path) - .concat_str(#namespace); + const #namespace_const_ident: ::uniffi::MetadataBuffer = + ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::NAMESPACE) + .concat_str(#module_path) + .concat_str(#namespace); #[doc(hidden)] #[no_mangle] - pub static #namespace_static_ident: [u8; #namespace_const_ident.size] = #namespace_const_ident.into_array(); + pub static #namespace_static_ident: [::std::primitive::u8; #namespace_const_ident.size] = + #namespace_const_ident.into_array(); // Everybody gets basic buffer support, since it's needed for passing complex types over the FFI. // @@ -60,29 +62,42 @@ pub fn setup_scaffolding(namespace: String) -> Result { #[allow(clippy::missing_safety_doc, missing_docs)] #[doc(hidden)] #[no_mangle] - pub extern "C" fn #ffi_rustbuffer_alloc_ident(size: u64, call_status: &mut uniffi::RustCallStatus) -> uniffi::RustBuffer { - uniffi::ffi::uniffi_rustbuffer_alloc(size, call_status) + pub extern "C" fn #ffi_rustbuffer_alloc_ident( + size: ::std::primitive::u64, + call_status: &mut ::uniffi::RustCallStatus, + ) -> ::uniffi::RustBuffer { + ::uniffi::ffi::uniffi_rustbuffer_alloc(size, call_status) } #[allow(clippy::missing_safety_doc, missing_docs)] #[doc(hidden)] #[no_mangle] - pub unsafe extern "C" fn #ffi_rustbuffer_from_bytes_ident(bytes: uniffi::ForeignBytes, call_status: &mut uniffi::RustCallStatus) -> uniffi::RustBuffer { - uniffi::ffi::uniffi_rustbuffer_from_bytes(bytes, call_status) + pub unsafe extern "C" fn #ffi_rustbuffer_from_bytes_ident( + bytes: ::uniffi::ForeignBytes, + call_status: &mut ::uniffi::RustCallStatus, + ) -> ::uniffi::RustBuffer { + ::uniffi::ffi::uniffi_rustbuffer_from_bytes(bytes, call_status) } #[allow(clippy::missing_safety_doc, missing_docs)] #[doc(hidden)] #[no_mangle] - pub unsafe extern "C" fn #ffi_rustbuffer_free_ident(buf: uniffi::RustBuffer, call_status: &mut uniffi::RustCallStatus) { - uniffi::ffi::uniffi_rustbuffer_free(buf, call_status); + pub unsafe extern "C" fn #ffi_rustbuffer_free_ident( + buf: ::uniffi::RustBuffer, + call_status: &mut ::uniffi::RustCallStatus, + ) { + ::uniffi::ffi::uniffi_rustbuffer_free(buf, call_status); } #[allow(clippy::missing_safety_doc, missing_docs)] #[doc(hidden)] #[no_mangle] - pub unsafe extern "C" fn #ffi_rustbuffer_reserve_ident(buf: uniffi::RustBuffer, additional: u64, call_status: &mut uniffi::RustCallStatus) -> uniffi::RustBuffer { - uniffi::ffi::uniffi_rustbuffer_reserve(buf, additional, call_status) + pub unsafe extern "C" fn #ffi_rustbuffer_reserve_ident( + buf: ::uniffi::RustBuffer, + additional: ::std::primitive::u64, + call_status: &mut ::uniffi::RustCallStatus, + ) -> ::uniffi::RustBuffer { + ::uniffi::ffi::uniffi_rustbuffer_reserve(buf, additional, call_status) } #ffi_rust_future_scaffolding_fns @@ -121,7 +136,9 @@ pub fn setup_scaffolding(namespace: String) -> Result { #[doc(hidden)] pub trait UniffiCustomTypeConverter { type Builtin; - fn into_custom(val: Self::Builtin) -> uniffi::Result where Self: Sized; + fn into_custom(val: Self::Builtin) -> ::uniffi::Result + where + Self: ::std::marker::Sized; fn from_custom(obj: Self) -> Self::Builtin; } }) diff --git a/third_party/rust/uniffi_macros/src/test.rs b/third_party/rust/uniffi_macros/src/test.rs index da7a343dbc79..e6ae142ce15f 100644 --- a/third_party/rust/uniffi_macros/src/test.rs +++ b/third_party/rust/uniffi_macros/src/test.rs @@ -30,16 +30,16 @@ pub(crate) fn build_foreign_language_testcases(tokens: TokenStream) -> TokenStre ); let run_test = match test_file_pathbuf.extension() { Some("kts") => quote! { - uniffi::kotlin_run_test + ::uniffi::kotlin_test::run_test }, Some("swift") => quote! { - uniffi::swift_run_test + ::uniffi::swift_test::run_test }, Some("py") => quote! { - uniffi::python_run_test + ::uniffi::python_test::run_test }, Some("rb") => quote! { - uniffi::ruby_run_test + ::uniffi::ruby_test::run_test }, _ => panic!("Unexpected extension for test script: {test_file_name}"), }; @@ -51,7 +51,7 @@ pub(crate) fn build_foreign_language_testcases(tokens: TokenStream) -> TokenStre quote! { #maybe_ignore #[test] - fn #test_name () -> uniffi::deps::anyhow::Result<()> { + fn #test_name () -> ::uniffi::deps::anyhow::Result<()> { #run_test( std::env!("CARGO_TARGET_TMPDIR"), std::env!("CARGO_PKG_NAME"), diff --git a/third_party/rust/uniffi_macros/src/util.rs b/third_party/rust/uniffi_macros/src/util.rs index cf4727e2f169..6f6214208b5f 100644 --- a/third_party/rust/uniffi_macros/src/util.rs +++ b/third_party/rust/uniffi_macros/src/util.rs @@ -2,6 +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::ffiops; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, ToTokens}; use std::path::{Path as StdPath, PathBuf}; @@ -77,14 +78,14 @@ pub fn mod_path() -> syn::Result { pub fn try_read_field(f: &syn::Field) -> TokenStream { let ident = &f.ident; - let ty = &f.ty; + let try_read = ffiops::try_read(&f.ty); match ident { Some(ident) => quote! { - #ident: <#ty as ::uniffi::Lift>::try_read(buf)?, + #ident: #try_read(buf)?, }, None => quote! { - <#ty as ::uniffi::Lift>::try_read(buf)?, + #try_read(buf)?, }, } } @@ -257,6 +258,10 @@ pub mod kw { syn::custom_keyword!(with_try_read); syn::custom_keyword!(name); syn::custom_keyword!(non_exhaustive); + syn::custom_keyword!(Record); + syn::custom_keyword!(Enum); + syn::custom_keyword!(Error); + syn::custom_keyword!(Object); syn::custom_keyword!(Debug); syn::custom_keyword!(Display); syn::custom_keyword!(Eq); diff --git a/third_party/rust/uniffi_meta/.cargo-checksum.json b/third_party/rust/uniffi_meta/.cargo-checksum.json index 502599706d1c..d365e379fe7f 100644 --- a/third_party/rust/uniffi_meta/.cargo-checksum.json +++ b/third_party/rust/uniffi_meta/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"3d53a00cb590863149f9e68505581ccbfc635ac1bb2b59d692f5d679cd1732bc","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/ffi_names.rs":"240e04f257fd199e268ff16d5979f521cb9d18e21d494981718fa2b96956324d","src/group.rs":"d0a43f3c528aba9403649715981ad3a8849d7a370f4ef9e2d618b88f60a3102f","src/lib.rs":"3f00d5214e2785e4b3045bc48899f6f6b1dce32ab3da6be3ebce716ee9d24c5f","src/metadata.rs":"3f236b337a1fd5082ea9cc4fee6800193a903ee88b81f1c3202843402f122a14","src/reader.rs":"579e2b87d8dd9d703b8811294abfb992621c0a46765800e4db2fad2906db2208","src/types.rs":"c2c5188da8cdf5af7f8496d4660bcfaa971b81ed73b64486c05b47256048544f"},"package":"583bab49f2bdf5681f9732f8b67a7e555ad920dbb5427be21450217bf1818189"} \ No newline at end of file +{"files":{"Cargo.toml":"b47c5c8446e1910ac250037c30c98407e25868a6fb91440975674a2c88217394","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/ffi_names.rs":"240e04f257fd199e268ff16d5979f521cb9d18e21d494981718fa2b96956324d","src/group.rs":"d0a43f3c528aba9403649715981ad3a8849d7a370f4ef9e2d618b88f60a3102f","src/lib.rs":"2e1a7829bcb63c83b21def1233fdf0a50d27230e5b7253d0a8944e243084e8b4","src/metadata.rs":"3f236b337a1fd5082ea9cc4fee6800193a903ee88b81f1c3202843402f122a14","src/reader.rs":"cc6f93c92ef53646595bea75b7e0ec719713e9af3e1b38d77d49a40c5ae4d092","src/types.rs":"1ebc50d050b12a002738fd3bf2a4eac2853b7c495d394c16020d1e6f2f232f9a"},"package":"d898893f102e0e39b8bcb7e3d2188f4156ba280db32db9e8af1f122d057e9526"} \ No newline at end of file diff --git a/third_party/rust/uniffi_meta/Cargo.toml b/third_party/rust/uniffi_meta/Cargo.toml index a862028f0ef1..5db136fcb15c 100644 --- a/third_party/rust/uniffi_meta/Cargo.toml +++ b/third_party/rust/uniffi_meta/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_meta" -version = "0.27.3" +version = "0.28.1" description = "uniffi_meta" homepage = "https://mozilla.github.io/uniffi-rs" readme = "README.md" @@ -33,4 +33,4 @@ version = "1.3" version = "0.3" [dependencies.uniffi_checksum_derive] -version = "0.27.3" +version = "0.28.1" diff --git a/third_party/rust/uniffi_meta/src/lib.rs b/third_party/rust/uniffi_meta/src/lib.rs index 90f7b2d3cdcf..5d8d25543131 100644 --- a/third_party/rust/uniffi_meta/src/lib.rs +++ b/third_party/rust/uniffi_meta/src/lib.rs @@ -309,11 +309,36 @@ pub struct FieldMetadata { pub docstring: Option, } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Checksum)] +pub enum EnumShape { + Enum, + Error { flat: bool }, +} + +impl EnumShape { + pub fn as_u8(&self) -> u8 { + match self { + EnumShape::Enum => 0, + EnumShape::Error { flat: false } => 1, + EnumShape::Error { flat: true } => 2, + } + } + + pub fn from(v: u8) -> anyhow::Result { + Ok(match v { + 0 => EnumShape::Enum, + 1 => EnumShape::Error { flat: false }, + 2 => EnumShape::Error { flat: true }, + _ => anyhow::bail!("invalid enum shape discriminant {v}"), + }) + } +} + #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct EnumMetadata { pub module_path: String, pub name: String, - pub forced_flatness: Option, + pub shape: EnumShape, pub variants: Vec, pub discr_type: Option, pub non_exhaustive: bool, diff --git a/third_party/rust/uniffi_meta/src/reader.rs b/third_party/rust/uniffi_meta/src/reader.rs index 6fec6cb3a359..85a34cb19799 100644 --- a/third_party/rust/uniffi_meta/src/reader.rs +++ b/third_party/rust/uniffi_meta/src/reader.rs @@ -259,7 +259,7 @@ impl<'a> MetadataReader<'a> { Type::Object { name, imp: ObjectImpl::Struct, .. } if name == &self_name ) }) - .context("Constructor return type must be Arc")?; + .context("Constructor return type must be Self or Arc")?; Ok(ConstructorMetadata { module_path, @@ -307,27 +307,21 @@ impl<'a> MetadataReader<'a> { fn read_enum(&mut self) -> Result { let module_path = self.read_string()?; let name = self.read_string()?; - let forced_flatness = match self.read_u8()? { - 0 => None, - 1 => Some(false), - 2 => Some(true), - _ => unreachable!("invalid flatness"), - }; + let shape = EnumShape::from(self.read_u8()?)?; let discr_type = if self.read_bool()? { Some(self.read_type()?) } else { None }; - let variants = if forced_flatness == Some(true) { - self.read_flat_variants()? - } else { - self.read_variants()? + let variants = match shape { + EnumShape::Enum | EnumShape::Error { flat: false } => self.read_variants()?, + EnumShape::Error { flat: true } => self.read_flat_variants()?, }; Ok(EnumMetadata { module_path, name, - forced_flatness, + shape, discr_type, variants, non_exhaustive: self.read_bool()?, diff --git a/third_party/rust/uniffi_meta/src/types.rs b/third_party/rust/uniffi_meta/src/types.rs index 51bf156b50b1..7fe55d81ac0c 100644 --- a/third_party/rust/uniffi_meta/src/types.rs +++ b/third_party/rust/uniffi_meta/src/types.rs @@ -143,10 +143,59 @@ impl Type { }; Box::new(std::iter::once(self).chain(nested_types)) } + + pub fn name(&self) -> Option { + match self { + Type::Object { name, .. } => Some(name.to_string()), + Type::Record { name, .. } => Some(name.to_string()), + Type::Enum { name, .. } => Some(name.to_string()), + Type::External { name, .. } => Some(name.to_string()), + Type::Custom { name, .. } => Some(name.to_string()), + Type::Optional { inner_type } | Type::Sequence { inner_type } => inner_type.name(), + _ => None, + } + } + + fn rename(&mut self, new_name: String) { + match self { + Type::Object { name, .. } => *name = new_name, + Type::Record { name, .. } => *name = new_name, + Type::Enum { name, .. } => *name = new_name, + Type::External { name, .. } => *name = new_name, + Type::Custom { name, .. } => *name = new_name, + _ => {} + } + } + + pub fn rename_recursive(&mut self, name_transformer: &impl Fn(&str) -> String) { + // Rename the current type if it has a name + if let Some(name) = self.name() { + self.rename(name_transformer(&name)); + } + + // Recursively rename nested types + match self { + Type::Optional { inner_type } | Type::Sequence { inner_type } => { + inner_type.rename_recursive(name_transformer); + } + Type::Map { + key_type, + value_type, + .. + } => { + key_type.rename_recursive(name_transformer); + value_type.rename_recursive(name_transformer); + } + Type::Custom { builtin, .. } => { + builtin.rename_recursive(name_transformer); + } + _ => {} + } + } } // A trait so various things can turn into a type. -pub trait AsType: core::fmt::Debug { +pub trait AsType: ::core::fmt::Debug { fn as_type(&self) -> Type; } diff --git a/third_party/rust/uniffi_testing/.cargo-checksum.json b/third_party/rust/uniffi_testing/.cargo-checksum.json index 0ede9fda96d5..62f01a9e7a01 100644 --- a/third_party/rust/uniffi_testing/.cargo-checksum.json +++ b/third_party/rust/uniffi_testing/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"02452729580c718585b4cc1cbaa2d09aa97ebec62c4d0bd3fdb50d6063cfe036","README.md":"ec6aba24af9a011ef6647422aa22efabdee519cdee3da1a9f9033b07b7cbdb0d","src/lib.rs":"e19f60aed5a137401203b9054ead27894b98490bab3e2f680a23549c8ee8a13a"},"package":"13963044ca9bde9b709d2eee68bc11dafc7acea144ae0fdc0cf29ed4add44481"} \ No newline at end of file +{"files":{"Cargo.toml":"54b381ea1c0f0a85bff9a31e52f2ca58d1c5bfb42b4545df3d503144f79ea31d","README.md":"ec6aba24af9a011ef6647422aa22efabdee519cdee3da1a9f9033b07b7cbdb0d","src/lib.rs":"8e0818381a8f90acecf9d82ce914c06948b7fb1f4513babac54880c62f7667c3"},"package":"2c6aa4f0cf9d12172d84fc00a35a6c1f3522b526daad05ae739f709f6941b9b6"} \ No newline at end of file diff --git a/third_party/rust/uniffi_testing/Cargo.toml b/third_party/rust/uniffi_testing/Cargo.toml index c511869e3120..903e7dab7681 100644 --- a/third_party/rust/uniffi_testing/Cargo.toml +++ b/third_party/rust/uniffi_testing/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_testing" -version = "0.27.3" +version = "0.28.1" authors = ["Firefox Sync Team "] description = "a multi-language bindings generator for rust (testing helpers)" homepage = "https://mozilla.github.io/uniffi-rs" diff --git a/third_party/rust/uniffi_testing/src/lib.rs b/third_party/rust/uniffi_testing/src/lib.rs index f8a0d8499a1c..444a7f8146eb 100644 --- a/third_party/rust/uniffi_testing/src/lib.rs +++ b/third_party/rust/uniffi_testing/src/lib.rs @@ -37,17 +37,15 @@ static CARGO_BUILD_MESSAGES: Lazy> = Lazy::new(get_cargo_build_mess /// - The fixture crate produces a cdylib library /// - The fixture crate, and any external-crates, has 1 UDL file in it's src/ directory pub struct UniFFITestHelper { - name: String, - package: Package, + crate_name: String, + cdylib: Utf8PathBuf, } impl UniFFITestHelper { - pub fn new(name: &str) -> Result { - let package = Self::find_package(name)?; - Ok(Self { - name: name.to_string(), - package, - }) + pub fn new(package_name: &str) -> Result { + let package = Self::find_package(package_name)?; + let (crate_name, cdylib) = Self::find_name_and_cdylib_path(&package)?; + Ok(Self { crate_name, cdylib }) } fn find_package(name: &str) -> Result { @@ -62,7 +60,7 @@ impl UniFFITestHelper { } } - fn find_cdylib_path(package: &Package) -> Result { + fn find_name_and_cdylib_path(package: &Package) -> Result<(String, Utf8PathBuf)> { let cdylib_targets: Vec<&Target> = package .targets .iter() @@ -72,6 +70,7 @@ impl UniFFITestHelper { 1 => cdylib_targets[0], n => bail!("Found {n} cdylib targets for {}", package.name), }; + let target_name = target.name.replace('-', "_"); let artifacts = CARGO_BUILD_MESSAGES .iter() @@ -97,7 +96,7 @@ impl UniFFITestHelper { .collect(); match cdylib_files.len() { - 1 => Ok(cdylib_files[0].to_owned()), + 1 => Ok((target_name, cdylib_files[0].to_owned())), n => bail!("Found {n} cdylib files for {}", package.name), } } @@ -119,7 +118,7 @@ impl UniFFITestHelper { temp_dir: impl AsRef, script_path: impl AsRef, ) -> Result { - let dirname = format!("{}-{}", self.name, hash_path(script_path.as_ref())); + let dirname = format!("{}-{}", self.crate_name, hash_path(script_path.as_ref())); let out_dir = temp_dir.as_ref().join(dirname); if out_dir.exists() { // Clean out any files from previous runs @@ -144,7 +143,15 @@ impl UniFFITestHelper { /// Get the path to the cdylib file for this package pub fn cdylib_path(&self) -> Result { - Self::find_cdylib_path(&self.package) + Ok(self.cdylib.clone()) + } + + pub fn crate_name(&self) -> &str { + &self.crate_name + } + + pub fn cargo_metadata(&self) -> Metadata { + CARGO_METADATA.clone() } } @@ -156,7 +163,8 @@ fn get_cargo_metadata() -> Metadata { fn get_cargo_build_messages() -> Vec { let mut child = Command::new(env!("CARGO")) - .arg("build") + .arg("test") + .arg("--no-run") .arg("--message-format=json") .stdout(Stdio::piped()) .spawn() diff --git a/third_party/rust/uniffi_udl/.cargo-checksum.json b/third_party/rust/uniffi_udl/.cargo-checksum.json index a64cb6f3c2f7..d851b85885d5 100644 --- a/third_party/rust/uniffi_udl/.cargo-checksum.json +++ b/third_party/rust/uniffi_udl/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"eda87b82f785000e7ac4d07d24285dc5a961d8109bd90dfd134f8545a86f3b56","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/attributes.rs":"f1cdee01db837920dbd109d60b39dd4b0ece56f83797fe4ace1e0caf97c02483","src/collectors.rs":"00c9cd8e8f7be6949996f069b449f120f0b0694ff2f1ca92b79201721c18c594","src/converters/callables.rs":"1ad26c2782629e98272edc75c38343f58194ebf9626ae451ba84546a60d45a48","src/converters/enum_.rs":"aa0ca7a7a50521a45e296c6f53be5f1981a41872443946f72c2ca8baebe4d69b","src/converters/interface.rs":"6042d4abd5e236ed6158c5f6d4d9b81bb01fbbcb8b42bf8a5b385b978c68f6f8","src/converters/mod.rs":"c34a30e3b7a2e3c092a7074f4bab6f6c34364177c096af59a7dda13e44ffdc3c","src/finder.rs":"3586ffd3772151eabbc3d6062725933c88978e1b5feb64312bbf42cd43af30fa","src/lib.rs":"56c50ce61ba5e7266fe7fc9fa9d0022cdbfbe9801730753bd4ee66fed040221c","src/literal.rs":"4f28ad49a17246b4dc30a677cfff65b345bfac0924856e19f58e7574a74c2c40","src/resolver.rs":"c4ff362055dc4ed489e94a063ec0fd3becb8787ad35ce65cdec437a1aae518a0"},"package":"b92f984bb0d9a06778f256aec963e1e9a80714014f7a90fb0e01008821fe5a97"} \ No newline at end of file +{"files":{"Cargo.toml":"05a239cc9313d8b4164ab3d3c2cb86fdaaa0cedf728d5bc0c74ec247067aaca9","README.md":"37c1af00ec81a9f1bc206ab3578356e5f9ad4077dc46dd1bb623d81d804948b8","src/attributes.rs":"309292afc2ba936bbe7bae3af13ee58a507ca0e11bde3e3294daa4952fd8126c","src/collectors.rs":"408615354c316767adb20aa29faadc5ef5f06674c0f1b2fc7286cc70e294f459","src/converters/callables.rs":"1ad26c2782629e98272edc75c38343f58194ebf9626ae451ba84546a60d45a48","src/converters/enum_.rs":"33820452744c071097d745cb931479698eb624e62a8d8fd2baa3dd4545cc0f9b","src/converters/interface.rs":"6042d4abd5e236ed6158c5f6d4d9b81bb01fbbcb8b42bf8a5b385b978c68f6f8","src/converters/mod.rs":"c34a30e3b7a2e3c092a7074f4bab6f6c34364177c096af59a7dda13e44ffdc3c","src/finder.rs":"8eb964514325ee9fc739e5a9b1ac009e61faae0cf7eb4f54f58b80f6ce7bcf64","src/lib.rs":"56c50ce61ba5e7266fe7fc9fa9d0022cdbfbe9801730753bd4ee66fed040221c","src/literal.rs":"4f28ad49a17246b4dc30a677cfff65b345bfac0924856e19f58e7574a74c2c40","src/resolver.rs":"c4ff362055dc4ed489e94a063ec0fd3becb8787ad35ce65cdec437a1aae518a0"},"package":"6b044e9c519e0bb51e516ab6f6d8f4f4dcf900ce30d5ad07c03f924e2824f28e"} \ No newline at end of file diff --git a/third_party/rust/uniffi_udl/Cargo.toml b/third_party/rust/uniffi_udl/Cargo.toml index f202383db2ea..99bd7ebdcf41 100644 --- a/third_party/rust/uniffi_udl/Cargo.toml +++ b/third_party/rust/uniffi_udl/Cargo.toml @@ -12,7 +12,7 @@ [package] edition = "2021" name = "uniffi_udl" -version = "0.27.3" +version = "0.28.1" description = "udl parsing for the uniffi project" homepage = "https://mozilla.github.io/uniffi-rs" documentation = "https://mozilla.github.io/uniffi-rs" @@ -33,10 +33,10 @@ features = ["smawk"] default-features = false [dependencies.uniffi_meta] -version = "=0.27.3" +version = "=0.28.1" [dependencies.uniffi_testing] -version = "=0.27.3" +version = "=0.28.1" [dependencies.weedle2] version = "5.0.0" diff --git a/third_party/rust/uniffi_udl/src/attributes.rs b/third_party/rust/uniffi_udl/src/attributes.rs index 7bb05808c484..a40ef29fdb80 100644 --- a/third_party/rust/uniffi_udl/src/attributes.rs +++ b/third_party/rust/uniffi_udl/src/attributes.rs @@ -856,11 +856,11 @@ mod test { fn test_byref_attribute() { let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[ByRef]").unwrap(); let attrs = ArgumentAttributes::try_from(&node).unwrap(); - assert!(matches!(attrs.by_ref(), true)); + assert!(attrs.by_ref()); let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[]").unwrap(); let attrs = ArgumentAttributes::try_from(&node).unwrap(); - assert!(matches!(attrs.by_ref(), false)); + assert!(!attrs.by_ref()); } #[test] @@ -898,15 +898,15 @@ mod test { fn test_enum_attribute_on_interface() { let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Enum]").unwrap(); let attrs = InterfaceAttributes::try_from(&node).unwrap(); - assert!(matches!(attrs.contains_enum_attr(), true)); + assert!(attrs.contains_enum_attr()); let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[]").unwrap(); let attrs = InterfaceAttributes::try_from(&node).unwrap(); - assert!(matches!(attrs.contains_enum_attr(), false)); + assert!(!attrs.contains_enum_attr()); let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Trait]").unwrap(); let attrs = InterfaceAttributes::try_from(&node).unwrap(); - assert!(matches!(attrs.contains_enum_attr(), false)); + assert!(!attrs.contains_enum_attr()); let (_, node) = weedle::attribute::ExtendedAttributeList::parse("[Trait, Enum]").unwrap(); let err = InterfaceAttributes::try_from(&node).unwrap_err(); diff --git a/third_party/rust/uniffi_udl/src/collectors.rs b/third_party/rust/uniffi_udl/src/collectors.rs index de5489f5f9a4..e29441611216 100644 --- a/third_party/rust/uniffi_udl/src/collectors.rs +++ b/third_party/rust/uniffi_udl/src/collectors.rs @@ -172,12 +172,7 @@ impl APIBuilder for weedle::Definition<'_> { match self { weedle::Definition::Namespace(d) => d.process(ci)?, weedle::Definition::Enum(d) => { - let mut e: uniffi_meta::EnumMetadata = d.convert(ci)?; - // We check if the enum represents an error... - let attrs = attributes::EnumAttributes::try_from(d.attributes.as_ref())?; - if attrs.contains_error_attr() { - e.forced_flatness = Some(true); - } + let e: uniffi_meta::EnumMetadata = d.convert(ci)?; ci.add_definition(e.into())?; } weedle::Definition::Dictionary(d) => { diff --git a/third_party/rust/uniffi_udl/src/converters/enum_.rs b/third_party/rust/uniffi_udl/src/converters/enum_.rs index 1615a1a7ca89..d2dc7f3d3c84 100644 --- a/third_party/rust/uniffi_udl/src/converters/enum_.rs +++ b/third_party/rust/uniffi_udl/src/converters/enum_.rs @@ -6,7 +6,7 @@ use super::APIConverter; use crate::{attributes::EnumAttributes, converters::convert_docstring, InterfaceCollector}; use anyhow::{bail, Result}; -use uniffi_meta::{EnumMetadata, VariantMetadata}; +use uniffi_meta::{EnumMetadata, EnumShape, VariantMetadata}; // Note that we have 2 `APIConverter` impls here - one for the `enum` case // (including an enum with `[Error]`), and one for the `[Error] interface` cas @@ -14,10 +14,15 @@ use uniffi_meta::{EnumMetadata, VariantMetadata}; impl APIConverter for weedle::EnumDefinition<'_> { fn convert(&self, ci: &mut InterfaceCollector) -> Result { let attributes = EnumAttributes::try_from(self.attributes.as_ref())?; + let shape = if attributes.contains_error_attr() { + EnumShape::Error { flat: true } + } else { + EnumShape::Enum + }; Ok(EnumMetadata { module_path: ci.module_path(), name: self.identifier.0.to_string(), - forced_flatness: None, + shape, discr_type: None, variants: self .values @@ -45,10 +50,15 @@ impl APIConverter for weedle::InterfaceDefinition<'_> { bail!("interface inheritance is not supported for enum interfaces"); } let attributes = EnumAttributes::try_from(self.attributes.as_ref())?; + let shape = if attributes.contains_error_attr() { + EnumShape::Error { flat: false } + } else { + EnumShape::Enum + }; Ok(EnumMetadata { module_path: ci.module_path(), name: self.identifier.0.to_string(), - forced_flatness: Some(false), + shape, variants: self .members .body diff --git a/third_party/rust/uniffi_udl/src/finder.rs b/third_party/rust/uniffi_udl/src/finder.rs index 259557ad07e4..6a2b6084b8bb 100644 --- a/third_party/rust/uniffi_udl/src/finder.rs +++ b/third_party/rust/uniffi_udl/src/finder.rs @@ -129,43 +129,89 @@ impl TypeFinder for weedle::TypedefDefinition<'_> { }, ) } else { + let typedef_type = match &self.type_.type_ { + weedle::types::Type::Single(weedle::types::SingleType::NonAny( + weedle::types::NonAnyType::Identifier(weedle::types::MayBeNull { + type_: i, + .. + }), + )) => i.0, + _ => bail!("Failed to get typedef type: {:?}", self), + }; + let module_path = types.module_path(); let name = self.identifier.0.to_string(); - let ty = match attrs.rust_kind() { - Some(RustKind::Object) => Type::Object { - module_path, - name, - imp: ObjectImpl::Struct, - }, - Some(RustKind::Trait) => Type::Object { - module_path, - name, - imp: ObjectImpl::Trait, - }, - Some(RustKind::CallbackTrait) => Type::Object { - module_path, - name, - imp: ObjectImpl::CallbackTrait, - }, - Some(RustKind::Record) => Type::Record { module_path, name }, - Some(RustKind::Enum) => Type::Enum { module_path, name }, - Some(RustKind::CallbackInterface) => Type::CallbackInterface { module_path, name }, - // must be external + + let ty = match attrs.external_tagged() { None => { - let kind = attrs.external_kind().expect("External missing kind"); - let tagged = attrs.external_tagged().expect("External missing tagged"); - Type::External { - name, - namespace: "".to_string(), // we don't know this yet - module_path: attrs.get_crate_name(), - kind, - tagged, + // Not external, not custom, not Rust - so we basically + // pretend it is Rust, thus soft-deprecating it. + // We use `type_` + match typedef_type { + "dictionary" | "record" | "struct" => Type::Record { + module_path, + name, + }, + "enum" => Type::Enum { + module_path, + name, + }, + "custom" => panic!("don't know builtin"), + "interface" | "impl" => Type::Object { + module_path, + name, + imp: ObjectImpl::Struct, + }, + "trait" => Type::Object { + module_path, + name, + imp: ObjectImpl::Trait, + }, + "callback" | "trait_with_foreign" => Type::Object { + module_path, + name, + imp: ObjectImpl::CallbackTrait, + }, + _ => bail!("Can't work out the type - no attributes and unknown extern type '{typedef_type}'"), + } + } + Some(tagged) => { + // Must be either `[Rust..]` or `[Extern..]` + match attrs.rust_kind() { + Some(RustKind::Object) => Type::Object { + module_path, + name, + imp: ObjectImpl::Struct, + }, + Some(RustKind::Trait) => Type::Object { + module_path, + name, + imp: ObjectImpl::Trait, + }, + Some(RustKind::CallbackTrait) => Type::Object { + module_path, + name, + imp: ObjectImpl::CallbackTrait, + }, + Some(RustKind::Record) => Type::Record { module_path, name }, + Some(RustKind::Enum) => Type::Enum { module_path, name }, + Some(RustKind::CallbackInterface) => { + Type::CallbackInterface { module_path, name } + } + // must be external + None => { + let kind = attrs.external_kind().expect("External missing kind"); + Type::External { + name, + namespace: "".to_string(), // we don't know this yet + module_path: attrs.get_crate_name(), + kind, + tagged, + } + } } } }; - // A crate which can supply an `FfiConverter`. - // We don't reference `self._type`, so ideally we could insist on it being - // the literal 'extern' but that's tricky types.add_type_definition(self.identifier.0, ty) } } @@ -190,7 +236,7 @@ impl TypeFinder for weedle::CallbackInterfaceDefinition<'_> { #[cfg(test)] mod test { use super::*; - use uniffi_meta::ExternalKind; + use uniffi_meta::{ExternalKind, ObjectImpl}; // A helper to take valid UDL and a closure to check what's in it. fn test_a_finding(udl: &str, tester: F) @@ -289,6 +335,74 @@ mod test { ); } + #[test] + fn test_extern_local_types() { + // should test more, but these are already deprecated + test_a_finding( + r#" + typedef interface Interface; + typedef impl Interface2; + typedef trait Trait; + typedef callback Callback; + + typedef dictionary R1; + typedef record R2; + typedef record R3; + typedef enum Enum; + "#, + |types| { + assert!(matches!( + types.get_type_definition("Interface").unwrap(), + Type::Object { name, module_path, imp: ObjectImpl::Struct } if name == "Interface" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("Interface2").unwrap(), + Type::Object { name, module_path, imp: ObjectImpl::Struct } if name == "Interface2" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("Trait").unwrap(), + Type::Object { name, module_path, imp: ObjectImpl::Trait } if name == "Trait" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("Callback").unwrap(), + Type::Object { name, module_path, imp: ObjectImpl::CallbackTrait } if name == "Callback" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("R1").unwrap(), + Type::Record { name, module_path } if name == "R1" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("R2").unwrap(), + Type::Record { name, module_path } if name == "R2" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("R3").unwrap(), + Type::Record { name, module_path } if name == "R3" && module_path.is_empty())); + assert!(matches!( + types.get_type_definition("Enum").unwrap(), + Type::Enum { name, module_path } if name == "Enum" && module_path.is_empty())); + }, + ); + } + + #[test] + fn test_rust_attr_types() { + // should test more, but these are already deprecated + test_a_finding( + r#" + [Rust="interface"] + typedef extern LocalInterface; + + [Rust="dictionary"] + typedef extern Dict; + "#, + |types| { + assert!( + matches!(types.get_type_definition("LocalInterface").unwrap(), Type::Object { name, module_path, imp: ObjectImpl::Struct } + if name == "LocalInterface" && module_path.is_empty()) + ); + assert!( + matches!(types.get_type_definition("Dict").unwrap(), Type::Record { name, module_path } + if name == "Dict" && module_path.is_empty()) + ); + }, + ); + } + fn get_err(udl: &str) -> String { let parsed = weedle::parse(udl).unwrap(); let mut types = TypeCollector::default(); @@ -299,9 +413,8 @@ mod test { } #[test] - #[should_panic] - fn test_typedef_error_on_no_attr() { - // Sorry, still working out what we want for non-imported typedefs.. - get_err("typedef string Custom;"); + fn test_local_type_unknown_typedef() { + let e = get_err("typedef xyz Foo;"); + assert!(e.contains("unknown extern type 'xyz'")); } } diff --git a/third_party/rust/webext-storage/.cargo-checksum.json b/third_party/rust/webext-storage/.cargo-checksum.json index cbfa3c54246d..5ee582011067 100644 --- a/third_party/rust/webext-storage/.cargo-checksum.json +++ b/third_party/rust/webext-storage/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"81b4e03b6df32859fabe75be2a86051e4646b2eac61d610323beb780b7f7574b","README.md":"821cac7eb5b963fc3f3fe21dd890427ab2bbf335cb25cbae89b713b3350687c5","build.rs":"92f7d380f3d8fab1e6d80276915af57192e276321d132a5f800ea4520e9cb469","sql/create_schema.sql":"a17311a407ec10e033886b7125da4c8b84bc6d761f6b28edc9594de430e1d964","sql/create_sync_temp_tables.sql":"860ede362c94feb47d85522553fa2852f9bdb9f9b025d6438dd5dee3d4acd527","sql/tests/create_schema_v1.sql":"77cf0c90eaac3e1aea626537147e1b8ec349b68d6076c92fa7ae402aac613050","src/api.rs":"b3f0ff950178d006e443ddbeec4513e0acaa8894211053cfdfc1de104b9fb6ab","src/db.rs":"04ef67021b6aad7552a268397c7323302c4f619b3fb07fb140132beb8b37f8b5","src/error.rs":"8587813be8e2a7f5efad4216a5c4686554ed44e98cf94bfd9c2f2c9adc8e9a11","src/ffi.rs":"f66a81393bebe7a4b7e7960cb426df106ff1f02bfebcaa6e335b4b8b56c5c936","src/lib.rs":"ab25e7c6ea67fb905fe6dad866c0d2c462b1e93bcff283db947513aeabbb2d73","src/migration.rs":"8d92f82b2ba38e1039fd054c8c75078a6b896a0d3cdc1a52571456b25a32c9c3","src/schema.rs":"d8dd8f66cad71e3e369722734e0d5d16fd9423d5f6a5abba1854a27e1e814724","src/store.rs":"d208689c46fb97cd2c60a0c610ba1998a7132fb50fffa2eefa1d6b169b7c34f0","src/sync/bridge.rs":"996de05beb2904f84b3cbfc9ef85c4844078fdb4867d9068390d496156bee614","src/sync/incoming.rs":"dd77c64e2ade4f39cba258decab6d3db8ad0b5f513aa018efbd56b9869a021d9","src/sync/mod.rs":"05da064e1bc2cc449c806a534842da92d8d4b24a919f2dff2e88dc69f3e926a5","src/sync/outgoing.rs":"dacb77b956f2546fd60a89367927a199d9b662b17201d0781145f7405b61fdce","src/sync/sync_tests.rs":"bc9845312c7b08c5efd892979f61e9385b553f872a6c5d78600f4587b14421f5","src/webext-storage.udl":"0341d431ba837cf64ea210ef6157010c6664a0b5a194e89acb0414938636b391","uniffi.toml":"beeec89c2f877eb89be0090dc304dbc7c74e787385e7459bad78c6165bb66791"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"30f29c517673d81dd3e689169fdee1dd0522b40855d984341d35b34fedd391b3","README.md":"821cac7eb5b963fc3f3fe21dd890427ab2bbf335cb25cbae89b713b3350687c5","build.rs":"92f7d380f3d8fab1e6d80276915af57192e276321d132a5f800ea4520e9cb469","sql/create_schema.sql":"a17311a407ec10e033886b7125da4c8b84bc6d761f6b28edc9594de430e1d964","sql/create_sync_temp_tables.sql":"860ede362c94feb47d85522553fa2852f9bdb9f9b025d6438dd5dee3d4acd527","sql/tests/create_schema_v1.sql":"77cf0c90eaac3e1aea626537147e1b8ec349b68d6076c92fa7ae402aac613050","src/api.rs":"b3f0ff950178d006e443ddbeec4513e0acaa8894211053cfdfc1de104b9fb6ab","src/db.rs":"04ef67021b6aad7552a268397c7323302c4f619b3fb07fb140132beb8b37f8b5","src/error.rs":"8587813be8e2a7f5efad4216a5c4686554ed44e98cf94bfd9c2f2c9adc8e9a11","src/ffi.rs":"f66a81393bebe7a4b7e7960cb426df106ff1f02bfebcaa6e335b4b8b56c5c936","src/lib.rs":"ab25e7c6ea67fb905fe6dad866c0d2c462b1e93bcff283db947513aeabbb2d73","src/migration.rs":"8d92f82b2ba38e1039fd054c8c75078a6b896a0d3cdc1a52571456b25a32c9c3","src/schema.rs":"d8dd8f66cad71e3e369722734e0d5d16fd9423d5f6a5abba1854a27e1e814724","src/store.rs":"d208689c46fb97cd2c60a0c610ba1998a7132fb50fffa2eefa1d6b169b7c34f0","src/sync/bridge.rs":"996de05beb2904f84b3cbfc9ef85c4844078fdb4867d9068390d496156bee614","src/sync/incoming.rs":"dd77c64e2ade4f39cba258decab6d3db8ad0b5f513aa018efbd56b9869a021d9","src/sync/mod.rs":"05da064e1bc2cc449c806a534842da92d8d4b24a919f2dff2e88dc69f3e926a5","src/sync/outgoing.rs":"dacb77b956f2546fd60a89367927a199d9b662b17201d0781145f7405b61fdce","src/sync/sync_tests.rs":"bc9845312c7b08c5efd892979f61e9385b553f872a6c5d78600f4587b14421f5","src/webext-storage.udl":"0341d431ba837cf64ea210ef6157010c6664a0b5a194e89acb0414938636b391","uniffi.toml":"beeec89c2f877eb89be0090dc304dbc7c74e787385e7459bad78c6165bb66791"},"package":null} \ No newline at end of file diff --git a/third_party/rust/webext-storage/Cargo.toml b/third_party/rust/webext-storage/Cargo.toml index fcca3f82f836..7fed2e64f1c4 100644 --- a/third_party/rust/webext-storage/Cargo.toml +++ b/third_party/rust/webext-storage/Cargo.toml @@ -73,7 +73,7 @@ path = "../../components/sync15" features = ["sync-engine"] [dependencies.uniffi] -version = "0.27.1" +version = "0.28.0" [dependencies.url] version = "2.1" @@ -100,7 +100,7 @@ path = "../support/sql" path = "../support/rc_crypto/nss/nss_build_common" [build-dependencies.uniffi] -version = "0.27.1" +version = "0.28.0" features = ["build"] [features] diff --git a/toolkit/components/uniffi-bindgen-gecko-js/Cargo.toml b/toolkit/components/uniffi-bindgen-gecko-js/Cargo.toml index 5ef165dc73a5..9b5b8b06c297 100644 --- a/toolkit/components/uniffi-bindgen-gecko-js/Cargo.toml +++ b/toolkit/components/uniffi-bindgen-gecko-js/Cargo.toml @@ -13,7 +13,7 @@ anyhow = "1" askama = { version = "0.12", default-features = false, features = ["config"] } clap = { version = "4", default-features = false, features = ["std", "derive", "cargo"] } extend = "1.1" -heck = "0.4" +heck = "0.5" uniffi = { workspace = true } uniffi_bindgen = { workspace = true } serde = "1"