mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Backed out changeset ab4790cd94eb (bug 1772132) for causing wrench bustage CLOSED TREE
This commit is contained in:
parent
86debe7916
commit
36788ca992
64
Cargo.lock
generated
64
Cargo.lock
generated
@ -58,14 +58,14 @@ checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
|
||||
|
||||
[[package]]
|
||||
name = "android_logger"
|
||||
version = "0.11.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b74b7ddf197de32e415d197aa21c1c0cb36e01e4794fd801302280ac7847ee02"
|
||||
checksum = "d9ed09b18365ed295d722d0b5ed59c01b79a826ff2d2a8f73d5ecca8e6fb2f66"
|
||||
dependencies = [
|
||||
"android_log-sys",
|
||||
"env_logger 0.9.0",
|
||||
"env_logger 0.8.999",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -644,6 +644,13 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.13.999"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.14.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.14.2"
|
||||
@ -2270,9 +2277,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glean"
|
||||
version = "50.1.2"
|
||||
version = "50.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "813fa9059f1a7d9da4fcf6cff6c77e6226fc26f58797d1659d16a8279c4655f2"
|
||||
checksum = "0857be0c251ae1fc3b5672237c99f5115a6546cd8b171cb240173098ab5e9629"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
@ -2290,15 +2297,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glean-core"
|
||||
version = "50.1.2"
|
||||
version = "50.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5edb2b6cf2938242adda6ece26ac29b2238c693c423331c8a68ce980c348b28"
|
||||
checksum = "f1bdfa0e2e6476190b4762c4cdc87c1a7a0347f601864b091cf9ad674a909c68"
|
||||
dependencies = [
|
||||
"android_logger",
|
||||
"bincode",
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
"env_logger 0.9.0",
|
||||
"env_logger 0.8.999",
|
||||
"ffi-support",
|
||||
"flate2",
|
||||
"log",
|
||||
@ -3737,6 +3744,13 @@ dependencies = [
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "5.999.999"
|
||||
dependencies = [
|
||||
"nom 6.1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "6.1.2"
|
||||
@ -5676,14 +5690,13 @@ checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||
|
||||
[[package]]
|
||||
name = "uniffi"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc1de33ad46ce00bc9a31cea44e80ef69175d3a23007335216fe3996880a310d"
|
||||
checksum = "d0fe14882ae6ea89f31ac922ad8e6f76b3f346f07965791a60ade60cc3bcdd60"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes 1.1.0",
|
||||
"camino",
|
||||
"cargo_metadata",
|
||||
"cargo_metadata 0.13.999",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"paste",
|
||||
@ -5692,18 +5705,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_bindgen"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b18e05c55840ddd690ba211f72bb1f2f6ca8c50bfeb7d7211ea5ee60b0f9be07"
|
||||
checksum = "49a9810482e988792ed22fc6747d872bd32600f7e3bfc11fe93019d155d7e89c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"askama",
|
||||
"camino",
|
||||
"cargo_metadata",
|
||||
"cargo_metadata 0.13.999",
|
||||
"clap",
|
||||
"fs-err",
|
||||
"heck",
|
||||
"lazy_static",
|
||||
"paste",
|
||||
"serde",
|
||||
"toml 0.5.9",
|
||||
@ -5712,22 +5722,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_build"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fff0860625e4e621f0317e5f6ac9e79966262bd86a6cfb2049e8425df23afbd"
|
||||
checksum = "bcb7401cfd8da93541c23a0683c1dab3c782d2a118254536106b0aa4d9b30607"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
"uniffi_bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_macros"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7956a6c1fb12bff15e537028ea2174f000f90dd4f87912233b276ea782d420f2"
|
||||
checksum = "4e7b60ccb030ef51b0c85eb9ca55f28ff68b82c1a29d2bc0c7053777010af0d3"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"glob",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -6085,12 +6093,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "weedle2"
|
||||
version = "3.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d730d941cf471131c40a64cf2e8a595822009f51e64c05c5afdbc85af155857"
|
||||
checksum = "8a69b360c3d0df7dc1a18124677ee8476576c806418f30a360a6cf6cf4e072a6"
|
||||
dependencies = [
|
||||
"fs-err",
|
||||
"nom 6.1.2",
|
||||
"nom 5.999.999",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -115,6 +115,13 @@ env_logger = { path = "build/rust/env_logger" }
|
||||
# Patch toml 0.4 to 0.5
|
||||
toml = { path = "build/rust/toml" }
|
||||
|
||||
# Patch cargo_metadata 0.13 to 0.14.2
|
||||
# FIXME(bug 1772132): To be removed with the next Glean update
|
||||
cargo_metadata = { path = "build/rust/cargo_metadata" }
|
||||
|
||||
# Patch nom 5 to nom 6
|
||||
nom = { path = "build/rust/nom" }
|
||||
|
||||
# Patch parking_lot 0.12 down to 0.11, which is compatible for most crates that use it, to avoid
|
||||
# dependencies on windows-sys.
|
||||
parking_lot = { path = "build/rust/parking_lot" }
|
||||
|
@ -36,7 +36,7 @@ allprojects {
|
||||
topsrcdir = gradle.mozconfig.topsrcdir
|
||||
topobjdir = gradle.mozconfig.topobjdir
|
||||
|
||||
gleanVersion = "50.1.2"
|
||||
gleanVersion = "50.1.0"
|
||||
if (gleanVersion != getRustVersionFor("glean")) {
|
||||
throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
|
||||
" found ${getRustVersionFor("glean")}")
|
||||
|
15
build/rust/cargo_metadata/Cargo.toml
Normal file
15
build/rust/cargo_metadata/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "cargo_metadata"
|
||||
version = "0.13.999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
cargo_metadata = "0.14.2"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
builder = ["cargo_metadata/derive_builder"]
|
5
build/rust/cargo_metadata/lib.rs
Normal file
5
build/rust/cargo_metadata/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
/* 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 cargo_metadata::*;
|
20
build/rust/nom/Cargo.toml
Normal file
20
build/rust/nom/Cargo.toml
Normal file
@ -0,0 +1,20 @@
|
||||
[package]
|
||||
name = "nom"
|
||||
version = "5.999.999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.nom]
|
||||
version = "6.0"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
alloc = ["nom/alloc"]
|
||||
default = ["nom/default"]
|
||||
lexical = ["nom/lexical-core"]
|
||||
regexp = ["nom/regex"]
|
||||
regexp_macros = ["nom/regexp_macros"]
|
||||
std = ["nom/std"]
|
10
build/rust/nom/lib.rs
Normal file
10
build/rust/nom/lib.rs
Normal file
@ -0,0 +1,10 @@
|
||||
/* 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 nom::*;
|
||||
|
||||
pub use nom::separated_list0 as separated_list;
|
||||
pub use nom::separated_list1 as separated_nonempty_list;
|
||||
|
||||
pub type IResult<I, O, E=(I, error::ErrorKind)> = nom::IResult<I, O, E>;
|
@ -51,7 +51,7 @@ svg_fmt = "0.4"
|
||||
tracy-rs = "0.1.2"
|
||||
derive_more = { version = "0.99", default-features = false, features = ["add_assign"] }
|
||||
etagere = "0.2.6"
|
||||
glean = "50.1.2"
|
||||
glean = "50.1.0"
|
||||
fog = { version = "0.1.0", optional = true }
|
||||
swgl = { path = "../swgl", optional = true }
|
||||
topological-sort = "0.1"
|
||||
|
@ -129,7 +129,7 @@ pth:xpcom/geckoprocesstypes_generator
|
||||
pth:xpcom/idl-parser
|
||||
# glean-sdk may not be installable if a wheel isn't available
|
||||
# and it has to be built from source.
|
||||
pypi-optional:glean-sdk==50.1.2:telemetry will not be collected
|
||||
pypi-optional:glean-sdk==50.1.0:telemetry will not be collected
|
||||
# Mach gracefully handles the case where `psutil` is unavailable.
|
||||
# We aren't (yet) able to pin packages in automation, so we have to
|
||||
# support down to the oldest locally-installed version (5.4.2).
|
||||
|
@ -1,12 +1,6 @@
|
||||
|
||||
# cargo-vet audits file
|
||||
|
||||
[[audits.android_logger]]
|
||||
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.11.0"
|
||||
notes = "Small crate, wrapping Android log functionality, reviewed by janerik"
|
||||
|
||||
[[audits.android_system_properties]]
|
||||
who = "Nicolas Silva <nical@fastmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
@ -63,24 +57,12 @@ criteria = "safe-to-deploy"
|
||||
version = "50.1.0"
|
||||
notes = "Maintained by the Glean team at Mozilla"
|
||||
|
||||
[[audits.glean]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "50.1.2"
|
||||
notes = "Maintained by the Glean team at Mozilla"
|
||||
|
||||
[[audits.glean-core]]
|
||||
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "50.1.0"
|
||||
notes = "Maintained by the Glean team at Mozilla"
|
||||
|
||||
[[audits.glean-core]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "50.1.2"
|
||||
notes = "Maintained by the Glean team at Mozilla"
|
||||
|
||||
[[audits.linked-hash-map]]
|
||||
who = "Aria Beingessner <a.beingessner@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
@ -147,42 +129,12 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.1.19 -> 0.1.20"
|
||||
notes = "I am the author of most of these changes upstream, and prepared the release myself, at which point I looked at the other changes since 0.1.19."
|
||||
|
||||
[[audits.uniffi]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.19.3"
|
||||
notes = "Maintained by the Glean and Application Services teams"
|
||||
|
||||
[[audits.uniffi_bindgen]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.19.3"
|
||||
notes = "Maintained by the Glean and Application Services teams."
|
||||
|
||||
[[audits.uniffi_build]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.19.3"
|
||||
notes = "Maintained by the Glean and Application Services teams."
|
||||
|
||||
[[audits.uniffi_macros]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "0.19.3"
|
||||
notes = "Maintained by the Glean and Application Services teams."
|
||||
|
||||
[[audits.void]]
|
||||
who = "Bobby Holley <bobbyholley@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "1.0.2"
|
||||
notes = "Very small crate, just hosts the Void type for easier cross-crate interfacing."
|
||||
|
||||
[[audits.weedle2]]
|
||||
who = "Travis Long <tlong@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
version = "3.0.0"
|
||||
notes = "Maintained by the Glean and Application Services teams."
|
||||
|
||||
[[audits.webdriver]]
|
||||
who = "Henrik Skupin <mail@hskupin.info>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -177,6 +177,10 @@ criteria = "safe-to-deploy"
|
||||
version = "0.2.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.android_logger]]
|
||||
version = "0.10.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.anyhow]]
|
||||
version = "1.0.57"
|
||||
criteria = "safe-to-deploy"
|
||||
@ -1717,6 +1721,22 @@ criteria = "safe-to-deploy"
|
||||
version = "0.2.3"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.uniffi]]
|
||||
version = "0.18.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.uniffi_bindgen]]
|
||||
version = "0.18.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.uniffi_build]]
|
||||
version = "0.18.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.uniffi_macros]]
|
||||
version = "0.18.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.unix_path]]
|
||||
version = "1.0.1"
|
||||
criteria = "safe-to-run"
|
||||
@ -1773,6 +1793,10 @@ criteria = "safe-to-deploy"
|
||||
version = "0.3.9"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.weedle2]]
|
||||
version = "2.0.1"
|
||||
criteria = "safe-to-deploy"
|
||||
|
||||
[[exemptions.wgpu-core]]
|
||||
version = "0.12.0"
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"896268b277c2cd333293139e868abac82c39983de9aa56aead4464c38239b66a","LICENSE-APACHE":"99938c5864dd33decb62ab20fd883a9b00181d768ae887a4f19b2d0015c41dc9","LICENSE-MIT":"35043211d1b7be8f7e3f9cad27d981f2189ba9a39d9527b275b3c9740298dfe2","README.md":"bf2e6227790edeb5959c2be250b71d1a197a3a344dc5fc1638fbb39c73bdfd21","src/lib.rs":"e3a0a6bb68d7bad681a978274b612e77cecc41112b448209a09c96b5b33d029e","tests/config_log_level.rs":"8aae2c7decbcf12a2a454486c9d4dd4a82a20e01d327c4abf4e9cfded973159d","tests/default_init.rs":"ef18c9ea38687a178623c11acfa3d34d16b9030eaad337ab9ed6a609a2c42ca2","tests/multiple_init.rs":"a6ed4986a758b7b2322c6ad0a18ec99fd06521a6c8767a6622eab2cbf9be601e"},"package":"b74b7ddf197de32e415d197aa21c1c0cb36e01e4794fd801302280ac7847ee02"}
|
||||
{"files":{"Cargo.toml":"632df8824223ca0e23352f6b0d103ac994fab57dc51f33c2e6d41c91256e1c4d","LICENSE-APACHE":"99938c5864dd33decb62ab20fd883a9b00181d768ae887a4f19b2d0015c41dc9","LICENSE-MIT":"35043211d1b7be8f7e3f9cad27d981f2189ba9a39d9527b275b3c9740298dfe2","README.md":"7a4f75e61fc014f4dbb907fa947e1983f45993dc2a85104cdb619c0808433f65","src/lib.rs":"bdbd60c12117123c2554b1984949dfbc403d890318a0de637829592f4359de6d","tests/config_log_level.rs":"8aae2c7decbcf12a2a454486c9d4dd4a82a20e01d327c4abf4e9cfded973159d","tests/default_init.rs":"ef18c9ea38687a178623c11acfa3d34d16b9030eaad337ab9ed6a609a2c42ca2","tests/multiple_init.rs":"a6ed4986a758b7b2322c6ad0a18ec99fd06521a6c8767a6622eab2cbf9be601e"},"package":"d9ed09b18365ed295d722d0b5ed59c01b79a826ff2d2a8f73d5ecca8e6fb2f66"}
|
32
third_party/rust/android_logger/Cargo.toml
vendored
32
third_party/rust/android_logger/Cargo.toml
vendored
@ -3,46 +3,38 @@
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "android_logger"
|
||||
version = "0.11.0"
|
||||
version = "0.10.1"
|
||||
authors = ["The android_logger Developers"]
|
||||
description = """
|
||||
A logging implementation for `log` which hooks to android log output.
|
||||
"""
|
||||
description = "A logging implementation for `log` which hooks to android log output.\n"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"android",
|
||||
"bindings",
|
||||
"log",
|
||||
"logger",
|
||||
]
|
||||
keywords = ["android", "bindings", "log", "logger"]
|
||||
categories = ["api-bindings"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/Nercury/android_logger-rs"
|
||||
|
||||
[dependencies.android_log-sys]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.env_logger]
|
||||
version = "0.9"
|
||||
version = "0.8"
|
||||
default-features = false
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.4"
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.9"
|
||||
|
||||
[features]
|
||||
default = ["regex"]
|
||||
regex = ["env_logger/regex"]
|
||||
|
||||
[badges.travis-ci]
|
||||
repository = "Nercury/android_logger-rs"
|
||||
|
2
third_party/rust/android_logger/README.md
vendored
2
third_party/rust/android_logger/README.md
vendored
@ -13,7 +13,7 @@ this library:
|
||||
|
||||
```toml
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android_logger = "0.11"
|
||||
android_logger = "0.10"
|
||||
```
|
||||
|
||||
Example of initialization on activity creation, with log configuration:
|
||||
|
59
third_party/rust/android_logger/src/lib.rs
vendored
59
third_party/rust/android_logger/src/lib.rs
vendored
@ -65,13 +65,15 @@
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
extern crate android_log_sys as log_ffi;
|
||||
extern crate once_cell;
|
||||
use once_cell::sync::OnceCell;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
extern crate env_logger;
|
||||
|
||||
use std::sync::RwLock;
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use log_ffi::LogPriority;
|
||||
use log::{Level, Log, Metadata, Record};
|
||||
@ -103,20 +105,21 @@ fn android_log(_priority: Level, _tag: &CStr, _msg: &CStr) {}
|
||||
|
||||
/// Underlying android logger backend
|
||||
pub struct AndroidLogger {
|
||||
config: OnceCell<Config>,
|
||||
config: RwLock<Config>,
|
||||
}
|
||||
|
||||
impl AndroidLogger {
|
||||
/// Create new logger instance from config
|
||||
pub fn new(config: Config) -> AndroidLogger {
|
||||
AndroidLogger {
|
||||
config: OnceCell::from(config),
|
||||
config: RwLock::new(config),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ANDROID_LOGGER: OnceCell<AndroidLogger> = OnceCell::new();
|
||||
lazy_static! {
|
||||
static ref ANDROID_LOGGER: AndroidLogger = AndroidLogger::default();
|
||||
}
|
||||
|
||||
const LOGGING_TAG_MAX_LEN: usize = 23;
|
||||
const LOGGING_MSG_MAX_LEN: usize = 4000;
|
||||
@ -125,7 +128,7 @@ impl Default for AndroidLogger {
|
||||
/// Create a new logger with default config
|
||||
fn default() -> AndroidLogger {
|
||||
AndroidLogger {
|
||||
config: OnceCell::from(Config::default()),
|
||||
config: RwLock::new(Config::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,7 +140,8 @@ impl Log for AndroidLogger {
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
let config = self.config
|
||||
.get_or_init(Config::default);
|
||||
.read()
|
||||
.expect("failed to acquire android_log filter lock for read");
|
||||
|
||||
if !config.filter_matches(record) {
|
||||
return;
|
||||
@ -151,7 +155,7 @@ impl Log for AndroidLogger {
|
||||
|
||||
// If no tag was specified, use module name
|
||||
let custom_tag = &config.tag;
|
||||
let tag = custom_tag.as_ref().map(|s| s.as_bytes()).unwrap_or_else(|| module_path.as_bytes());
|
||||
let tag = custom_tag.as_ref().map(|s| s.as_bytes()).unwrap_or(module_path.as_bytes());
|
||||
|
||||
// truncate the tag here to fit into LOGGING_TAG_MAX_LEN
|
||||
self.fill_tag_bytes(&mut tag_bytes, tag);
|
||||
@ -202,7 +206,6 @@ impl AndroidLogger {
|
||||
}
|
||||
|
||||
/// Filter for android logger.
|
||||
#[derive(Default)]
|
||||
pub struct Config {
|
||||
log_level: Option<Level>,
|
||||
filter: Option<env_logger::filter::Filter>,
|
||||
@ -210,6 +213,17 @@ pub struct Config {
|
||||
custom_format: Option<FormatFn>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Config {
|
||||
log_level: None,
|
||||
filter: None,
|
||||
tag: None,
|
||||
custom_format: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Change the minimum log level.
|
||||
///
|
||||
@ -222,7 +236,7 @@ impl Config {
|
||||
|
||||
fn filter_matches(&self, record: &Record) -> bool {
|
||||
if let Some(ref filter) = self.filter {
|
||||
filter.matches(record)
|
||||
filter.matches(&record)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@ -351,7 +365,7 @@ impl<'a> PlatformLogWriter<'a> {
|
||||
|
||||
/// Copy `len` bytes from `index` position to starting position.
|
||||
fn copy_bytes_to_start(&mut self, index: usize, len: usize) {
|
||||
let src = unsafe { self.buffer.as_ptr().add(index) };
|
||||
let src = unsafe { self.buffer.as_ptr().offset(index as isize) };
|
||||
let dst = self.buffer.as_mut_ptr();
|
||||
unsafe { ptr::copy(src, dst, len) };
|
||||
}
|
||||
@ -409,7 +423,7 @@ impl<'a> fmt::Write for PlatformLogWriter<'a> {
|
||||
/// This action does not require initialization. However, without initialization it
|
||||
/// will use the default filter, which allows all logs.
|
||||
pub fn log(record: &Record) {
|
||||
ANDROID_LOGGER.get_or_init(AndroidLogger::default).log(record)
|
||||
ANDROID_LOGGER.log(record)
|
||||
}
|
||||
|
||||
/// Initializes the global logger with an android logger.
|
||||
@ -420,13 +434,16 @@ pub fn log(record: &Record) {
|
||||
/// It is ok to call this at the activity creation, and it will be
|
||||
/// repeatedly called on every lifecycle restart (i.e. screen rotation).
|
||||
pub fn init_once(config: Config) {
|
||||
let log_level = config.log_level;
|
||||
let logger = ANDROID_LOGGER.get_or_init(|| AndroidLogger::new(config));
|
||||
|
||||
if let Err(err) = log::set_logger(logger) {
|
||||
if let Err(err) = log::set_logger(&*ANDROID_LOGGER) {
|
||||
debug!("android_logger: log::set_logger failed: {}", err);
|
||||
} else if let Some(level) = log_level {
|
||||
log::set_max_level(level.to_level_filter());
|
||||
} else {
|
||||
if let Some(level) = config.log_level {
|
||||
log::set_max_level(level.to_level_filter());
|
||||
}
|
||||
*ANDROID_LOGGER
|
||||
.config
|
||||
.write()
|
||||
.expect("failed to acquire android_log filter lock for write") = config;
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,7 +531,7 @@ mod tests {
|
||||
fn platform_log_writer_init_values() {
|
||||
let tag = CStr::from_bytes_with_nul(b"tag\0").unwrap();
|
||||
|
||||
let writer = PlatformLogWriter::new(Level::Warn, tag);
|
||||
let writer = PlatformLogWriter::new(Level::Warn, &tag);
|
||||
|
||||
assert_eq!(writer.tag, tag);
|
||||
// Android uses LogPriority instead, which doesn't implement equality checks
|
||||
@ -613,6 +630,6 @@ mod tests {
|
||||
}
|
||||
|
||||
fn get_tag_writer() -> PlatformLogWriter<'static> {
|
||||
PlatformLogWriter::new(Level::Warn, CStr::from_bytes_with_nul(b"tag\0").unwrap())
|
||||
PlatformLogWriter::new(Level::Warn, &CStr::from_bytes_with_nul(b"tag\0").unwrap())
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
14
third_party/rust/glean-core/Cargo.toml
vendored
14
third_party/rust/glean-core/Cargo.toml
vendored
@ -12,7 +12,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "glean-core"
|
||||
version = "50.1.2"
|
||||
version = "50.1.0"
|
||||
authors = [
|
||||
"Jan-Erik Rediger <jrediger@mozilla.com>",
|
||||
"The Glean Team <glean-team@mozilla.com>",
|
||||
@ -76,10 +76,10 @@ version = "1.0.4"
|
||||
version = "0.1.40"
|
||||
|
||||
[dependencies.uniffi]
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
|
||||
[dependencies.uniffi_macros]
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
|
||||
[dependencies.uuid]
|
||||
version = "0.8.1"
|
||||
@ -95,7 +95,7 @@ version = "0.1.0"
|
||||
version = "0.1.12"
|
||||
|
||||
[dev-dependencies.env_logger]
|
||||
version = "0.9.0"
|
||||
version = "0.8.0"
|
||||
features = [
|
||||
"termcolor",
|
||||
"atty",
|
||||
@ -110,14 +110,14 @@ version = "0.4"
|
||||
version = "3.1.0"
|
||||
|
||||
[build-dependencies.uniffi_build]
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
features = ["builtin-bindgen"]
|
||||
|
||||
[features]
|
||||
rkv-safe-mode = []
|
||||
|
||||
[target."cfg(not(target_os = \"android\"))".dependencies.env_logger]
|
||||
version = "0.9.0"
|
||||
version = "0.8.0"
|
||||
features = [
|
||||
"termcolor",
|
||||
"atty",
|
||||
@ -126,7 +126,7 @@ features = [
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_os = \"android\")".dependencies.android_logger]
|
||||
version = "0.11.0"
|
||||
version = "0.10.0"
|
||||
default-features = false
|
||||
|
||||
[target."cfg(target_os = \"ios\")".dependencies.oslog]
|
||||
|
@ -63,7 +63,7 @@ enum Command {
|
||||
}
|
||||
|
||||
/// The error returned from operations on the dispatcher
|
||||
#[derive(Error, Debug, PartialEq, Eq)]
|
||||
#[derive(Error, Debug, PartialEq)]
|
||||
pub enum DispatchError {
|
||||
/// The worker panicked while running a task
|
||||
#[error("The worker panicked while running a task")]
|
||||
|
@ -27,7 +27,7 @@ use crate::Lifetime;
|
||||
/// in the platform-specific code (e.g. `ErrorType.kt`) and with the
|
||||
/// metrics in the registry files.
|
||||
// When adding a new error type ensure it's also added to `ErrorType::iter()` below.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ErrorType {
|
||||
/// For when the value to be recorded does not match the metric-specific restrictions
|
||||
InvalidValue,
|
||||
|
@ -56,7 +56,7 @@ fn exponential_range(min: u64, max: u64, bucket_count: usize) -> Vec<u64> {
|
||||
///
|
||||
/// Buckets are pre-computed at instantiation with an exponential distribution from `min` to `max`
|
||||
/// and `bucket_count` buckets.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct PrecomputedExponential {
|
||||
// Don't serialize the (potentially large) array of ranges, instead compute them on first
|
||||
// access.
|
||||
|
@ -36,7 +36,7 @@ fn linear_range(min: u64, max: u64, count: usize) -> Vec<u64> {
|
||||
///
|
||||
/// Buckets are pre-computed at instantiation with a linear distribution from `min` to `max`
|
||||
/// and `bucket_count` buckets.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct PrecomputedLinear {
|
||||
// Don't serialize the (potentially large) array of ranges, instead compute them on first
|
||||
// access.
|
||||
|
@ -58,7 +58,7 @@ impl TryFrom<i32> for HistogramType {
|
||||
/// assert_eq!(10, hist.count());
|
||||
/// assert_eq!(55, hist.sum());
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct Histogram<B> {
|
||||
/// Mapping bucket's minimum to sample count.
|
||||
values: HashMap<u64, u64>,
|
||||
|
1
third_party/rust/glean-core/src/lib.rs
vendored
1
third_party/rust/glean-core/src/lib.rs
vendored
@ -2,7 +2,6 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
#![allow(clippy::significant_drop_in_scrutinee)]
|
||||
#![deny(rustdoc::broken_intra_doc_links)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Map as JsonMap, Value as JsonValue};
|
||||
|
||||
/// Deserialized experiment data.
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
|
||||
pub struct RecordedExperiment {
|
||||
/// The experiment's branch as set through [`set_experiment_active`](crate::glean_set_experiment_active).
|
||||
pub branch: String,
|
||||
|
@ -11,7 +11,7 @@ use crate::error::{Error, ErrorKind};
|
||||
|
||||
/// Different resolutions supported by the time related
|
||||
/// metric types (e.g. DatetimeMetric).
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[repr(i32)] // use i32 to be compatible with our JNA definition
|
||||
pub enum TimeUnit {
|
||||
|
@ -127,7 +127,7 @@ impl RateLimiter {
|
||||
/// the requester may receive one out of three possible tasks.
|
||||
///
|
||||
/// If new variants are added, this should be reflected in `glean-core/ffi/src/upload.rs` as well.
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum PingUploadTask {
|
||||
/// An upload task
|
||||
Upload {
|
||||
|
@ -180,7 +180,7 @@ impl Builder {
|
||||
}
|
||||
|
||||
/// Represents a request to upload a ping.
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct PingRequest {
|
||||
/// The Job ID to identify this request,
|
||||
/// this is the same as the ping UUID.
|
||||
|
2
third_party/rust/glean/.cargo-checksum.json
vendored
2
third_party/rust/glean/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"22631469f647eb393b83eccffadea1ff3124ba4e79e402b754aab30926d384c0","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5bc5b1c46695f628e1023662752272e938a963b535d5686bd1ecc433f9e018c4","src/common_test.rs":"68f6d408cb7b683fa32c8b38a4df1e6c45bfd77c0c90ca35976ea7548bbc4b2f","src/configuration.rs":"37ad5b3e7d4e31dd04a7d6690179168b5f2768d87dd36056dee5d08bdbe20fb2","src/core_metrics.rs":"76ac5350cb6f82d9a193d519b085a08f138dceba77da3514bd0c636bcdefefca","src/lib.rs":"e342d497d60abceca3c84d35523a54d187b0282220a112da53e4ab1cf76da205","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"86cbcb0b46f9d13923a20db9e482b65da49d7daa4e335a3f3092f1d760f572b0","src/private/event.rs":"f6cd799c7764c53510180a1cef6a5a9b435fae27b87270519d5b4e59201e8ecc","src/private/mod.rs":"0364ecf5f0439443a5b209583f4ff2c474b79f7c253c981ab0b7cdc528368698","src/private/ping.rs":"cbdc57f41fc9d46e56b4dfff91ac683753d1f8b3ecd0aa9bc3419e3595b8b81b","src/system.rs":"ff23a5b94f52dab484342dfed702412bc29ab1bbfd5af326033d8e07e7b9075f","src/test.rs":"30d62d967c56a7ca76c097e27bfb6d6d3779ccd5d374cf5a07a04216e4e0880b","tests/common/mod.rs":"37cd4c48e140c793b852ae09fb3e812da28a4412977295015bcbffd632fcf294","tests/init_fails.rs":"9b78226a4e3220de5b64a205a97b8d5778d1700391b5b71c7819b6cdd120747e","tests/never_init.rs":"1f33b8ce7ca3514b57b48cc16d98408974c85cf8aa7d13257ffc2ad878ebb295","tests/no_time_to_init.rs":"494dcddce49f279c6508f484ee59cf8bb83e7324de07bdbc1142f2a066b7f6a1","tests/overflowing_preinit.rs":"396206d5078b7e6c148bbf2aecb0f963cfaa4d7eff3fc7bf6590125076ee6113","tests/persist_ping_lifetime.rs":"2297d4b208e14188e6dcca2d4806b805cfc7dd824d21bd143a7803b95e0709f4","tests/persist_ping_lifetime_nopanic.rs":"06f1f3ca3b8a6c8b7fc4d6fc48d0e1d2ccffd32139f080db0a95003e9edd507d","tests/schema.rs":"a96089f828928b6be1fad7815e3269f5693af1b773e570312b357a29af28122a","tests/simple.rs":"a1d72af899293390bb955ca379baafb89c29bb746630409f8c51f453d222dbad"},"package":"813fa9059f1a7d9da4fcf6cff6c77e6226fc26f58797d1659d16a8279c4655f2"}
|
||||
{"files":{"Cargo.toml":"0b561e6268bc36b36c8c29d82fde25a451bd8fb7d618efa2145255033616a73b","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5bc5b1c46695f628e1023662752272e938a963b535d5686bd1ecc433f9e018c4","src/common_test.rs":"68f6d408cb7b683fa32c8b38a4df1e6c45bfd77c0c90ca35976ea7548bbc4b2f","src/configuration.rs":"37ad5b3e7d4e31dd04a7d6690179168b5f2768d87dd36056dee5d08bdbe20fb2","src/core_metrics.rs":"76ac5350cb6f82d9a193d519b085a08f138dceba77da3514bd0c636bcdefefca","src/lib.rs":"e342d497d60abceca3c84d35523a54d187b0282220a112da53e4ab1cf76da205","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"86cbcb0b46f9d13923a20db9e482b65da49d7daa4e335a3f3092f1d760f572b0","src/private/event.rs":"f6cd799c7764c53510180a1cef6a5a9b435fae27b87270519d5b4e59201e8ecc","src/private/mod.rs":"0364ecf5f0439443a5b209583f4ff2c474b79f7c253c981ab0b7cdc528368698","src/private/ping.rs":"cbdc57f41fc9d46e56b4dfff91ac683753d1f8b3ecd0aa9bc3419e3595b8b81b","src/system.rs":"ff23a5b94f52dab484342dfed702412bc29ab1bbfd5af326033d8e07e7b9075f","src/test.rs":"30d62d967c56a7ca76c097e27bfb6d6d3779ccd5d374cf5a07a04216e4e0880b","tests/common/mod.rs":"37cd4c48e140c793b852ae09fb3e812da28a4412977295015bcbffd632fcf294","tests/init_fails.rs":"9b78226a4e3220de5b64a205a97b8d5778d1700391b5b71c7819b6cdd120747e","tests/never_init.rs":"1f33b8ce7ca3514b57b48cc16d98408974c85cf8aa7d13257ffc2ad878ebb295","tests/no_time_to_init.rs":"494dcddce49f279c6508f484ee59cf8bb83e7324de07bdbc1142f2a066b7f6a1","tests/overflowing_preinit.rs":"396206d5078b7e6c148bbf2aecb0f963cfaa4d7eff3fc7bf6590125076ee6113","tests/persist_ping_lifetime.rs":"2297d4b208e14188e6dcca2d4806b805cfc7dd824d21bd143a7803b95e0709f4","tests/persist_ping_lifetime_nopanic.rs":"06f1f3ca3b8a6c8b7fc4d6fc48d0e1d2ccffd32139f080db0a95003e9edd507d","tests/schema.rs":"a96089f828928b6be1fad7815e3269f5693af1b773e570312b357a29af28122a","tests/simple.rs":"a1d72af899293390bb955ca379baafb89c29bb746630409f8c51f453d222dbad"},"package":"0857be0c251ae1fc3b5672237c99f5115a6546cd8b171cb240173098ab5e9629"}
|
6
third_party/rust/glean/Cargo.toml
vendored
6
third_party/rust/glean/Cargo.toml
vendored
@ -12,7 +12,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "glean"
|
||||
version = "50.1.2"
|
||||
version = "50.1.0"
|
||||
authors = [
|
||||
"Jan-Erik Rediger <jrediger@mozilla.com>",
|
||||
"The Glean Team <glean-team@mozilla.com>",
|
||||
@ -41,7 +41,7 @@ features = ["serde"]
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.glean-core]
|
||||
version = "50.1.2"
|
||||
version = "50.1.0"
|
||||
|
||||
[dependencies.inherent]
|
||||
version = "1"
|
||||
@ -73,7 +73,7 @@ features = ["v4"]
|
||||
version = "0.1.2"
|
||||
|
||||
[dev-dependencies.env_logger]
|
||||
version = "0.9.0"
|
||||
version = "0.8.0"
|
||||
features = [
|
||||
"termcolor",
|
||||
"atty",
|
||||
|
2
third_party/rust/uniffi/.cargo-checksum.json
vendored
2
third_party/rust/uniffi/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"2d5f07251fa9e9b2422003e9ac5d8d1d8ba4656b656ee3c493e8531266dc82ed","release.toml":"a6602545cd6eb46e44d89ce946d7954957ac00f1c955de54c736fa2cb560b1df","src/ffi/ffidefault.rs":"c7ab752fffed17c3fabb60e818ad1d093482f95dd0bdeae6871287695c583e48","src/ffi/foreignbytes.rs":"37061e2da7135576abccb86fe27b4fefc054586a040f2ca81fe9858d5649e887","src/ffi/foreigncallbacks.rs":"e19a038128d25e7d945034935f0d296ea8603ad2f5a8da4bfe6d95c78a5f76b3","src/ffi/mod.rs":"3fb3b74607066e0052fc91168e9473dbf82dbae562f85c33774a7f5f6b350616","src/ffi/rustbuffer.rs":"b773637d9e4651b80cd16f7a02ed75846d02ce0a9e32b718ce644cdba3a83cdd","src/ffi/rustcalls.rs":"79192b82878fee2c09a74ec7cef1f8efdf5b7a84692a9f3a42b512bcf3400bed","src/lib.rs":"a2dba349d0c0c2f31b314f145bf576a4d0c8855fe265f987542ddbbe638ca87f","src/panichook.rs":"de3c63909691efc014ff528c767aa346109dccedf8b529c339e6715784780ae5","src/testing.rs":"6dc9b93d8bd500a0abd552a1830b968718ac6c2f713af4c325ed46c3f0a7a6c4","tests/ui/version_mismatch.rs":"16ea359e5853517ee0d0704c015ae8c825533109fbefd715130d0f4a51f15898","tests/ui/version_mismatch.stderr":"aadbd8f3847f5663022d8dd75d6afa3b25dfc8abccd30b386a681f98587d4ceb"},"package":"bc1de33ad46ce00bc9a31cea44e80ef69175d3a23007335216fe3996880a310d"}
|
||||
{"files":{"Cargo.toml":"629736f65f72d44b4e972c6e21bc998f7cc0ab5880863d80ce462df9fe3c86e4","release.toml":"a6602545cd6eb46e44d89ce946d7954957ac00f1c955de54c736fa2cb560b1df","src/ffi/ffidefault.rs":"c7ab752fffed17c3fabb60e818ad1d093482f95dd0bdeae6871287695c583e48","src/ffi/foreignbytes.rs":"6dfd91c7c9371620d45a2e950ff7c16470a7f917e034a5f1c04672bcc45682d3","src/ffi/foreigncallbacks.rs":"e19a038128d25e7d945034935f0d296ea8603ad2f5a8da4bfe6d95c78a5f76b3","src/ffi/mod.rs":"3fb3b74607066e0052fc91168e9473dbf82dbae562f85c33774a7f5f6b350616","src/ffi/rustbuffer.rs":"93ca5e8608ef1cae0da76106aa2244e50e998c99b2530cb613ff735483cd914c","src/ffi/rustcalls.rs":"79192b82878fee2c09a74ec7cef1f8efdf5b7a84692a9f3a42b512bcf3400bed","src/lib.rs":"ef06d0f87da668edf8fda2381bf484a612d35d7507a0e3bf807390077b664b7d","src/panichook.rs":"de3c63909691efc014ff528c767aa346109dccedf8b529c339e6715784780ae5","src/testing.rs":"e474fc7486cd8101449284d15b71c5b3f70ac17fe8214ab0c495e94d761b6c19","tests/ui/version_mismatch.rs":"16ea359e5853517ee0d0704c015ae8c825533109fbefd715130d0f4a51f15898","tests/ui/version_mismatch.stderr":"aadbd8f3847f5663022d8dd75d6afa3b25dfc8abccd30b386a681f98587d4ceb"},"package":"d0fe14882ae6ea89f31ac922ad8e6f76b3f346f07965791a60ade60cc3bcdd60"}
|
12
third_party/rust/uniffi/Cargo.toml
vendored
12
third_party/rust/uniffi/Cargo.toml
vendored
@ -10,9 +10,9 @@
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
edition = "2018"
|
||||
name = "uniffi"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
description = "a multi-language bindings generator for rust (runtime support code)"
|
||||
homepage = "https://mozilla.github.io/uniffi-rs"
|
||||
@ -23,7 +23,6 @@ keywords = [
|
||||
]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/mozilla/uniffi-rs"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies.anyhow]
|
||||
version = "1"
|
||||
@ -31,11 +30,8 @@ version = "1"
|
||||
[dependencies.bytes]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.camino]
|
||||
version = "1.0.8"
|
||||
|
||||
[dependencies.cargo_metadata]
|
||||
version = "0.14"
|
||||
version = "0.13"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.4"
|
||||
@ -50,7 +46,7 @@ version = "1.0"
|
||||
version = "1.1.0"
|
||||
|
||||
[dependencies.uniffi_bindgen]
|
||||
version = "=0.19.3"
|
||||
version = "=0.18.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.trybuild]
|
||||
|
@ -2,6 +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 std::convert::TryInto;
|
||||
|
||||
/// Support for reading a slice of foreign-language-allocated bytes over the FFI.
|
||||
///
|
||||
/// Foreign language code can pass a slice of bytes by providing a data pointer
|
||||
|
@ -3,6 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::ffi::{call_with_output, ForeignBytes, RustCallStatus};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
|
||||
/// Support for passing an allocated-by-Rust buffer of bytes over the FFI.
|
||||
///
|
||||
|
4
third_party/rust/uniffi/src/lib.rs
vendored
4
third_party/rust/uniffi/src/lib.rs
vendored
@ -514,7 +514,7 @@ impl<T: FfiConverter> RustBufferFfiConverter for Vec<T> {
|
||||
// TODO: would be nice not to panic here :-/
|
||||
let len = i32::try_from(obj.len()).unwrap();
|
||||
buf.put_i32(len); // We limit arrays to i32::MAX items
|
||||
for item in obj {
|
||||
for item in obj.into_iter() {
|
||||
<T as FfiConverter>::write(item, buf);
|
||||
}
|
||||
}
|
||||
@ -548,7 +548,7 @@ where
|
||||
// TODO: would be nice not to panic here :-/
|
||||
let len = i32::try_from(obj.len()).unwrap();
|
||||
buf.put_i32(len); // We limit HashMaps to i32::MAX entries
|
||||
for (key, value) in obj {
|
||||
for (key, value) in obj.into_iter() {
|
||||
<K as FfiConverter>::write(key, buf);
|
||||
<V as FfiConverter>::write(value, buf);
|
||||
}
|
||||
|
27
third_party/rust/uniffi/src/testing.rs
vendored
27
third_party/rust/uniffi/src/testing.rs
vendored
@ -9,12 +9,12 @@
|
||||
//! and should instead use the `build_foreign_language_testcases!` macro provided by
|
||||
//! the `uniffi_macros` crate.
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use anyhow::{bail, Result};
|
||||
use cargo_metadata::Message;
|
||||
use lazy_static::lazy_static;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
path::Path,
|
||||
process::{Command, Stdio},
|
||||
sync::Mutex,
|
||||
};
|
||||
@ -23,7 +23,7 @@ use std::{
|
||||
// They map uniffi component crate directories to data about build steps that have already
|
||||
// been executed by this process.
|
||||
lazy_static! {
|
||||
static ref COMPILED_COMPONENTS: Mutex<HashMap<Utf8PathBuf, Utf8PathBuf>> = Mutex::new(HashMap::new());
|
||||
static ref COMPILED_COMPONENTS: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new());
|
||||
// Since uniffi-bindgen does the actual generating/compiling of bindings and script files,
|
||||
// we ensure that only one call happens at once (making tests pretty much serialized sorry :/).
|
||||
static ref UNIFFI_BINDGEN: Mutex<i32> = Mutex::new(0);
|
||||
@ -41,10 +41,11 @@ pub fn run_foreign_language_testcase(
|
||||
test_file: &str,
|
||||
) -> Result<()> {
|
||||
let cdylib_file = ensure_compiled_cdylib(pkg_dir)?;
|
||||
let out_dir = cdylib_file
|
||||
let out_dir = Path::new(cdylib_file.as_str())
|
||||
.parent()
|
||||
.context("Generated cdylib has no parent directory")?
|
||||
.as_str();
|
||||
.ok_or_else(|| anyhow::anyhow!("Generated cdylib has no parent directory"))?
|
||||
.to_str()
|
||||
.unwrap();
|
||||
let _lock = UNIFFI_BINDGEN.lock();
|
||||
run_uniffi_bindgen_test(out_dir, udl_files, test_file)?;
|
||||
Ok(())
|
||||
@ -58,13 +59,11 @@ pub fn run_foreign_language_testcase(
|
||||
///
|
||||
/// Internally, this function does a bit of caching and concurrency management to avoid rebuilding
|
||||
/// the component for multiple testcases.
|
||||
pub fn ensure_compiled_cdylib(pkg_dir: &str) -> Result<Utf8PathBuf> {
|
||||
let pkg_dir = Utf8Path::new(pkg_dir);
|
||||
|
||||
pub fn ensure_compiled_cdylib(pkg_dir: &str) -> Result<String> {
|
||||
// Have we already compiled this component?
|
||||
let mut compiled_components = COMPILED_COMPONENTS.lock().unwrap();
|
||||
if let Some(cdylib_file) = compiled_components.get(pkg_dir) {
|
||||
return Ok(cdylib_file.to_owned());
|
||||
return Ok(cdylib_file.to_string());
|
||||
}
|
||||
// Nope, looks like we'll have to compile it afresh.
|
||||
let mut cmd = Command::new("cargo");
|
||||
@ -124,10 +123,10 @@ pub fn ensure_compiled_cdylib(pkg_dir: &str) -> Result<Utf8PathBuf> {
|
||||
if cdylib_files.len() != 1 {
|
||||
bail!("Failed to build exactly one cdylib file, it must not be a uniffi component");
|
||||
}
|
||||
let cdylib_file = cdylib_files[0];
|
||||
let cdylib_file = cdylib_files[0].to_string();
|
||||
// Cache the result for subsequent tests.
|
||||
compiled_components.insert(pkg_dir.to_owned(), cdylib_file.to_owned());
|
||||
Ok(cdylib_file.to_owned())
|
||||
compiled_components.insert(pkg_dir.to_string(), cdylib_file.clone());
|
||||
Ok(cdylib_file)
|
||||
}
|
||||
|
||||
/// Execute the `uniffi-bindgen test` command.
|
||||
@ -152,5 +151,5 @@ fn run_uniffi_bindgen_test(out_dir: &str, udl_files: &[&str], test_file: &str) -
|
||||
|
||||
#[cfg(feature = "builtin-bindgen")]
|
||||
fn run_uniffi_bindgen_test(out_dir: &str, udl_files: &[&str], test_file: &str) -> Result<()> {
|
||||
uniffi_bindgen::run_tests(out_dir, udl_files, &[test_file], None)
|
||||
uniffi_bindgen::run_tests(out_dir, udl_files, vec![test_file], None)
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
178
third_party/rust/uniffi_bindgen/Cargo.lock
generated
vendored
178
third_party/rust/uniffi_bindgen/Cargo.lock
generated
vendored
@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.58"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
||||
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
@ -76,23 +76,11 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
version = "0.19.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
|
||||
dependencies = [
|
||||
"funty",
|
||||
"radium",
|
||||
"tap",
|
||||
"wyz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.0.9"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412"
|
||||
checksum = "6f3132262930b0522068049f5870a856ab8affc80c70d08b6ecb785771a6fc23"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@ -108,22 +96,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.14.2"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
|
||||
checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform",
|
||||
"semver",
|
||||
"semver-parser",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.18"
|
||||
version = "3.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
|
||||
checksum = "85a35a599b11c089a7f49105658d089b8f2cf0882993c17daf6de15285c2c35d"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@ -138,9 +127,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.1.18"
|
||||
version = "3.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
|
||||
checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@ -151,30 +140,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.2.4"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
|
||||
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs-err"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e"
|
||||
|
||||
[[package]]
|
||||
name = "funty"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
@ -193,9 +170,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.1"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
@ -203,9 +180,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.2"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
@ -215,15 +192,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
version = "0.2.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.4"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
@ -249,12 +226,10 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "6.2.1"
|
||||
version = "5.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
|
||||
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"funty",
|
||||
"memchr",
|
||||
"version_check",
|
||||
]
|
||||
@ -271,9 +246,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.1.0"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
@ -281,6 +256,15 @@ version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||
dependencies = [
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
@ -307,57 +291,61 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.10"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.12"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1"
|
||||
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.138"
|
||||
name = "semver-parser"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47"
|
||||
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
|
||||
dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.138"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c"
|
||||
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -366,9 +354,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.82"
|
||||
version = "1.0.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
|
||||
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@ -383,21 +371,15 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
@ -422,6 +404,12 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
@ -432,23 +420,20 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.1"
|
||||
name = "unicode-xid"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_bindgen"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"askama",
|
||||
"camino",
|
||||
"cargo_metadata",
|
||||
"clap",
|
||||
"fs-err",
|
||||
"heck",
|
||||
"lazy_static",
|
||||
"paste",
|
||||
"serde",
|
||||
"toml",
|
||||
@ -463,12 +448,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "weedle2"
|
||||
version = "3.0.0"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d730d941cf471131c40a64cf2e8a595822009f51e64c05c5afdbc85af155857"
|
||||
checksum = "8655cb807b9f5c665d199c735dae90e10230eae6ae5cf009d3506963214fe451"
|
||||
dependencies = [
|
||||
"fs-err",
|
||||
"nom 6.2.1",
|
||||
"nom 5.1.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -501,9 +485,3 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
|
||||
|
20
third_party/rust/uniffi_bindgen/Cargo.toml
vendored
20
third_party/rust/uniffi_bindgen/Cargo.toml
vendored
@ -10,9 +10,9 @@
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
edition = "2018"
|
||||
name = "uniffi_bindgen"
|
||||
version = "0.19.3"
|
||||
version = "0.18.0"
|
||||
authors = ["Firefox Sync Team <sync-team@mozilla.com>"]
|
||||
description = "a multi-language bindings generator for rust (codegen and cli tooling)"
|
||||
homepage = "https://mozilla.github.io/uniffi-rs"
|
||||
@ -23,7 +23,6 @@ keywords = [
|
||||
]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/mozilla/uniffi-rs"
|
||||
resolver = "2"
|
||||
|
||||
[[bin]]
|
||||
name = "uniffi-bindgen"
|
||||
@ -37,29 +36,20 @@ version = "0.11"
|
||||
features = ["config"]
|
||||
default-features = false
|
||||
|
||||
[dependencies.camino]
|
||||
version = "1.0.8"
|
||||
|
||||
[dependencies.cargo_metadata]
|
||||
version = "0.14"
|
||||
version = "0.13"
|
||||
|
||||
[dependencies.clap]
|
||||
version = "~3.1"
|
||||
version = "3"
|
||||
features = [
|
||||
"cargo",
|
||||
"std",
|
||||
"derive",
|
||||
]
|
||||
|
||||
[dependencies.fs-err]
|
||||
version = "2.7.0"
|
||||
|
||||
[dependencies.heck]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "1.4"
|
||||
|
||||
[dependencies.paste]
|
||||
version = "1.0"
|
||||
|
||||
@ -70,4 +60,4 @@ version = "1"
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.weedle2]
|
||||
version = "3.0.0"
|
||||
version = "2.0.0"
|
||||
|
@ -6,7 +6,7 @@ use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::Result;
|
||||
use askama::Template;
|
||||
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToUpperCamelCase};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -89,7 +89,7 @@ impl MergeWith for Config {
|
||||
pub fn generate_bindings(config: &Config, ci: &ComponentInterface) -> Result<String> {
|
||||
KotlinWrapper::new(config.clone(), ci)
|
||||
.render()
|
||||
.context("failed to render kotlin bindings")
|
||||
.map_err(|_| anyhow::anyhow!("failed to render kotlin bindings"))
|
||||
}
|
||||
|
||||
/// Renders Kotlin helper code for all types
|
||||
@ -174,6 +174,7 @@ impl<'a> KotlinWrapper<'a> {
|
||||
pub fn initialization_fns(&self) -> Vec<String> {
|
||||
self.ci
|
||||
.iter_types()
|
||||
.into_iter()
|
||||
.filter_map(|t| t.initialization_fn(&KotlinCodeOracle))
|
||||
.collect()
|
||||
}
|
||||
@ -240,12 +241,12 @@ impl CodeOracle for KotlinCodeOracle {
|
||||
|
||||
/// Get the idiomatic Kotlin rendering of a function name.
|
||||
fn fn_name(&self, nm: &str) -> String {
|
||||
format!("`{}`", nm.to_string().to_lower_camel_case())
|
||||
nm.to_string().to_lower_camel_case()
|
||||
}
|
||||
|
||||
/// Get the idiomatic Kotlin rendering of a variable name.
|
||||
fn var_name(&self, nm: &str) -> String {
|
||||
format!("`{}`", nm.to_string().to_lower_camel_case())
|
||||
nm.to_string().to_lower_camel_case()
|
||||
}
|
||||
|
||||
/// Get the idiomatic Kotlin rendering of an individual enum variant.
|
||||
@ -259,11 +260,14 @@ impl CodeOracle for KotlinCodeOracle {
|
||||
/// "Error" for any type of error but in the Java world, "Error" means a non-recoverable error
|
||||
/// and is distinguished from an "Exception".
|
||||
fn error_name(&self, nm: &str) -> String {
|
||||
// errors are a class in kotlin.
|
||||
let name = self.class_name(nm);
|
||||
let name = nm.to_string();
|
||||
match name.strip_suffix("Error") {
|
||||
None => name,
|
||||
Some(stripped) => format!("{}Exception", stripped),
|
||||
Some(stripped) => {
|
||||
let mut kt_exc_name = stripped.to_owned();
|
||||
kt_exc_name.push_str("Exception");
|
||||
kt_exc_name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +282,7 @@ impl CodeOracle for KotlinCodeOracle {
|
||||
FFIType::Int64 | FFIType::UInt64 => "Long".to_string(),
|
||||
FFIType::Float32 => "Float".to_string(),
|
||||
FFIType::Float64 => "Double".to_string(),
|
||||
FFIType::RustArcPtr(_) => "Pointer".to_string(),
|
||||
FFIType::RustArcPtr => "Pointer".to_string(),
|
||||
FFIType::RustBuffer => "RustBuffer.ByValue".to_string(),
|
||||
FFIType::ForeignBytes => "ForeignBytes.ByValue".to_string(),
|
||||
FFIType::ForeignCallback => "ForeignCallback".to_string(),
|
||||
@ -360,8 +364,11 @@ pub mod filters {
|
||||
Ok(oracle().enum_variant_name(nm))
|
||||
}
|
||||
|
||||
/// Get the idiomatic Kotlin rendering of an exception name, replacing
|
||||
/// `Error` with `Exception`.
|
||||
/// Get the idiomatic Kotlin rendering of an exception name
|
||||
///
|
||||
/// This replaces "Error" at the end of the name with "Exception". Rust code typically uses
|
||||
/// "Error" for any type of error but in the Java world, "Error" means a non-recoverable error
|
||||
/// and is distinguished from an "Exception".
|
||||
pub fn exception_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(oracle().error_name(nm))
|
||||
}
|
||||
|
@ -3,9 +3,14 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use fs_err::{self as fs, File};
|
||||
use std::{env, ffi::OsString, io::Write, process::Command};
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsString,
|
||||
fs::File,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
pub mod gen_kotlin;
|
||||
pub use gen_kotlin::{generate_bindings, Config};
|
||||
@ -15,19 +20,23 @@ use super::super::interface::ComponentInterface;
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
out_dir: &Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let mut kt_file = full_bindings_path(config, out_dir);
|
||||
fs::create_dir_all(&kt_file)?;
|
||||
let mut kt_file = full_bindings_path(config, out_dir)?;
|
||||
std::fs::create_dir_all(&kt_file)?;
|
||||
kt_file.push(format!("{}.kt", ci.namespace()));
|
||||
let mut f = File::create(&kt_file)?;
|
||||
let mut f = File::create(&kt_file).context("Failed to create .kt file for bindings")?;
|
||||
write!(f, "{}", generate_bindings(config, ci)?)?;
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("ktlint").arg("-F").arg(&kt_file).output() {
|
||||
if let Err(e) = Command::new("ktlint")
|
||||
.arg("-F")
|
||||
.arg(kt_file.to_str().unwrap())
|
||||
.output()
|
||||
{
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using ktlint: {:?}",
|
||||
kt_file.file_name().unwrap(),
|
||||
kt_file.file_name().unwrap().to_str().unwrap(),
|
||||
e
|
||||
)
|
||||
}
|
||||
@ -35,21 +44,18 @@ pub fn write_bindings(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn full_bindings_path(config: &Config, out_dir: &Utf8Path) -> Utf8PathBuf {
|
||||
let package_path: Utf8PathBuf = config.package_name().split('.').collect();
|
||||
Utf8PathBuf::from(out_dir).join(package_path)
|
||||
fn full_bindings_path(config: &Config, out_dir: &Path) -> Result<PathBuf> {
|
||||
let package_path: PathBuf = config.package_name().split('.').collect();
|
||||
Ok(PathBuf::from(out_dir).join(package_path))
|
||||
}
|
||||
|
||||
/// Generate kotlin bindings for the given namespace, then use the kotlin
|
||||
/// command-line tools to compile them into a .jar file.
|
||||
pub fn compile_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
) -> Result<()> {
|
||||
let mut kt_file = full_bindings_path(config, out_dir);
|
||||
pub fn compile_bindings(config: &Config, ci: &ComponentInterface, out_dir: &Path) -> Result<()> {
|
||||
let mut kt_file = full_bindings_path(config, out_dir)?;
|
||||
kt_file.push(format!("{}.kt", ci.namespace()));
|
||||
let jar_file = out_dir.join(format!("{}.jar", ci.namespace()));
|
||||
let mut jar_file = PathBuf::from(out_dir);
|
||||
jar_file.push(format!("{}.jar", ci.namespace()));
|
||||
let status = Command::new("kotlinc")
|
||||
// Our generated bindings should not produce any warnings; fail tests if they do.
|
||||
.arg("-Werror")
|
||||
@ -70,7 +76,7 @@ pub fn compile_bindings(
|
||||
|
||||
/// Execute the specifed kotlin script, with classpath based on the generated
|
||||
// artifacts in the given output directory.
|
||||
pub fn run_script(out_dir: &Utf8Path, script_file: &Utf8Path) -> Result<()> {
|
||||
pub fn run_script(out_dir: &Path, script_file: &Path) -> Result<()> {
|
||||
let mut cmd = Command::new("kotlinc");
|
||||
// Make sure it can load the .jar and its dependencies.
|
||||
cmd.arg("-classpath").arg(classpath_for_testing(out_dir)?);
|
||||
@ -91,8 +97,8 @@ pub fn run_script(out_dir: &Utf8Path, script_file: &Utf8Path) -> Result<()> {
|
||||
}
|
||||
|
||||
// Calculate the classpath string to use for testing
|
||||
pub fn classpath_for_testing(out_dir: &Utf8Path) -> Result<OsString> {
|
||||
let mut classpath = env::var_os("CLASSPATH").unwrap_or_default();
|
||||
pub fn classpath_for_testing(out_dir: &Path) -> Result<OsString> {
|
||||
let mut classpath = env::var_os("CLASSPATH").unwrap_or_else(|| OsString::from(""));
|
||||
// This lets java find the compiled library for the rust component.
|
||||
classpath.push(":");
|
||||
classpath.push(out_dir);
|
||||
@ -101,7 +107,7 @@ pub fn classpath_for_testing(out_dir: &Utf8Path) -> Result<OsString> {
|
||||
// Including all .jar files is needed for tests like ext-types that use multiple UDL files.
|
||||
// TODO: Instead of including all .jar files, we should only include jar files that we
|
||||
// previously built for this test.
|
||||
for entry in out_dir
|
||||
for entry in PathBuf::from(out_dir)
|
||||
.read_dir()
|
||||
.context("Failed to list target directory when running Kotlin script")?
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ fun {{ func.name()|fn_name }}({%- call kt::arg_list_decl(func) -%}): {{ return_t
|
||||
return {{ return_type|lift_fn }}({% call kt::to_ffi_call(func) %})
|
||||
}
|
||||
|
||||
{% when None %}
|
||||
{% when None -%}
|
||||
|
||||
fun {{ func.name()|fn_name }}({% call kt::arg_list_decl(func) %}) =
|
||||
{% call kt::to_ffi_call(func) %}
|
||||
|
@ -7,7 +7,7 @@
|
||||
{%- let contains_object_references = ci.item_contains_object_references(type_) %}
|
||||
|
||||
{#
|
||||
# Map `Type` instances to an include statement for that type.
|
||||
# Map `Type` instances to a `Box<dyn CodeType>` for that type.
|
||||
#
|
||||
# There is a companion match in `KotlinCodeOracle::create_code_type()` which performs a similar function for the
|
||||
# Rust code.
|
||||
|
@ -62,7 +62,7 @@
|
||||
-#}
|
||||
{%- macro arg_list_ffi_decl(func) %}
|
||||
{%- for arg in func.arguments() %}
|
||||
{{- arg.name()|var_name }}: {{ arg.type_().borrow()|ffi_type_name -}},
|
||||
{{- arg.name() }}: {{ arg.type_().borrow()|ffi_type_name -}},
|
||||
{%- endfor %}
|
||||
_uniffi_out_err: RustCallStatus
|
||||
{%- endmacro -%}
|
||||
@ -76,7 +76,7 @@
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro ffi_function_definition(func) %}
|
||||
fun {{ func.name()|fn_name }}(
|
||||
fun {{ func.name() }}(
|
||||
{%- call arg_list_ffi_decl(func) %}
|
||||
){%- match func.return_type() -%}{%- when Some with (type_) %}: {{ type_|ffi_type_name }}{% when None %}: Unit{% endmatch %}
|
||||
{% endmacro %}
|
||||
|
@ -40,7 +40,7 @@ import {{ imported_class }}
|
||||
// Public interface members begin here.
|
||||
{{ type_helper_code }}
|
||||
|
||||
{%- for func in ci.function_definitions() %}
|
||||
{%- for func in ci.iter_function_definitions() %}
|
||||
{%- include "TopLevelFunctionTemplate.kt" %}
|
||||
{%- endfor %}
|
||||
|
||||
|
@ -8,8 +8,9 @@
|
||||
//! along with some helpers for executing foreign language scripts or tests.
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use camino::Utf8Path;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::interface::ComponentInterface;
|
||||
use crate::MergeWith;
|
||||
@ -98,13 +99,17 @@ impl MergeWith for Config {
|
||||
}
|
||||
|
||||
/// Generate foreign language bindings from a compiled `uniffi` library.
|
||||
pub fn write_bindings(
|
||||
pub fn write_bindings<P>(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
out_dir: P,
|
||||
language: TargetLanguage,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
) -> Result<()>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let out_dir = out_dir.as_ref();
|
||||
match language {
|
||||
TargetLanguage::Kotlin => {
|
||||
kotlin::write_bindings(&config.kotlin, ci, out_dir, try_format_code)?
|
||||
@ -124,12 +129,16 @@ pub fn write_bindings(
|
||||
///
|
||||
/// Note: This function is only used for compiling the unit tests. See #1169 for plans to refactor
|
||||
/// it.
|
||||
pub fn compile_bindings(
|
||||
pub fn compile_bindings<P>(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
out_dir: P,
|
||||
language: TargetLanguage,
|
||||
) -> Result<()> {
|
||||
) -> Result<()>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let out_dir = out_dir.as_ref();
|
||||
match language {
|
||||
TargetLanguage::Kotlin => kotlin::compile_bindings(&config.kotlin, ci, out_dir)?,
|
||||
TargetLanguage::Swift => swift::compile_bindings(&config.swift, ci, out_dir)?,
|
||||
@ -143,11 +152,13 @@ pub fn compile_bindings(
|
||||
///
|
||||
/// Note: This function is only used for compiling the unit tests. See #1169 for plans to refactor
|
||||
/// it.
|
||||
pub fn run_script(
|
||||
out_dir: &Utf8Path,
|
||||
script_file: &Utf8Path,
|
||||
language: TargetLanguage,
|
||||
) -> Result<()> {
|
||||
pub fn run_script<P1, P2>(out_dir: P1, script_file: P2, language: TargetLanguage) -> Result<()>
|
||||
where
|
||||
P1: AsRef<Path>,
|
||||
P2: AsRef<Path>,
|
||||
{
|
||||
let out_dir = out_dir.as_ref();
|
||||
let script_file = script_file.as_ref();
|
||||
match language {
|
||||
TargetLanguage::Kotlin => kotlin::run_script(out_dir, script_file)?,
|
||||
TargetLanguage::Swift => swift::run_script(out_dir, script_file)?,
|
||||
|
@ -2,8 +2,12 @@
|
||||
* 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::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{CallbackInterface, ComponentInterface};
|
||||
use askama::Template;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use super::filters;
|
||||
pub struct CallbackInterfaceCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -31,3 +35,49 @@ impl CodeType for CallbackInterfaceCodeType {
|
||||
nm.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "CallbackInterfaceTemplate.py")]
|
||||
pub struct PythonCallbackInterface {
|
||||
inner: CallbackInterface,
|
||||
}
|
||||
|
||||
impl PythonCallbackInterface {
|
||||
pub fn new(inner: CallbackInterface, _ci: &ComponentInterface) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &CallbackInterface {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonCallbackInterface {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "CallbackInterfaceRuntime.py")]
|
||||
pub struct PythonCallbackInterfaceRuntime {
|
||||
is_needed: bool,
|
||||
}
|
||||
|
||||
impl PythonCallbackInterfaceRuntime {
|
||||
pub fn new(ci: &ComponentInterface) -> Self {
|
||||
Self {
|
||||
is_needed: !ci.iter_callback_interface_definitions().is_empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonCallbackInterfaceRuntime {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
if !self.is_needed {
|
||||
None
|
||||
} else {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,120 +2,155 @@
|
||||
* 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 super::filters;
|
||||
use crate::backend::{CodeOracle, CodeType, Literal, TypeIdentifier};
|
||||
use askama::Template;
|
||||
use paste::paste;
|
||||
|
||||
pub struct OptionalCodeType {
|
||||
inner: TypeIdentifier,
|
||||
}
|
||||
fn render_literal(oracle: &dyn CodeOracle, literal: &Literal, inner: &TypeIdentifier) -> String {
|
||||
match literal {
|
||||
Literal::Null => "None".into(),
|
||||
Literal::EmptySequence => "[]".into(),
|
||||
Literal::EmptyMap => "{}".into(),
|
||||
|
||||
impl OptionalCodeType {
|
||||
pub fn new(inner: TypeIdentifier) -> Self {
|
||||
Self { inner }
|
||||
// For optionals
|
||||
_ => oracle.find(inner).literal(oracle, literal),
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeType for OptionalCodeType {
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
oracle.find(&self.inner).type_label(oracle)
|
||||
}
|
||||
macro_rules! impl_code_type_for_compound {
|
||||
($T:ty, $canonical_name_pattern: literal, $template_file:literal, $coerce_code:expr) => {
|
||||
paste! {
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = $template_file)]
|
||||
pub struct $T {
|
||||
inner: TypeIdentifier,
|
||||
outer: TypeIdentifier,
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"Optional{}",
|
||||
oracle.find(&self.inner).canonical_name(oracle),
|
||||
)
|
||||
}
|
||||
impl $T {
|
||||
pub fn new(inner: TypeIdentifier, outer: TypeIdentifier) -> Self {
|
||||
Self { inner, outer }
|
||||
}
|
||||
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
match literal {
|
||||
Literal::Null => "None".into(),
|
||||
_ => oracle.find(&self.inner).literal(oracle, literal),
|
||||
fn inner(&self) -> &TypeIdentifier {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
fn outer(&self) -> &TypeIdentifier {
|
||||
&self.outer
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeType for $T {
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
oracle.find(self.inner()).type_label(oracle)
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!($canonical_name_pattern, oracle.find(self.inner()).canonical_name(oracle))
|
||||
}
|
||||
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
render_literal(oracle, &literal, self.inner())
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn coerce(&self, oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
$coerce_code(self, oracle, nm)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn coerce(&self, oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
format!(
|
||||
"(None if {} is None else {})",
|
||||
nm,
|
||||
oracle.find(&self.inner).coerce(oracle, nm)
|
||||
)
|
||||
}
|
||||
impl_code_type_for_compound!(
|
||||
OptionalCodeType,
|
||||
"Optional{}",
|
||||
"OptionalTemplate.py",
|
||||
optional_coerce
|
||||
);
|
||||
fn optional_coerce(this: &OptionalCodeType, oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
format!(
|
||||
"(None if {} is None else {})",
|
||||
nm,
|
||||
oracle.find(this.inner()).coerce(oracle, nm)
|
||||
)
|
||||
}
|
||||
|
||||
pub struct SequenceCodeType {
|
||||
inner: TypeIdentifier,
|
||||
}
|
||||
|
||||
impl SequenceCodeType {
|
||||
pub fn new(inner: TypeIdentifier) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeType for SequenceCodeType {
|
||||
fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
"list".to_string()
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"Sequence{}",
|
||||
oracle.find(&self.inner).canonical_name(oracle),
|
||||
)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
match literal {
|
||||
Literal::EmptySequence => "[]".into(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn coerce(&self, oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
format!(
|
||||
"list({} for x in {})",
|
||||
oracle.find(&self.inner).coerce(oracle, "x"),
|
||||
nm
|
||||
)
|
||||
}
|
||||
impl_code_type_for_compound!(
|
||||
SequenceCodeType,
|
||||
"Sequence{}",
|
||||
"SequenceTemplate.py",
|
||||
sequence_coerce
|
||||
);
|
||||
fn sequence_coerce(this: &SequenceCodeType, oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
format!(
|
||||
"list({} for x in {})",
|
||||
oracle.find(this.inner()).coerce(oracle, "x"),
|
||||
nm
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "MapTemplate.py")]
|
||||
pub struct MapCodeType {
|
||||
key: TypeIdentifier,
|
||||
value: TypeIdentifier,
|
||||
outer: TypeIdentifier,
|
||||
}
|
||||
|
||||
impl MapCodeType {
|
||||
pub fn new(key: TypeIdentifier, value: TypeIdentifier) -> Self {
|
||||
Self { key, value }
|
||||
pub fn new(key: TypeIdentifier, value: TypeIdentifier, outer: TypeIdentifier) -> Self {
|
||||
Self { key, value, outer }
|
||||
}
|
||||
|
||||
fn key(&self) -> &TypeIdentifier {
|
||||
&self.key
|
||||
}
|
||||
|
||||
fn value(&self) -> &TypeIdentifier {
|
||||
&self.value
|
||||
}
|
||||
|
||||
fn outer(&self) -> &TypeIdentifier {
|
||||
&self.outer
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeType for MapCodeType {
|
||||
fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
"dict".to_string()
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"Map<{}, {}>",
|
||||
self.key().type_label(oracle),
|
||||
self.value().type_label(oracle),
|
||||
)
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"Map{}{}",
|
||||
oracle.find(&self.key).canonical_name(oracle),
|
||||
oracle.find(&self.value).canonical_name(oracle),
|
||||
self.key().type_label(oracle),
|
||||
self.value().type_label(oracle),
|
||||
)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
match literal {
|
||||
Literal::EmptyMap => "{}".into(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
render_literal(oracle, literal, self.value())
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn coerce(&self, oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
format!(
|
||||
"dict(({}, {}) for (k, v) in {}.items())",
|
||||
self.key.coerce(oracle, "k"),
|
||||
self.value.coerce(oracle, "v"),
|
||||
self.key().coerce(oracle, "k"),
|
||||
self.value().coerce(oracle, "v"),
|
||||
nm
|
||||
)
|
||||
}
|
||||
|
@ -2,7 +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::backend::{CodeOracle, CodeType};
|
||||
use super::{filters, CustomTypeConfig};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, TypeIdentifier};
|
||||
use askama::Template;
|
||||
|
||||
pub struct CustomCodeType {
|
||||
name: String,
|
||||
@ -26,4 +28,42 @@ impl CodeType for CustomCodeType {
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
nm.to_string()
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"# Helper code for {} is found in CustomType.py",
|
||||
self.name,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "CustomType.py")]
|
||||
pub struct PythonCustomType {
|
||||
name: String,
|
||||
builtin: TypeIdentifier,
|
||||
config: Option<CustomTypeConfig>,
|
||||
}
|
||||
|
||||
impl PythonCustomType {
|
||||
pub fn new(name: String, builtin: TypeIdentifier, config: Option<CustomTypeConfig>) -> Self {
|
||||
Self {
|
||||
name,
|
||||
builtin,
|
||||
config,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonCustomType {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn imports(&self, _oracle: &dyn CodeOracle) -> Option<Vec<String>> {
|
||||
match &self.config {
|
||||
None => None,
|
||||
Some(custom_type_config) => custom_type_config.imports.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,11 @@
|
||||
* 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::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Enum};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
pub struct EnumCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -35,7 +38,36 @@ impl CodeType for EnumCodeType {
|
||||
}
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"# Helper code for {} enum is found in EnumTemplate.py",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
nm.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "EnumTemplate.py")]
|
||||
pub struct PythonEnum {
|
||||
inner: Enum,
|
||||
}
|
||||
|
||||
impl PythonEnum {
|
||||
pub fn new(inner: Enum, _ci: &ComponentInterface) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Enum {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonEnum {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,12 @@
|
||||
* 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::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Error, Type};
|
||||
use askama::Template;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use super::filters;
|
||||
pub struct ErrorCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -27,7 +31,36 @@ impl CodeType for ErrorCodeType {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"# Helper code for {} error is found in ErrorTemplate.py",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
nm.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "ErrorTemplate.py")]
|
||||
pub struct PythonError {
|
||||
inner: Error,
|
||||
}
|
||||
|
||||
impl PythonError {
|
||||
pub fn new(inner: Error, _ci: &ComponentInterface) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Error {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonError {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,20 @@
|
||||
* 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 super::filters;
|
||||
use crate::backend::{CodeOracle, CodeType};
|
||||
use askama::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "ExternalTemplate.py")]
|
||||
pub struct ExternalCodeType {
|
||||
name: String,
|
||||
crate_name: String,
|
||||
}
|
||||
|
||||
impl ExternalCodeType {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self { name }
|
||||
pub fn new(name: String, crate_name: String) -> Self {
|
||||
Self { name, crate_name }
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +28,10 @@ impl CodeType for ExternalCodeType {
|
||||
format!("Type{}", self.name)
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, _nm: &str) -> String {
|
||||
panic!("should not be necessary to coerce External types");
|
||||
}
|
||||
|
31
third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/function.rs
vendored
Normal file
31
third_party/rust/uniffi_bindgen/src/bindings/python/gen_python/function.rs
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
/* 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/. */
|
||||
|
||||
use crate::backend::{CodeDeclaration, CodeOracle};
|
||||
use crate::interface::{ComponentInterface, Function};
|
||||
use askama::Template;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use super::filters;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "TopLevelFunctionTemplate.py")]
|
||||
pub struct PythonFunction {
|
||||
inner: Function,
|
||||
}
|
||||
|
||||
impl PythonFunction {
|
||||
pub fn new(inner: Function, _ci: &ComponentInterface) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
pub fn inner(&self) -> &Function {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonFunction {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
@ -2,12 +2,17 @@
|
||||
* 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/. */
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use super::filters;
|
||||
use crate::backend::{CodeOracle, CodeType, Literal};
|
||||
use askama::Template;
|
||||
use paste::paste;
|
||||
|
||||
macro_rules! impl_code_type_for_miscellany {
|
||||
($T:ty, $canonical_name:literal) => {
|
||||
($T:ty, $canonical_name:literal, $template_file:literal) => {
|
||||
paste! {
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = $template_file)]
|
||||
pub struct $T;
|
||||
|
||||
impl CodeType for $T {
|
||||
@ -23,6 +28,10 @@ macro_rules! impl_code_type_for_miscellany {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
nm.to_string()
|
||||
}
|
||||
@ -31,6 +40,6 @@ macro_rules! impl_code_type_for_miscellany {
|
||||
};
|
||||
}
|
||||
|
||||
impl_code_type_for_miscellany!(TimestampCodeType, "Timestamp");
|
||||
impl_code_type_for_miscellany!(TimestampCodeType, "Timestamp", "TimestampHelper.py");
|
||||
|
||||
impl_code_type_for_miscellany!(DurationCodeType, "Duration");
|
||||
impl_code_type_for_miscellany!(DurationCodeType, "Duration", "DurationHelper.py");
|
||||
|
@ -2,15 +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::{Context, Result};
|
||||
use anyhow::Result;
|
||||
use askama::Template;
|
||||
use heck::{ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::backend::{CodeOracle, CodeType, TemplateExpression, TypeIdentifier};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, TemplateExpression, TypeIdentifier};
|
||||
use crate::interface::*;
|
||||
use crate::MergeWith;
|
||||
|
||||
@ -20,56 +19,12 @@ mod custom;
|
||||
mod enum_;
|
||||
mod error;
|
||||
mod external;
|
||||
mod function;
|
||||
mod miscellany;
|
||||
mod object;
|
||||
mod primitives;
|
||||
mod record;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
// Taken from Python's `keyword.py` module.
|
||||
static ref KEYWORDS: HashSet<String> = {
|
||||
let kwlist = vec![
|
||||
"False",
|
||||
"None",
|
||||
"True",
|
||||
"__peg_parser__",
|
||||
"and",
|
||||
"as",
|
||||
"assert",
|
||||
"async",
|
||||
"await",
|
||||
"break",
|
||||
"class",
|
||||
"continue",
|
||||
"def",
|
||||
"del",
|
||||
"elif",
|
||||
"else",
|
||||
"except",
|
||||
"finally",
|
||||
"for",
|
||||
"from",
|
||||
"global",
|
||||
"if",
|
||||
"import",
|
||||
"in",
|
||||
"is",
|
||||
"lambda",
|
||||
"nonlocal",
|
||||
"not",
|
||||
"or",
|
||||
"pass",
|
||||
"raise",
|
||||
"return",
|
||||
"try",
|
||||
"while",
|
||||
"with",
|
||||
"yield",
|
||||
];
|
||||
HashSet::from_iter(kwlist.into_iter().map(|s| s.to_string()))
|
||||
};
|
||||
}
|
||||
|
||||
// Config options to customize the generated python.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
@ -117,58 +72,9 @@ impl MergeWith for Config {
|
||||
|
||||
// Generate python bindings for the given ComponentInterface, as a string.
|
||||
pub fn generate_python_bindings(config: &Config, ci: &ComponentInterface) -> Result<String> {
|
||||
PythonWrapper::new(config.clone(), ci)
|
||||
PythonWrapper::new(PythonCodeOracle, config.clone(), ci)
|
||||
.render()
|
||||
.context("failed to render python bindings")
|
||||
}
|
||||
|
||||
/// Renders Python helper code for all types
|
||||
///
|
||||
/// This template is a bit different than others in that it stores internal state from the render
|
||||
/// process. Make sure to only call `render()` once.
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "Types.py")]
|
||||
pub struct TypeRenderer<'a> {
|
||||
python_config: &'a Config,
|
||||
ci: &'a ComponentInterface,
|
||||
// Track included modules for the `include_once()` macro
|
||||
include_once_names: RefCell<HashSet<String>>,
|
||||
// Track imports added with the `add_import()` macro
|
||||
imports: RefCell<BTreeSet<String>>,
|
||||
}
|
||||
|
||||
impl<'a> TypeRenderer<'a> {
|
||||
fn new(python_config: &'a Config, ci: &'a ComponentInterface) -> Self {
|
||||
Self {
|
||||
python_config,
|
||||
ci,
|
||||
include_once_names: RefCell::new(HashSet::new()),
|
||||
imports: RefCell::new(BTreeSet::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// The following methods are used by the `Types.py` macros.
|
||||
|
||||
// Helper for the including a template, but only once.
|
||||
//
|
||||
// The first time this is called with a name it will return true, indicating that we should
|
||||
// include the template. Subsequent calls will return false.
|
||||
fn include_once_check(&self, name: &str) -> bool {
|
||||
self.include_once_names
|
||||
.borrow_mut()
|
||||
.insert(name.to_string())
|
||||
}
|
||||
|
||||
// Helper to add an import statement
|
||||
//
|
||||
// Call this inside your template to cause an import statement to be added at the top of the
|
||||
// file. Imports will be sorted and de-deuped.
|
||||
//
|
||||
// Returns an empty string so that it can be used inside an askama `{{ }}` block.
|
||||
fn add_import(&self, name: &str) -> &str {
|
||||
self.imports.borrow_mut().insert(name.to_owned());
|
||||
""
|
||||
}
|
||||
.map_err(|_| anyhow::anyhow!("failed to render python bindings"))
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
@ -176,32 +82,96 @@ impl<'a> TypeRenderer<'a> {
|
||||
pub struct PythonWrapper<'a> {
|
||||
ci: &'a ComponentInterface,
|
||||
config: Config,
|
||||
type_helper_code: String,
|
||||
type_imports: BTreeSet<String>,
|
||||
oracle: PythonCodeOracle,
|
||||
}
|
||||
impl<'a> PythonWrapper<'a> {
|
||||
pub fn new(config: Config, ci: &'a ComponentInterface) -> Self {
|
||||
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,
|
||||
type_helper_code,
|
||||
type_imports,
|
||||
}
|
||||
pub fn new(oracle: PythonCodeOracle, config: Config, ci: &'a ComponentInterface) -> Self {
|
||||
Self { oracle, config, ci }
|
||||
}
|
||||
|
||||
pub fn members(&self) -> Vec<Box<dyn CodeDeclaration + 'a>> {
|
||||
let ci = self.ci;
|
||||
vec![
|
||||
Box::new(callback_interface::PythonCallbackInterfaceRuntime::new(ci))
|
||||
as Box<dyn CodeDeclaration>,
|
||||
]
|
||||
.into_iter()
|
||||
.chain(
|
||||
ci.iter_enum_definitions().into_iter().map(|inner| {
|
||||
Box::new(enum_::PythonEnum::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(ci.iter_function_definitions().into_iter().map(|inner| {
|
||||
Box::new(function::PythonFunction::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.chain(ci.iter_object_definitions().into_iter().map(|inner| {
|
||||
Box::new(object::PythonObject::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.chain(ci.iter_record_definitions().into_iter().map(|inner| {
|
||||
Box::new(record::PythonRecord::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.chain(
|
||||
ci.iter_error_definitions().into_iter().map(|inner| {
|
||||
Box::new(error::PythonError::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
ci.iter_callback_interface_definitions()
|
||||
.into_iter()
|
||||
.map(|inner| {
|
||||
Box::new(callback_interface::PythonCallbackInterface::new(inner, ci))
|
||||
as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(ci.iter_custom_types().into_iter().map(|(name, type_)| {
|
||||
let config = self.config.custom_types.get(&name).cloned();
|
||||
Box::new(custom::PythonCustomType::new(name, type_, config)) as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn initialization_code(&self) -> Vec<String> {
|
||||
let oracle = &self.oracle;
|
||||
self.members()
|
||||
.into_iter()
|
||||
.filter_map(|member| member.initialization_code(oracle))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn declaration_code(&self) -> Vec<String> {
|
||||
let oracle = &self.oracle;
|
||||
self.members()
|
||||
.into_iter()
|
||||
.filter_map(|member| member.definition_code(oracle))
|
||||
.chain(
|
||||
self.ci
|
||||
.iter_types()
|
||||
.into_iter()
|
||||
.filter_map(|type_| oracle.find(&type_).helper_code(oracle)),
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn imports(&self) -> Vec<String> {
|
||||
self.type_imports.iter().cloned().collect()
|
||||
}
|
||||
}
|
||||
let oracle = &self.oracle;
|
||||
let mut imports: Vec<String> = self
|
||||
.members()
|
||||
.into_iter()
|
||||
.filter_map(|member| member.imports(oracle))
|
||||
.flatten()
|
||||
.chain(
|
||||
self.ci
|
||||
.iter_types()
|
||||
.into_iter()
|
||||
.filter_map(|type_| oracle.find(&type_).imports(oracle))
|
||||
.flatten(),
|
||||
)
|
||||
.collect::<HashSet<String>>()
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
fn fixup_keyword(name: String) -> String {
|
||||
if KEYWORDS.contains(&name) {
|
||||
format!("_{}", name)
|
||||
} else {
|
||||
name
|
||||
imports.sort();
|
||||
imports
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,14 +179,11 @@ fn fixup_keyword(name: String) -> String {
|
||||
pub struct PythonCodeOracle;
|
||||
|
||||
impl PythonCodeOracle {
|
||||
// Map `Type` instances to a `Box<dyn CodeType>` for that type.
|
||||
//
|
||||
// There is a companion match in `templates/Types.py` which performs a similar function for the
|
||||
// template code.
|
||||
//
|
||||
// - When adding additional types here, make sure to also add a match arm to the `Types.py` template.
|
||||
// - To keep things managable, let's try to limit ourselves to these 2 mega-matches
|
||||
fn create_code_type(&self, type_: TypeIdentifier) -> Box<dyn CodeType> {
|
||||
// I really want access to the ComponentInterface here so I can look up the interface::{Enum, Record, Error, Object, etc}
|
||||
// However, there's some violence and gore I need to do to (temporarily) make the oracle usable from filters.
|
||||
|
||||
// Some refactor of the templates is needed to make progress here: I think most of the filter functions need to take an &dyn CodeOracle
|
||||
match type_ {
|
||||
Type::UInt8 => Box::new(primitives::UInt8CodeType),
|
||||
Type::Int8 => Box::new(primitives::Int8CodeType),
|
||||
@ -242,10 +209,25 @@ impl PythonCodeOracle {
|
||||
Box::new(callback_interface::CallbackInterfaceCodeType::new(id))
|
||||
}
|
||||
|
||||
Type::Optional(inner) => Box::new(compounds::OptionalCodeType::new(*inner)),
|
||||
Type::Sequence(inner) => Box::new(compounds::SequenceCodeType::new(*inner)),
|
||||
Type::Map(key, value) => Box::new(compounds::MapCodeType::new(*key, *value)),
|
||||
Type::External { name, .. } => Box::new(external::ExternalCodeType::new(name)),
|
||||
Type::Optional(ref inner) => {
|
||||
let outer = type_.clone();
|
||||
let inner = *inner.to_owned();
|
||||
Box::new(compounds::OptionalCodeType::new(inner, outer))
|
||||
}
|
||||
Type::Sequence(ref inner) => {
|
||||
let outer = type_.clone();
|
||||
let inner = *inner.to_owned();
|
||||
Box::new(compounds::SequenceCodeType::new(inner, outer))
|
||||
}
|
||||
Type::Map(ref key, ref value) => {
|
||||
let outer = type_.clone();
|
||||
let key = *key.to_owned();
|
||||
let value = *value.to_owned();
|
||||
Box::new(compounds::MapCodeType::new(key, value, outer))
|
||||
}
|
||||
Type::External { name, crate_name } => {
|
||||
Box::new(external::ExternalCodeType::new(name, crate_name))
|
||||
}
|
||||
Type::Custom { name, .. } => Box::new(custom::CustomCodeType::new(name)),
|
||||
}
|
||||
}
|
||||
@ -258,31 +240,38 @@ impl CodeOracle for PythonCodeOracle {
|
||||
|
||||
/// Get the idiomatic Python rendering of a class name (for enums, records, errors, etc).
|
||||
fn class_name(&self, nm: &str) -> String {
|
||||
fixup_keyword(nm.to_string().to_upper_camel_case())
|
||||
nm.to_string().to_upper_camel_case()
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of a function name.
|
||||
fn fn_name(&self, nm: &str) -> String {
|
||||
fixup_keyword(nm.to_string().to_snake_case())
|
||||
nm.to_string().to_snake_case()
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of a variable name.
|
||||
fn var_name(&self, nm: &str) -> String {
|
||||
fixup_keyword(nm.to_string().to_snake_case())
|
||||
nm.to_string().to_snake_case()
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of an individual enum variant.
|
||||
fn enum_variant_name(&self, nm: &str) -> String {
|
||||
fixup_keyword(nm.to_string().to_shouty_snake_case())
|
||||
nm.to_string().to_shouty_snake_case()
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of an exception name
|
||||
/// This replaces "Error" at the end of the name with "Exception".
|
||||
///
|
||||
/// This replaces "Error" at the end of the name with "Exception". Rust code typically uses
|
||||
/// "Error" for any type of error but in the Java world, "Error" means a non-recoverable error
|
||||
/// and is distinguished from an "Exception".
|
||||
fn error_name(&self, nm: &str) -> String {
|
||||
let name = fixup_keyword(self.class_name(nm));
|
||||
let name = nm.to_string();
|
||||
match name.strip_suffix("Error") {
|
||||
None => name,
|
||||
Some(stripped) => format!("{}Exception", stripped),
|
||||
Some(stripped) => {
|
||||
let mut py_exc_name = stripped.to_owned();
|
||||
py_exc_name.push_str("Exception");
|
||||
py_exc_name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +287,7 @@ impl CodeOracle for PythonCodeOracle {
|
||||
FFIType::UInt64 => "ctypes.c_uint64".to_string(),
|
||||
FFIType::Float32 => "ctypes.c_float".to_string(),
|
||||
FFIType::Float64 => "ctypes.c_double".to_string(),
|
||||
FFIType::RustArcPtr(_) => "ctypes.c_void_p".to_string(),
|
||||
FFIType::RustArcPtr => "ctypes.c_void_p".to_string(),
|
||||
FFIType::RustBuffer => "RustBuffer".to_string(),
|
||||
FFIType::ForeignBytes => "ForeignBytes".to_string(),
|
||||
FFIType::ForeignCallback => "FOREIGN_CALLBACK_T".to_string(),
|
||||
@ -378,6 +367,10 @@ pub mod filters {
|
||||
}
|
||||
|
||||
/// Get the idiomatic Python rendering of an exception name
|
||||
///
|
||||
/// This replaces "Error" at the end of the name with "Exception". Rust code typically uses
|
||||
/// "Error" for any type of error but in the Java world, "Error" means a non-recoverable error
|
||||
/// and is distinguished from an "Exception".
|
||||
pub fn exception_name(nm: &str) -> Result<String, askama::Error> {
|
||||
Ok(oracle().error_name(nm))
|
||||
}
|
||||
|
@ -2,8 +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::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Object};
|
||||
use askama::Template;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
// Filters is used by ObjectTemplate.py, which looks for the filters module here.
|
||||
use super::filters;
|
||||
pub struct ObjectCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -27,7 +32,35 @@ impl CodeType for ObjectCodeType {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"# Helper code for {} class is found in ObjectTemplate.py",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
nm.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "ObjectTemplate.py")]
|
||||
pub struct PythonObject {
|
||||
inner: Object,
|
||||
}
|
||||
|
||||
impl PythonObject {
|
||||
pub fn new(inner: Object, _ci: &ComponentInterface) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
pub fn inner(&self) -> &Object {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonObject {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use super::filters;
|
||||
use crate::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::interface::Radix;
|
||||
use askama::Template;
|
||||
use paste::paste;
|
||||
|
||||
fn render_literal(_oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
@ -34,8 +37,10 @@ fn render_literal(_oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
}
|
||||
|
||||
macro_rules! impl_code_type_for_primitive {
|
||||
($T:ty, $class_name:literal, $coerce_code:expr) => {
|
||||
($T:ty, $class_name:literal, $template_file:literal, $coerce_code:expr) => {
|
||||
paste! {
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = $template_file)]
|
||||
pub struct $T;
|
||||
|
||||
impl CodeType for $T {
|
||||
@ -47,6 +52,10 @@ macro_rules! impl_code_type_for_primitive {
|
||||
render_literal(oracle, &literal)
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
format!($coerce_code, nm)
|
||||
}
|
||||
@ -55,15 +64,15 @@ macro_rules! impl_code_type_for_primitive {
|
||||
};
|
||||
}
|
||||
|
||||
impl_code_type_for_primitive!(BooleanCodeType, "Bool", "bool({})");
|
||||
impl_code_type_for_primitive!(StringCodeType, "String", "{}");
|
||||
impl_code_type_for_primitive!(Int8CodeType, "Int8", "int({})");
|
||||
impl_code_type_for_primitive!(Int16CodeType, "Int16", "int({})");
|
||||
impl_code_type_for_primitive!(Int32CodeType, "Int32", "int({})");
|
||||
impl_code_type_for_primitive!(Int64CodeType, "Int64", "int({})");
|
||||
impl_code_type_for_primitive!(UInt8CodeType, "UInt8", "int({})");
|
||||
impl_code_type_for_primitive!(UInt16CodeType, "UInt16", "int({})");
|
||||
impl_code_type_for_primitive!(UInt32CodeType, "UInt32", "int({})");
|
||||
impl_code_type_for_primitive!(UInt64CodeType, "UInt64", "int({})");
|
||||
impl_code_type_for_primitive!(Float32CodeType, "Float", "float({})");
|
||||
impl_code_type_for_primitive!(Float64CodeType, "Double", "float({})");
|
||||
impl_code_type_for_primitive!(BooleanCodeType, "Bool", "BooleanHelper.py", "bool({})");
|
||||
impl_code_type_for_primitive!(StringCodeType, "String", "StringHelper.py", "{}");
|
||||
impl_code_type_for_primitive!(Int8CodeType, "Int8", "Int8Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(Int16CodeType, "Int16", "Int16Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(Int32CodeType, "Int32", "Int32Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(Int64CodeType, "Int64", "Int64Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(UInt8CodeType, "UInt8", "UInt8Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(UInt16CodeType, "UInt16", "UInt16Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(UInt32CodeType, "UInt32", "UInt32Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(UInt64CodeType, "UInt64", "UInt64Helper.py", "int({})");
|
||||
impl_code_type_for_primitive!(Float32CodeType, "Float", "Float32Helper.py", "float({})");
|
||||
impl_code_type_for_primitive!(Float64CodeType, "Double", "Float64Helper.py", "float({})");
|
||||
|
@ -2,7 +2,11 @@
|
||||
* 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::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Record};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
|
||||
pub struct RecordCodeType {
|
||||
id: String,
|
||||
@ -27,7 +31,36 @@ impl CodeType for RecordCodeType {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"# Helper code for {} record is found in RecordTemplate.py",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
|
||||
fn coerce(&self, _oracle: &dyn CodeOracle, nm: &str) -> String {
|
||||
nm.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "py", escape = "none", path = "RecordTemplate.py")]
|
||||
pub struct PythonRecord {
|
||||
inner: Record,
|
||||
}
|
||||
|
||||
impl PythonRecord {
|
||||
pub fn new(inner: Record, _ci: &ComponentInterface) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Record {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for PythonRecord {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,18 @@
|
||||
* 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 std::{env, io::Write, process::Command};
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsString,
|
||||
fs::File,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use fs_err::File;
|
||||
|
||||
pub mod gen_python;
|
||||
use camino::Utf8Path;
|
||||
pub use gen_python::{generate_python_bindings, Config};
|
||||
|
||||
use super::super::interface::ComponentInterface;
|
||||
@ -17,18 +22,19 @@ use super::super::interface::ComponentInterface;
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
out_dir: &Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let py_file = out_dir.join(format!("{}.py", ci.namespace()));
|
||||
let mut f = File::create(&py_file)?;
|
||||
let mut py_file = PathBuf::from(out_dir);
|
||||
py_file.push(format!("{}.py", ci.namespace()));
|
||||
let mut f = File::create(&py_file).context("Failed to create .py file for bindings")?;
|
||||
write!(f, "{}", generate_python_bindings(config, ci)?)?;
|
||||
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("yapf").arg(&py_file).output() {
|
||||
if let Err(e) = Command::new("yapf").arg(py_file.to_str().unwrap()).output() {
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using yapf: {:?}",
|
||||
py_file.file_name().unwrap(),
|
||||
py_file.file_name().unwrap().to_str().unwrap(),
|
||||
e
|
||||
)
|
||||
}
|
||||
@ -39,13 +45,12 @@ pub fn write_bindings(
|
||||
|
||||
/// Execute the specifed python script, with environment based on the generated
|
||||
/// artifacts in the given output directory.
|
||||
pub fn run_script(out_dir: &Utf8Path, script_file: &Utf8Path) -> Result<()> {
|
||||
pub fn run_script(out_dir: &Path, script_file: &Path) -> Result<()> {
|
||||
let mut cmd = Command::new("python3");
|
||||
// This helps python find the generated .py wrapper for rust component.
|
||||
let pythonpath = env::var_os("PYTHONPATH").unwrap_or_default();
|
||||
let pythonpath = env::join_paths(
|
||||
env::split_paths(&pythonpath).chain(vec![out_dir.as_std_path().to_owned()]),
|
||||
)?;
|
||||
let pythonpath = env::var_os("PYTHONPATH").unwrap_or_else(|| OsString::from(""));
|
||||
let pythonpath =
|
||||
env::join_paths(env::split_paths(&pythonpath).chain(vec![out_dir.to_path_buf()]))?;
|
||||
cmd.env("PYTHONPATH", pythonpath);
|
||||
// We should now be able to execute the tests successfully.
|
||||
cmd.arg(script_file);
|
||||
|
@ -1,11 +1,12 @@
|
||||
{%- let cbi = ci.get_callback_interface_definition(id).unwrap() %}
|
||||
{%- let foreign_callback = format!("foreignCallback{}", canonical_type_name) %}
|
||||
{% import "macros.py" as py %}
|
||||
{%- let cbi = self.inner() %}
|
||||
{%- let canonical_name = cbi|canonical_name %}
|
||||
{%- let ffi_converter = cbi|ffi_converter_name %}
|
||||
{%- let foreign_callback = format!("foreignCallback{}", canonical_name) %}
|
||||
|
||||
{% if self.include_once_check("CallbackInterfaceRuntime.py") %}{% include "CallbackInterfaceRuntime.py" %}{% endif %}
|
||||
# Declaration and FfiConverters for {{ cbi|type_name }} Callback Interface
|
||||
|
||||
# Declaration and FfiConverters for {{ type_name }} Callback Interface
|
||||
|
||||
class {{ type_name }}:
|
||||
class {{ cbi|type_name }}:
|
||||
{% for meth in cbi.methods() -%}
|
||||
def {{ meth.name()|fn_name }}({% call py::arg_list_decl(meth) %}):
|
||||
raise NotImplementedError
|
||||
@ -44,12 +45,12 @@ def py_{{ foreign_callback }}(handle, method, args, buf_ptr):
|
||||
# https://github.com/mozilla/uniffi-rs/issues/351
|
||||
{% endfor %}
|
||||
|
||||
cb = {{ ffi_converter_name }}.lift(handle)
|
||||
cb = {{ ffi_converter }}.lift(handle)
|
||||
if not cb:
|
||||
raise InternalError("No callback in handlemap; this is a Uniffi bug")
|
||||
|
||||
if method == IDX_CALLBACK_FREE:
|
||||
{{ ffi_converter_name }}.drop(handle)
|
||||
{{ ffi_converter }}.drop(handle)
|
||||
# No return value.
|
||||
# See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs`
|
||||
return 0
|
||||
@ -79,4 +80,4 @@ def py_{{ foreign_callback }}(handle, method, args, buf_ptr):
|
||||
|
||||
# The FfiConverter which transforms the Callbacks in to Handles to pass to Rust.
|
||||
rust_call(lambda err: _UniFFILib.{{ cbi.ffi_init_callback().name() }}({{ foreign_callback }}, err))
|
||||
{{ ffi_converter_name }} = FfiConverterCallbackInterface({{ foreign_callback }})
|
||||
{{ ffi_converter }} = FfiConverterCallbackInterface({{ foreign_callback }})
|
||||
|
@ -1,5 +1,5 @@
|
||||
{%- match python_config.custom_types.get(name.as_str()) %}
|
||||
{% when None %}
|
||||
{%- match config %}
|
||||
{%- when None %}
|
||||
{#- No custom type config, just forward all methods to our builtin type #}
|
||||
class FfiConverterType{{ name }}:
|
||||
@staticmethod
|
||||
@ -18,16 +18,7 @@ class FfiConverterType{{ name }}:
|
||||
def lower(value):
|
||||
return {{ builtin|ffi_converter_name }}.lower(value)
|
||||
|
||||
{%- when Some(config) %}
|
||||
|
||||
{%- match config.imports %}
|
||||
{%- when Some(imports) %}
|
||||
{%- for import_name in imports %}
|
||||
{{ self.add_import(import_name) }}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
{%- when Some with (config) %}
|
||||
{#- Custom type config supplied, use it to convert the builtin type #}
|
||||
class FfiConverterType{{ name }}:
|
||||
@staticmethod
|
||||
|
@ -4,18 +4,18 @@
|
||||
# when none of the variants have associated data, or a generic nested-class
|
||||
# construct when they do.
|
||||
#}
|
||||
{%- let e = ci.get_enum_definition(name).unwrap() %}
|
||||
{%- let e = self.inner() %}
|
||||
{% if e.is_flat() %}
|
||||
|
||||
class {{ type_name }}(enum.Enum):
|
||||
class {{ e|type_name }}(enum.Enum):
|
||||
{% for variant in e.variants() -%}
|
||||
{{ variant.name()|enum_variant_py }} = {{ loop.index }}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
|
||||
class {{ type_name }}:
|
||||
class {{ e|type_name }}:
|
||||
def __init__(self):
|
||||
raise RuntimeError("{{ type_name }} cannot be instantiated directly")
|
||||
raise RuntimeError("{{ e|type_name }} cannot be instantiated directly")
|
||||
|
||||
# Each enum variant is a nested class of the enum itself.
|
||||
{% for variant in e.variants() -%}
|
||||
@ -30,7 +30,7 @@ class {{ type_name }}:
|
||||
{% 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 "{{ e|type_name }}.{{ variant.name()|enum_variant_py }}({% 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 }}():
|
||||
@ -46,19 +46,19 @@ class {{ type_name }}:
|
||||
# whether an instance is that variant.
|
||||
{% for variant in e.variants() -%}
|
||||
def is_{{ variant.name()|var_name }}(self):
|
||||
return isinstance(self, {{ type_name }}.{{ variant.name()|enum_variant_py }})
|
||||
return isinstance(self, {{ e|type_name }}.{{ variant.name()|enum_variant_py }})
|
||||
{% 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 }},), {})
|
||||
{{ e|type_name }}.{{ variant.name()|enum_variant_py }} = type("{{ e|type_name }}.{{ variant.name()|enum_variant_py }}", ({{ e|type_name }}.{{variant.name()|enum_variant_py}}, {{ e|type_name }},), {})
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
class {{ e|ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@staticmethod
|
||||
def read(buf):
|
||||
variant = buf.readI32()
|
||||
@ -66,9 +66,9 @@ class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
{%- for variant in e.variants() %}
|
||||
if variant == {{ loop.index }}:
|
||||
{%- if e.is_flat() %}
|
||||
return {{ type_name }}.{{variant.name()|enum_variant_py}}
|
||||
return {{ e|type_name }}.{{variant.name()|enum_variant_py}}
|
||||
{%- else %}
|
||||
return {{ type_name }}.{{variant.name()|enum_variant_py}}(
|
||||
return {{ e|type_name }}.{{variant.name()|enum_variant_py}}(
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field|read_fn }}(buf),
|
||||
{%- endfor %}
|
||||
@ -80,7 +80,7 @@ class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
def write(value, buf):
|
||||
{%- for variant in e.variants() %}
|
||||
{%- if e.is_flat() %}
|
||||
if value == {{ type_name }}.{{ variant.name()|enum_variant_py }}:
|
||||
if value == {{ e|type_name }}.{{ variant.name()|enum_variant_py }}:
|
||||
buf.writeI32({{ loop.index }})
|
||||
{%- else %}
|
||||
if value.is_{{ variant.name()|var_name }}():
|
||||
|
@ -1,5 +1,5 @@
|
||||
{%- let e = ci.get_error_definition(name).unwrap() %}
|
||||
class {{ type_name }}(Exception):
|
||||
{%- let e = self.inner() %}
|
||||
class {{ e|type_name }}(Exception):
|
||||
{%- if e.is_flat() %}
|
||||
|
||||
# Each variant is a nested class of the error itself.
|
||||
@ -27,24 +27,24 @@ class {{ type_name }}(Exception):
|
||||
{%- if variant.has_fields() %}
|
||||
field_parts = [
|
||||
{%- for field in variant.fields() %}
|
||||
'{{ field.name()|var_name }}={!r}'.format(self.{{ field.name()|var_name }}),
|
||||
'{{ field.name() }}={!r}'.format(self.{{ field.name() }}),
|
||||
{%- endfor %}
|
||||
]
|
||||
return "{{ type_name }}.{{ variant.name()|class_name }}({})".format(', '.join(field_parts))
|
||||
return "{{ e|type_name }}.{{ variant.name()|class_name }}({})".format(', '.join(field_parts))
|
||||
{%- else %}
|
||||
return "{{ type_name }}.{{ variant.name()|class_name }}"
|
||||
return "{{ e|type_name }}.{{ variant.name()|class_name }}"
|
||||
{%- endif %}
|
||||
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
|
||||
class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
class {{ e|ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@staticmethod
|
||||
def read(buf):
|
||||
variant = buf.readI32()
|
||||
{%- for variant in e.variants() %}
|
||||
if variant == {{ loop.index }}:
|
||||
return {{ type_name }}.{{ variant.name()|class_name }}(
|
||||
return {{ e|type_name }}.{{ variant.name()|class_name }}(
|
||||
{%- if e.is_flat() %}
|
||||
{{ Type::String.borrow()|read_fn }}(buf),
|
||||
{%- else %}
|
||||
@ -59,7 +59,7 @@ class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@staticmethod
|
||||
def write(value, buf):
|
||||
{%- for variant in e.variants() %}
|
||||
if isinstance(value, {{ type_name }}.{{ variant.name()|class_name }}):
|
||||
if isinstance(value, {{ e|type_name }}.{{ variant.name()|class_name }}):
|
||||
buf.writeI32({{ loop.index }})
|
||||
{%- for field in variant.fields() %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, buf)
|
||||
|
@ -1 +1 @@
|
||||
from {{ crate_name|fn_name }} import FfiConverterType{{ name }}
|
||||
from {{ self.crate_name|fn_name }} import FfiConverterType{{ name }}
|
||||
|
@ -1,7 +1,10 @@
|
||||
{%- let outer_type = self.outer() %}
|
||||
{%- let key_type = self.key() %}
|
||||
{%- let value_type = self.value() %}
|
||||
{%- let key_ffi_converter = key_type|ffi_converter_name %}
|
||||
{%- let value_ffi_converter = value_type|ffi_converter_name %}
|
||||
|
||||
class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
class {{ outer_type|ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@classmethod
|
||||
def write(cls, items, buf):
|
||||
buf.writeI32(len(items))
|
||||
|
@ -1,10 +1,11 @@
|
||||
{%- let obj = ci.get_object_definition(name).unwrap() %}
|
||||
{% import "macros.py" as py %}
|
||||
{%- let obj = self.inner() %}
|
||||
|
||||
class {{ type_name }}(object):
|
||||
class {{ obj|type_name }}(object):
|
||||
{%- match obj.primary_constructor() %}
|
||||
{%- when Some with (cons) %}
|
||||
def __init__(self, {% call py::arg_list_decl(cons) -%}):
|
||||
{%- call py::setup_args_extra_indent(cons) %}
|
||||
{%- call py::coerce_args_extra_indent(cons) %}
|
||||
self._pointer = {% call py::to_ffi_call(cons) %}
|
||||
{%- when None %}
|
||||
{%- endmatch %}
|
||||
@ -27,7 +28,7 @@ class {{ type_name }}(object):
|
||||
{% for cons in obj.alternate_constructors() -%}
|
||||
@classmethod
|
||||
def {{ cons.name()|fn_name }}(cls, {% call py::arg_list_decl(cons) %}):
|
||||
{%- call py::setup_args_extra_indent(cons) %}
|
||||
{%- call py::coerce_args_extra_indent(cons) %}
|
||||
# Call the (fallible) function before creating any half-baked object instances.
|
||||
pointer = {% call py::to_ffi_call(cons) %}
|
||||
return cls._make_instance_(pointer)
|
||||
@ -38,20 +39,20 @@ class {{ type_name }}(object):
|
||||
|
||||
{%- when Some with (return_type) -%}
|
||||
def {{ meth.name()|fn_name }}(self, {% call py::arg_list_decl(meth) %}):
|
||||
{%- call py::setup_args_extra_indent(meth) %}
|
||||
{%- call py::coerce_args_extra_indent(meth) %}
|
||||
return {{ return_type|lift_fn }}(
|
||||
{% call py::to_ffi_call_with_prefix("self._pointer", meth) %}
|
||||
)
|
||||
|
||||
{%- when None -%}
|
||||
def {{ meth.name()|fn_name }}(self, {% call py::arg_list_decl(meth) %}):
|
||||
{%- call py::setup_args_extra_indent(meth) %}
|
||||
{%- call py::coerce_args_extra_indent(meth) %}
|
||||
{% call py::to_ffi_call_with_prefix("self._pointer", meth) %}
|
||||
{% endmatch %}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
class {{ ffi_converter_name }}:
|
||||
class {{ obj|ffi_converter_name }}:
|
||||
@classmethod
|
||||
def read(cls, buf):
|
||||
ptr = buf.readU64()
|
||||
@ -61,13 +62,13 @@ class {{ ffi_converter_name }}:
|
||||
|
||||
@classmethod
|
||||
def write(cls, value, buf):
|
||||
if not isinstance(value, {{ type_name }}):
|
||||
raise TypeError("Expected {{ type_name }} instance, {} found".format(value.__class__.__name__))
|
||||
if not isinstance(value, {{ obj|type_name }}):
|
||||
raise TypeError("Expected {{ obj|type_name }} instance, {} found".format(value.__class__.__name__))
|
||||
buf.writeU64(cls.lower(value))
|
||||
|
||||
@staticmethod
|
||||
def lift(value):
|
||||
return {{ type_name }}._make_instance_(value)
|
||||
return {{ obj|type_name }}._make_instance_(value)
|
||||
|
||||
@staticmethod
|
||||
def lower(value):
|
||||
|
@ -1,6 +1,8 @@
|
||||
{%- let inner_type = self.inner() %}
|
||||
{%- let outer_type = self.outer() %}
|
||||
{%- let inner_ffi_converter = inner_type|ffi_converter_name %}
|
||||
|
||||
class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
class {{ outer_type|ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@classmethod
|
||||
def write(cls, value, buf):
|
||||
if value is None:
|
||||
|
@ -1,26 +1,13 @@
|
||||
{%- let rec = ci.get_record_definition(name).unwrap() %}
|
||||
class {{ type_name }}:
|
||||
|
||||
def __init__(self, {% for field in rec.fields() %}
|
||||
{{- field.name()|var_name }}
|
||||
{%- if field.default_value().is_some() %} = DEFAULT{% endif %}
|
||||
{%- if !loop.last %}, {% endif %}
|
||||
{%- endfor %}):
|
||||
{% import "macros.py" as py %}
|
||||
{%- let rec = self.inner() %}
|
||||
class {{ rec|type_name }}:
|
||||
def __init__(self, {% call py::field_list_decl(rec) %}):
|
||||
{%- for field in rec.fields() %}
|
||||
{%- let field_name = field.name()|var_name %}
|
||||
{%- match field.default_value() %}
|
||||
{%- when None %}
|
||||
self.{{ field_name }} = {{ field_name }}
|
||||
{%- when Some with(literal) %}
|
||||
if {{ field_name }} is DEFAULT:
|
||||
self.{{ field_name }} = {{ literal|literal_py(field) }}
|
||||
else:
|
||||
self.{{ field_name }} = {{ field_name }}
|
||||
{%- endmatch %}
|
||||
self.{{ field.name()|var_name }} = {{ field.name()|var_name }}
|
||||
{%- endfor %}
|
||||
|
||||
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 "{{ rec|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() %}
|
||||
@ -29,10 +16,10 @@ class {{ type_name }}:
|
||||
{%- endfor %}
|
||||
return True
|
||||
|
||||
class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
class {{ rec|ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@staticmethod
|
||||
def read(buf):
|
||||
return {{ type_name }}(
|
||||
return {{ rec|type_name }}(
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field.name()|var_name }}={{ field|read_fn }}(buf),
|
||||
{%- endfor %}
|
||||
@ -41,5 +28,5 @@ class {{ ffi_converter_name }}(FfiConverterRustBuffer):
|
||||
@staticmethod
|
||||
def write(value, buf):
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, buf)
|
||||
{{ field|write_fn }}(value.{{ field.name() }}, buf)
|
||||
{%- endfor %}
|
||||
|
@ -1,6 +1,8 @@
|
||||
{%- let inner_type = self.inner() %}
|
||||
{%- let outer_type = self.outer() %}
|
||||
{%- let inner_ffi_converter = inner_type|ffi_converter_name %}
|
||||
|
||||
class {{ ffi_converter_name}}(FfiConverterRustBuffer):
|
||||
class {{ outer_type|ffi_converter_name}}(FfiConverterRustBuffer):
|
||||
@classmethod
|
||||
def write(cls, value, buf):
|
||||
items = len(value)
|
||||
|
@ -1,13 +1,15 @@
|
||||
{% import "macros.py" as py %}
|
||||
{%- let func = self.inner() %}
|
||||
{%- match func.return_type() -%}
|
||||
{%- when Some with (return_type) %}
|
||||
|
||||
def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}):
|
||||
{%- call py::setup_args(func) %}
|
||||
{%- call py::coerce_args(func) %}
|
||||
return {{ return_type|lift_fn }}({% call py::to_ffi_call(func) %})
|
||||
|
||||
{% when None %}
|
||||
{% when None -%}
|
||||
|
||||
def {{ func.name()|fn_name }}({%- call py::arg_list_decl(func) -%}):
|
||||
{%- call py::setup_args(func) %}
|
||||
{%- call py::coerce_args(func) %}
|
||||
{% call py::to_ffi_call(func) %}
|
||||
{% endmatch %}
|
||||
|
@ -1,93 +0,0 @@
|
||||
{%- import "macros.py" as py %}
|
||||
|
||||
{%- for type_ in ci.iter_types() %}
|
||||
{%- let type_name = type_|type_name %}
|
||||
{%- let ffi_converter_name = type_|ffi_converter_name %}
|
||||
{%- let canonical_type_name = type_|canonical_name %}
|
||||
|
||||
{#
|
||||
# Map `Type` instances to an include statement for that type.
|
||||
#
|
||||
# There is a companion match in `PythonCodeOracle::create_code_type()` which performs a similar function for the
|
||||
# Rust code.
|
||||
#
|
||||
# - When adding additional types here, make sure to also add a match arm to that function.
|
||||
# - To keep things managable, let's try to limit ourselves to these 2 mega-matches
|
||||
#}
|
||||
{%- match type_ %}
|
||||
|
||||
{%- when Type::Boolean %}
|
||||
{%- include "BooleanHelper.py" %}
|
||||
|
||||
{%- when Type::Int8 %}
|
||||
{%- include "Int8Helper.py" %}
|
||||
|
||||
{%- when Type::Int16 %}
|
||||
{%- include "Int16Helper.py" %}
|
||||
|
||||
{%- when Type::Int32 %}
|
||||
{%- include "Int32Helper.py" %}
|
||||
|
||||
{%- when Type::Int64 %}
|
||||
{%- include "Int64Helper.py" %}
|
||||
|
||||
{%- when Type::UInt8 %}
|
||||
{%- include "UInt8Helper.py" %}
|
||||
|
||||
{%- when Type::UInt16 %}
|
||||
{%- include "UInt16Helper.py" %}
|
||||
|
||||
{%- when Type::UInt32 %}
|
||||
{%- include "UInt32Helper.py" %}
|
||||
|
||||
{%- when Type::UInt64 %}
|
||||
{%- include "UInt64Helper.py" %}
|
||||
|
||||
{%- when Type::Float32 %}
|
||||
{%- include "Float32Helper.py" %}
|
||||
|
||||
{%- when Type::Float64 %}
|
||||
{%- include "Float64Helper.py" %}
|
||||
|
||||
{%- when Type::String %}
|
||||
{%- include "StringHelper.py" %}
|
||||
|
||||
{%- when Type::Enum(name) %}
|
||||
{%- include "EnumTemplate.py" %}
|
||||
|
||||
{%- when Type::Error(name) %}
|
||||
{%- include "ErrorTemplate.py" %}
|
||||
|
||||
{%- when Type::Record(name) %}
|
||||
{%- include "RecordTemplate.py" %}
|
||||
|
||||
{%- when Type::Object(name) %}
|
||||
{%- include "ObjectTemplate.py" %}
|
||||
|
||||
{%- when Type::Timestamp %}
|
||||
{%- include "TimestampHelper.py" %}
|
||||
|
||||
{%- when Type::Duration %}
|
||||
{%- include "DurationHelper.py" %}
|
||||
|
||||
{%- when Type::Optional(inner_type) %}
|
||||
{%- include "OptionalTemplate.py" %}
|
||||
|
||||
{%- when Type::Sequence(inner_type) %}
|
||||
{%- include "SequenceTemplate.py" %}
|
||||
|
||||
{%- when Type::Map(key_type, value_type) %}
|
||||
{%- include "MapTemplate.py" %}
|
||||
|
||||
{%- when Type::CallbackInterface(id) %}
|
||||
{%- include "CallbackInterfaceTemplate.py" %}
|
||||
|
||||
{%- when Type::Custom { name, builtin } %}
|
||||
{%- include "CustomType.py" %}
|
||||
|
||||
{%- when Type::External { name, crate_name } %}
|
||||
{%- include "ExternalTemplate.py" %}
|
||||
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
{%- endfor %}
|
@ -32,7 +32,7 @@ rust_call(
|
||||
|
||||
{%- macro _arg_list_ffi_call(func) %}
|
||||
{%- for arg in func.arguments() %}
|
||||
{{ arg|lower_fn }}({{ arg.name()|var_name }})
|
||||
{{ arg|lower_fn }}({{ arg.name() }})
|
||||
{%- if !loop.last %},{% endif %}
|
||||
{%- endfor %}
|
||||
{%- endmacro -%}
|
||||
@ -46,13 +46,28 @@ rust_call(
|
||||
{%- for arg in func.arguments() -%}
|
||||
{{ arg.name()|var_name }}
|
||||
{%- match arg.default_value() %}
|
||||
{%- when Some with(literal) %} = DEFAULT
|
||||
{%- when Some with(literal) %} = {{ literal|literal_py(arg.type_().borrow()) }}
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
{%- if !loop.last %},{% endif -%}
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{#-
|
||||
// Field lists as used in Python declarations of Records.
|
||||
// Note the var_name.
|
||||
-#}
|
||||
{%- macro field_list_decl(item) %}
|
||||
{%- for field in item.fields() -%}
|
||||
{{ field.name()|var_name }}
|
||||
{%- match field.default_value() %}
|
||||
{%- when Some with(literal) %} = {{ literal|literal_py(field) }}
|
||||
{%- else %}
|
||||
{%- endmatch -%}
|
||||
{% if !loop.last %}, {% endif %}
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{#-
|
||||
// Arglist as used in the _UniFFILib function declations.
|
||||
// Note unfiltered name but ffi_type_name filters.
|
||||
@ -64,38 +79,14 @@ rust_call(
|
||||
ctypes.POINTER(RustCallStatus),
|
||||
{% endmacro -%}
|
||||
|
||||
{#
|
||||
# Setup function arguments by initializing default values and passing other
|
||||
# values through coerce.
|
||||
#}
|
||||
{%- macro setup_args(func) %}
|
||||
{%- macro coerce_args(func) %}
|
||||
{%- for arg in func.arguments() %}
|
||||
{%- match arg.default_value() %}
|
||||
{%- when None %}
|
||||
{{ arg.name()|var_name }} = {{ arg.name()|var_name|coerce_py(arg.type_().borrow()) -}}
|
||||
{%- when Some with(literal) %}
|
||||
if {{ arg.name()|var_name }} is DEFAULT:
|
||||
{{ arg.name()|var_name }} = {{ literal|literal_py(arg.type_().borrow()) }}
|
||||
else:
|
||||
{{ arg.name()|var_name }} = {{ arg.name()|var_name|coerce_py(arg.type_().borrow()) -}}
|
||||
{%- endmatch %}
|
||||
{{ arg.name() }} = {{ arg.name()|coerce_py(arg.type_().borrow()) -}}
|
||||
{% endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{#
|
||||
# Exactly the same thing as `setup_args()` but with an extra 4 spaces of
|
||||
# indent so that it works with object methods.
|
||||
#}
|
||||
{%- macro setup_args_extra_indent(func) %}
|
||||
{%- macro coerce_args_extra_indent(func) %}
|
||||
{%- for arg in func.arguments() %}
|
||||
{%- match arg.default_value() %}
|
||||
{%- when None %}
|
||||
{{ arg.name()|var_name }} = {{ arg.name()|var_name|coerce_py(arg.type_().borrow()) -}}
|
||||
{%- when Some with(literal) %}
|
||||
if {{ arg.name()|var_name }} is DEFAULT:
|
||||
{{ arg.name()|var_name }} = {{ literal|literal_py(arg.type_().borrow()) }}
|
||||
else:
|
||||
{{ arg.name()|var_name }} = {{ arg.name()|var_name|coerce_py(arg.type_().borrow()) -}}
|
||||
{%- endmatch %}
|
||||
{% endfor -%}
|
||||
{{ arg.name() }} = {{ arg.name()|coerce_py(arg.type_().borrow()) }}
|
||||
{%- endfor %}
|
||||
{%- endmacro -%}
|
||||
|
@ -28,9 +28,6 @@ import datetime
|
||||
import {{ module_name }}
|
||||
{%- endfor %}
|
||||
|
||||
# Used for default argument values
|
||||
DEFAULT = object()
|
||||
|
||||
{% include "RustBufferTemplate.py" %}
|
||||
{% include "Helpers.py" %}
|
||||
{% include "RustBufferHelper.py" %}
|
||||
@ -40,30 +37,28 @@ DEFAULT = object()
|
||||
{% include "NamespaceLibraryTemplate.py" %}
|
||||
|
||||
# Public interface members begin here.
|
||||
{{ type_helper_code }}
|
||||
|
||||
{%- for func in ci.function_definitions() %}
|
||||
{%- include "TopLevelFunctionTemplate.py" %}
|
||||
{% for code in self.declaration_code() %}
|
||||
{{ code }}
|
||||
{%- endfor %}
|
||||
|
||||
__all__ = [
|
||||
"InternalError",
|
||||
{%- for e in ci.enum_definitions() %}
|
||||
{%- for e in ci.iter_enum_definitions() %}
|
||||
"{{ e|type_name }}",
|
||||
{%- endfor %}
|
||||
{%- for record in ci.record_definitions() %}
|
||||
{%- for record in ci.iter_record_definitions() %}
|
||||
"{{ record|type_name }}",
|
||||
{%- endfor %}
|
||||
{%- for func in ci.function_definitions() %}
|
||||
{%- for func in ci.iter_function_definitions() %}
|
||||
"{{ func.name()|fn_name }}",
|
||||
{%- endfor %}
|
||||
{%- for obj in ci.object_definitions() %}
|
||||
{%- for obj in ci.iter_object_definitions() %}
|
||||
"{{ obj|type_name }}",
|
||||
{%- endfor %}
|
||||
{%- for e in ci.error_definitions() %}
|
||||
{%- for e in ci.iter_error_definitions() %}
|
||||
"{{ e|type_name }}",
|
||||
{%- endfor %}
|
||||
{%- for c in ci.callback_interface_definitions() %}
|
||||
{%- for c in ci.iter_callback_interface_definitions() %}
|
||||
"{{ c.name()|class_name }}",
|
||||
{%- endfor %}
|
||||
]
|
||||
|
@ -92,7 +92,7 @@ mod filters {
|
||||
FFIType::UInt64 => ":uint64".to_string(),
|
||||
FFIType::Float32 => ":float".to_string(),
|
||||
FFIType::Float64 => ":double".to_string(),
|
||||
FFIType::RustArcPtr(_) => ":pointer".to_string(),
|
||||
FFIType::RustArcPtr => ":pointer".to_string(),
|
||||
FFIType::RustBuffer => "RustBuffer.by_value".to_string(),
|
||||
FFIType::ForeignBytes => "ForeignBytes".to_string(),
|
||||
FFIType::ForeignCallback => unimplemented!("Callback interfaces are not implemented"),
|
||||
|
@ -2,13 +2,18 @@
|
||||
* 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 std::{env, io::Write, process::Command};
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsString,
|
||||
fs::File,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use fs_err::File;
|
||||
|
||||
pub mod gen_ruby;
|
||||
use camino::Utf8Path;
|
||||
pub use gen_ruby::{Config, RubyWrapper};
|
||||
|
||||
use super::super::interface::ComponentInterface;
|
||||
@ -18,18 +23,23 @@ use super::super::interface::ComponentInterface;
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
out_dir: &Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let rb_file = out_dir.join(format!("{}.rb", ci.namespace()));
|
||||
let mut f = File::create(&rb_file)?;
|
||||
let mut rb_file = PathBuf::from(out_dir);
|
||||
rb_file.push(format!("{}.rb", ci.namespace()));
|
||||
let mut f = File::create(&rb_file).context("Failed to create .rb file for bindings")?;
|
||||
write!(f, "{}", generate_ruby_bindings(config, ci)?)?;
|
||||
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("rubocop").arg("-A").arg(&rb_file).output() {
|
||||
if let Err(e) = Command::new("rubocop")
|
||||
.arg("-A")
|
||||
.arg(rb_file.to_str().unwrap())
|
||||
.output()
|
||||
{
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using rubocop: {:?}",
|
||||
rb_file.file_name().unwrap(),
|
||||
rb_file.file_name().unwrap().to_str().unwrap(),
|
||||
e
|
||||
)
|
||||
}
|
||||
@ -44,17 +54,16 @@ pub fn generate_ruby_bindings(config: &Config, ci: &ComponentInterface) -> Resul
|
||||
use askama::Template;
|
||||
RubyWrapper::new(config.clone(), ci)
|
||||
.render()
|
||||
.context("failed to render ruby bindings")
|
||||
.map_err(|_| anyhow::anyhow!("failed to render ruby bindings"))
|
||||
}
|
||||
|
||||
/// Execute the specifed ruby script, with environment based on the generated
|
||||
/// artifacts in the given output directory.
|
||||
pub fn run_script(out_dir: &Utf8Path, script_file: &Utf8Path) -> Result<()> {
|
||||
pub fn run_script(out_dir: &Path, script_file: &Path) -> Result<()> {
|
||||
let mut cmd = Command::new("ruby");
|
||||
// This helps ruby find the generated .rb wrapper for rust component.
|
||||
let rubypath = env::var_os("RUBYLIB").unwrap_or_default();
|
||||
let rubypath =
|
||||
env::join_paths(env::split_paths(&rubypath).chain(vec![out_dir.as_std_path().to_owned()]))?;
|
||||
let rubypath = env::var_os("RUBYLIB").unwrap_or_else(|| OsString::from(""));
|
||||
let rubypath = env::join_paths(env::split_paths(&rubypath).chain(vec![out_dir.to_path_buf()]))?;
|
||||
|
||||
cmd.env("RUBYLIB", rubypath);
|
||||
// We should now be able to execute the tests successfully.
|
||||
|
@ -19,7 +19,7 @@ end
|
||||
CALL_SUCCESS = 0
|
||||
CALL_ERROR = 1
|
||||
CALL_PANIC = 2
|
||||
{%- for e in ci.error_definitions() %}
|
||||
{%- for e in ci.iter_error_definitions() %}
|
||||
{% if e.is_flat() %}
|
||||
class {{ e.name()|class_name_rb }}
|
||||
{%- for variant in e.variants() %}
|
||||
@ -47,7 +47,7 @@ end
|
||||
|
||||
# Map error modules to the RustBuffer method name that reads them
|
||||
ERROR_MODULE_TO_READER_METHOD = {
|
||||
{%- for e in ci.error_definitions() %}
|
||||
{%- for e in ci.iter_error_definitions() %}
|
||||
{%- let typ=ci.get_type(e.name()).unwrap() %}
|
||||
{%- let canonical_type_name = typ.canonical_name().borrow()|class_name_rb %}
|
||||
{{ e.name()|class_name_rb }} => :read{{ canonical_type_name }},
|
||||
|
@ -7,7 +7,7 @@ def self.{{ func.name()|fn_name_rb }}({%- call rb::arg_list_decl(func) -%})
|
||||
return {{ "result"|lift_rb(return_type) }}
|
||||
end
|
||||
|
||||
{% when None %}
|
||||
{% when None -%}
|
||||
|
||||
def self.{{ func.name()|fn_name_rb }}({%- call rb::arg_list_decl(func) -%})
|
||||
{%- call rb::coerce_args(func) %}
|
||||
|
@ -27,19 +27,19 @@ module {{ ci.namespace()|class_name_rb }}
|
||||
|
||||
# Public interface members begin here.
|
||||
|
||||
{% for e in ci.enum_definitions() %}
|
||||
{% for e in ci.iter_enum_definitions() %}
|
||||
{% include "EnumTemplate.rb" %}
|
||||
{%- endfor -%}
|
||||
|
||||
{%- for rec in ci.record_definitions() %}
|
||||
{%- for rec in ci.iter_record_definitions() %}
|
||||
{% include "RecordTemplate.rb" %}
|
||||
{% endfor %}
|
||||
|
||||
{% for func in ci.function_definitions() %}
|
||||
{% for func in ci.iter_function_definitions() %}
|
||||
{% include "TopLevelFunctionTemplate.rb" %}
|
||||
{% endfor %}
|
||||
|
||||
{% for obj in ci.object_definitions() %}
|
||||
{% for obj in ci.iter_object_definitions() %}
|
||||
{% include "ObjectTemplate.rb" %}
|
||||
{% endfor %}
|
||||
end
|
||||
|
@ -2,7 +2,12 @@
|
||||
* 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::backend::{CodeOracle, CodeType};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{CallbackInterface, ComponentInterface};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
use super::Config;
|
||||
|
||||
pub struct CallbackInterfaceCodeType {
|
||||
id: String,
|
||||
@ -22,4 +27,74 @@ impl CodeType for CallbackInterfaceCodeType {
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!("CallbackInterface{}", self.type_label(oracle))
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
syntax = "swift",
|
||||
escape = "none",
|
||||
path = "CallbackInterfaceTemplate.swift"
|
||||
)]
|
||||
pub struct SwiftCallbackInterface {
|
||||
inner: CallbackInterface,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl SwiftCallbackInterface {
|
||||
pub fn new(inner: CallbackInterface, _ci: &ComponentInterface, config: Config) -> Self {
|
||||
Self { inner, config }
|
||||
}
|
||||
pub fn inner(&self) -> &CallbackInterface {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftCallbackInterface {
|
||||
fn initialization_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn imports(&self, _oracle: &dyn CodeOracle) -> Option<Vec<String>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
syntax = "swift",
|
||||
escape = "none",
|
||||
path = "CallbackInterfaceRuntime.swift"
|
||||
)]
|
||||
pub struct SwiftCallbackInterfaceRuntime {
|
||||
is_needed: bool,
|
||||
}
|
||||
|
||||
impl SwiftCallbackInterfaceRuntime {
|
||||
pub fn new(ci: &ComponentInterface) -> Self {
|
||||
Self {
|
||||
is_needed: !ci.iter_callback_interface_definitions().is_empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftCallbackInterfaceRuntime {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
if !self.is_needed {
|
||||
None
|
||||
} else {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,72 +3,103 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::backend::{CodeOracle, CodeType, Literal, TypeIdentifier};
|
||||
use askama::Template;
|
||||
use paste::paste;
|
||||
|
||||
pub struct OptionalCodeType {
|
||||
inner: TypeIdentifier,
|
||||
}
|
||||
// Used in template files.
|
||||
use super::filters;
|
||||
|
||||
impl OptionalCodeType {
|
||||
pub fn new(inner: TypeIdentifier) -> Self {
|
||||
Self { inner }
|
||||
fn render_literal(oracle: &dyn CodeOracle, literal: &Literal, inner: &TypeIdentifier) -> String {
|
||||
match literal {
|
||||
Literal::Null => "nil".into(),
|
||||
Literal::EmptySequence => "[]".into(),
|
||||
Literal::EmptyMap => "[:]".into(),
|
||||
|
||||
// For optionals
|
||||
_ => oracle.find(inner).literal(oracle, literal),
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeType for OptionalCodeType {
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!("{}?", oracle.find(&self.inner).type_label(oracle))
|
||||
}
|
||||
macro_rules! impl_code_type_for_compound {
|
||||
($T:ty, $type_label_pattern:literal, $canonical_name_pattern:literal, $template_file:literal) => {
|
||||
paste! {
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = $template_file)]
|
||||
pub struct $T {
|
||||
inner: TypeIdentifier,
|
||||
outer: TypeIdentifier,
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!("Option{}", oracle.find(&self.inner).canonical_name(oracle))
|
||||
}
|
||||
impl $T {
|
||||
pub fn new(inner: TypeIdentifier, outer: TypeIdentifier) -> Self {
|
||||
Self { inner, outer }
|
||||
}
|
||||
fn inner(&self) -> &TypeIdentifier {
|
||||
&self.inner
|
||||
}
|
||||
fn outer(&self) -> &TypeIdentifier {
|
||||
&self.outer
|
||||
}
|
||||
}
|
||||
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
match literal {
|
||||
Literal::Null => "nil".into(),
|
||||
_ => oracle.find(&self.inner).literal(oracle, literal),
|
||||
impl CodeType for $T {
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!($type_label_pattern, oracle.find(self.inner()).type_label(oracle))
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!($canonical_name_pattern, oracle.find(self.inner()).canonical_name(oracle))
|
||||
}
|
||||
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
render_literal(oracle, literal, self.inner())
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SequenceCodeType {
|
||||
inner: TypeIdentifier,
|
||||
}
|
||||
impl_code_type_for_compound!(
|
||||
OptionalCodeType,
|
||||
"{}?",
|
||||
"Option{}",
|
||||
"OptionalTemplate.swift"
|
||||
);
|
||||
|
||||
impl SequenceCodeType {
|
||||
pub fn new(inner: TypeIdentifier) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeType for SequenceCodeType {
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!("[{}]", oracle.find(&self.inner).type_label(oracle))
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"Sequence{}",
|
||||
oracle.find(&self.inner).canonical_name(oracle)
|
||||
)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
match literal {
|
||||
Literal::EmptySequence => "[]".into(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_code_type_for_compound!(
|
||||
SequenceCodeType,
|
||||
"[{}]",
|
||||
"Sequence{}",
|
||||
"SequenceTemplate.swift"
|
||||
);
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = "MapTemplate.swift")]
|
||||
pub struct MapCodeType {
|
||||
key: TypeIdentifier,
|
||||
value: TypeIdentifier,
|
||||
outer: TypeIdentifier,
|
||||
}
|
||||
|
||||
impl MapCodeType {
|
||||
pub fn new(key: TypeIdentifier, value: TypeIdentifier) -> Self {
|
||||
Self { key, value }
|
||||
pub fn new(key: TypeIdentifier, value: TypeIdentifier, outer: TypeIdentifier) -> Self {
|
||||
Self { key, value, outer }
|
||||
}
|
||||
|
||||
fn key(&self) -> &TypeIdentifier {
|
||||
&self.key
|
||||
}
|
||||
|
||||
fn value(&self) -> &TypeIdentifier {
|
||||
&self.value
|
||||
}
|
||||
|
||||
fn outer(&self) -> &TypeIdentifier {
|
||||
&self.outer
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,23 +107,24 @@ impl CodeType for MapCodeType {
|
||||
fn type_label(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"[{}: {}]",
|
||||
oracle.find(&self.key).type_label(oracle),
|
||||
oracle.find(&self.value).type_label(oracle)
|
||||
oracle.find(self.key()).type_label(oracle),
|
||||
oracle.find(self.value()).type_label(oracle)
|
||||
)
|
||||
}
|
||||
|
||||
fn canonical_name(&self, oracle: &dyn CodeOracle) -> String {
|
||||
format!(
|
||||
"Dictionary{}{}",
|
||||
oracle.find(&self.key).type_label(oracle),
|
||||
oracle.find(&self.value).type_label(oracle)
|
||||
oracle.find(self.key()).type_label(oracle),
|
||||
oracle.find(self.value()).type_label(oracle)
|
||||
)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
match literal {
|
||||
Literal::EmptyMap => "[:]".into(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
render_literal(oracle, literal, self.value())
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,11 @@
|
||||
* 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::backend::{CodeOracle, CodeType};
|
||||
use super::{filters, CustomTypeConfig};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{FFIType, Type};
|
||||
use askama::Template;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
pub struct CustomCodeType {
|
||||
name: String,
|
||||
@ -22,4 +26,51 @@ impl CodeType for CustomCodeType {
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
format!("Type{}", self.name)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String {
|
||||
// No such thing as a literal custom type
|
||||
unreachable!("Can't have a literal of a custom type");
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"// Helper code for {} is found in CustomType.py",
|
||||
self.name,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = "CustomType.swift")]
|
||||
pub struct SwiftCustomType {
|
||||
name: String,
|
||||
builtin: Type,
|
||||
config: Option<CustomTypeConfig>,
|
||||
}
|
||||
|
||||
impl SwiftCustomType {
|
||||
pub fn new(name: String, builtin: Type, config: Option<CustomTypeConfig>) -> Self {
|
||||
SwiftCustomType {
|
||||
name,
|
||||
builtin,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
fn builtin_ffi_type(&self) -> FFIType {
|
||||
FFIType::from(&self.builtin)
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftCustomType {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn imports(&self, _oracle: &dyn CodeOracle) -> Option<Vec<String>> {
|
||||
match &self.config {
|
||||
None => None,
|
||||
Some(custom_type_config) => custom_type_config.imports.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,11 @@
|
||||
* 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::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Enum};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
pub struct EnumCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -30,4 +33,39 @@ impl CodeType for EnumCodeType {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"// Helper code for {} enum is found in EnumTemplate.swift",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = "EnumTemplate.swift")]
|
||||
pub struct SwiftEnum {
|
||||
inner: Enum,
|
||||
contains_object_references: bool,
|
||||
}
|
||||
|
||||
impl SwiftEnum {
|
||||
pub fn new(inner: Enum, ci: &ComponentInterface) -> Self {
|
||||
Self {
|
||||
contains_object_references: ci.item_contains_object_references(&inner),
|
||||
inner,
|
||||
}
|
||||
}
|
||||
pub fn inner(&self) -> &Enum {
|
||||
&self.inner
|
||||
}
|
||||
pub fn contains_object_references(&self) -> bool {
|
||||
self.contains_object_references
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftEnum {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,12 @@
|
||||
* 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::backend::{CodeOracle, CodeType};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Error, Type};
|
||||
use askama::Template;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use super::filters;
|
||||
pub struct ErrorCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -22,4 +26,43 @@ impl CodeType for ErrorCodeType {
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
format!("Type{}", self.id)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"// Helper code for {} error is found in ErrorTemplate.swift",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = "ErrorTemplate.swift")]
|
||||
pub struct SwiftError {
|
||||
inner: Error,
|
||||
contains_object_references: bool,
|
||||
}
|
||||
|
||||
impl SwiftError {
|
||||
pub fn new(inner: Error, ci: &ComponentInterface) -> Self {
|
||||
Self {
|
||||
contains_object_references: ci.item_contains_object_references(&inner),
|
||||
inner,
|
||||
}
|
||||
}
|
||||
pub fn inner(&self) -> &Error {
|
||||
&self.inner
|
||||
}
|
||||
pub fn contains_object_references(&self) -> bool {
|
||||
self.contains_object_references
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftError {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
37
third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/function.rs
vendored
Normal file
37
third_party/rust/uniffi_bindgen/src/bindings/swift/gen_swift/function.rs
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
/* 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/. */
|
||||
|
||||
use crate::backend::{CodeDeclaration, CodeOracle};
|
||||
use crate::interface::{ComponentInterface, Function};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
use super::Config;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(
|
||||
syntax = "swift",
|
||||
escape = "none",
|
||||
path = "TopLevelFunctionTemplate.swift"
|
||||
)]
|
||||
pub struct SwiftFunction {
|
||||
inner: Function,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl SwiftFunction {
|
||||
pub fn new(inner: Function, _ci: &ComponentInterface, config: Config) -> Self {
|
||||
Self { inner, config }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Function {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftFunction {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
@ -2,28 +2,64 @@
|
||||
* 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::backend::{CodeOracle, CodeType};
|
||||
use crate::backend::{CodeOracle, CodeType, Literal};
|
||||
use askama::Template;
|
||||
use paste::paste;
|
||||
|
||||
pub struct TimestampCodeType;
|
||||
#[allow(unused_imports)]
|
||||
use super::filters;
|
||||
|
||||
impl CodeType for TimestampCodeType {
|
||||
fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
"Date".into()
|
||||
}
|
||||
macro_rules! impl_code_type_for_miscellany {
|
||||
($T:ty, $class_name:literal, $canonical_name:literal, $imports:expr, $template_file:literal) => {
|
||||
paste! {
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = $template_file)]
|
||||
pub struct $T;
|
||||
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
"Timestamp".into()
|
||||
}
|
||||
impl CodeType for $T {
|
||||
fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
$class_name.into()
|
||||
}
|
||||
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
$canonical_name.into()
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn imports(&self, _oracle: &dyn CodeOracle) -> Option<Vec<String>> {
|
||||
let imports: Vec<&str> = $imports;
|
||||
if (!imports.is_empty()) {
|
||||
Some(
|
||||
imports.into_iter().map(|s| s.into()).collect()
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub struct DurationCodeType;
|
||||
impl_code_type_for_miscellany!(
|
||||
TimestampCodeType,
|
||||
"Date",
|
||||
"Timestamp",
|
||||
vec![],
|
||||
"TimestampHelper.swift"
|
||||
);
|
||||
|
||||
impl CodeType for DurationCodeType {
|
||||
fn type_label(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
"TimeInterval".into()
|
||||
}
|
||||
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
"Duration".into()
|
||||
}
|
||||
}
|
||||
impl_code_type_for_miscellany!(
|
||||
DurationCodeType,
|
||||
"TimeInterval",
|
||||
"Duration",
|
||||
vec![],
|
||||
"DurationHelper.swift"
|
||||
);
|
||||
|
@ -3,16 +3,15 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{anyhow, Result};
|
||||
use askama::Template;
|
||||
use heck::{ToLowerCamelCase, ToUpperCamelCase};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Bindings;
|
||||
use crate::backend::{CodeOracle, CodeType, TemplateExpression, TypeIdentifier};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, TemplateExpression, TypeIdentifier};
|
||||
use crate::interface::*;
|
||||
use crate::MergeWith;
|
||||
|
||||
@ -21,6 +20,7 @@ mod compounds;
|
||||
mod custom;
|
||||
mod enum_;
|
||||
mod error;
|
||||
mod function;
|
||||
mod miscellany;
|
||||
mod object;
|
||||
mod primitives;
|
||||
@ -140,15 +140,15 @@ impl MergeWith for Config {
|
||||
pub fn generate_bindings(config: &Config, ci: &ComponentInterface) -> Result<Bindings> {
|
||||
let header = BridgingHeader::new(config, ci)
|
||||
.render()
|
||||
.context("failed to render Swift bridging header")?;
|
||||
let library = SwiftWrapper::new(config.clone(), ci)
|
||||
.map_err(|_| anyhow!("failed to render Swift bridging header"))?;
|
||||
let library = SwiftWrapper::new(SwiftCodeOracle, config.clone(), ci)
|
||||
.render()
|
||||
.context("failed to render Swift library")?;
|
||||
.map_err(|_| anyhow!("failed to render Swift library"))?;
|
||||
let modulemap = if config.generate_module_map() {
|
||||
Some(
|
||||
ModuleMap::new(config, ci)
|
||||
.render()
|
||||
.context("failed to render Swift modulemap")?,
|
||||
.map_err(|_| anyhow!("failed to render Swift modulemap"))?,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
@ -160,55 +160,6 @@ pub fn generate_bindings(config: &Config, ci: &ComponentInterface) -> Result<Bin
|
||||
})
|
||||
}
|
||||
|
||||
/// Renders Swift helper code for all types
|
||||
///
|
||||
/// This template is a bit different than others in that it stores internal state from the render
|
||||
/// process. Make sure to only call `render()` once.
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "kt", escape = "none", path = "Types.swift")]
|
||||
pub struct TypeRenderer<'a> {
|
||||
config: &'a Config,
|
||||
ci: &'a ComponentInterface,
|
||||
// Track included modules for the `include_once()` macro
|
||||
include_once_names: RefCell<HashSet<String>>,
|
||||
// Track imports added with the `add_import()` macro
|
||||
imports: RefCell<BTreeSet<String>>,
|
||||
}
|
||||
|
||||
impl<'a> TypeRenderer<'a> {
|
||||
fn new(config: &'a Config, ci: &'a ComponentInterface) -> Self {
|
||||
Self {
|
||||
config,
|
||||
ci,
|
||||
include_once_names: RefCell::new(HashSet::new()),
|
||||
imports: RefCell::new(BTreeSet::new()),
|
||||
}
|
||||
}
|
||||
|
||||
// The following methods are used by the `Types.kt` macros.
|
||||
|
||||
// Helper for the including a template, but only once.
|
||||
//
|
||||
// The first time this is called with a name it will return true, indicating that we should
|
||||
// include the template. Subsequent calls will return false.
|
||||
fn include_once_check(&self, name: &str) -> bool {
|
||||
self.include_once_names
|
||||
.borrow_mut()
|
||||
.insert(name.to_string())
|
||||
}
|
||||
|
||||
// Helper to add an import statement
|
||||
//
|
||||
// Call this inside your template to cause an import statement to be added at the top of the
|
||||
// file. Imports will be sorted and de-deuped.
|
||||
//
|
||||
// Returns an empty string so that it can be used inside an askama `{{ }}` block.
|
||||
fn add_import(&self, name: &str) -> &str {
|
||||
self.imports.borrow_mut().insert(name.to_owned());
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
/// Template for generating the `.h` file that defines the low-level C FFI.
|
||||
///
|
||||
/// This file defines only the low-level structs and functions that are exposed
|
||||
@ -254,32 +205,103 @@ impl<'config, 'ci> ModuleMap<'config, 'ci> {
|
||||
pub struct SwiftWrapper<'a> {
|
||||
config: Config,
|
||||
ci: &'a ComponentInterface,
|
||||
type_helper_code: String,
|
||||
type_imports: BTreeSet<String>,
|
||||
oracle: SwiftCodeOracle,
|
||||
}
|
||||
impl<'a> SwiftWrapper<'a> {
|
||||
pub fn new(config: Config, ci: &'a ComponentInterface) -> Self {
|
||||
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,
|
||||
type_helper_code,
|
||||
type_imports,
|
||||
}
|
||||
pub fn new(oracle: SwiftCodeOracle, config: Config, ci: &'a ComponentInterface) -> Self {
|
||||
Self { oracle, config, ci }
|
||||
}
|
||||
|
||||
pub fn members(&self) -> Vec<Box<dyn CodeDeclaration + 'a>> {
|
||||
let ci = self.ci;
|
||||
vec![
|
||||
Box::new(callback_interface::SwiftCallbackInterfaceRuntime::new(ci))
|
||||
as Box<dyn CodeDeclaration>,
|
||||
]
|
||||
.into_iter()
|
||||
.chain(
|
||||
ci.iter_enum_definitions().into_iter().map(|inner| {
|
||||
Box::new(enum_::SwiftEnum::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(ci.iter_function_definitions().into_iter().map(|inner| {
|
||||
Box::new(function::SwiftFunction::new(inner, ci, self.config.clone()))
|
||||
as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.chain(ci.iter_object_definitions().into_iter().map(|inner| {
|
||||
Box::new(object::SwiftObject::new(inner, ci, self.config.clone()))
|
||||
as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.chain(
|
||||
ci.iter_record_definitions().into_iter().map(|inner| {
|
||||
Box::new(record::SwiftRecord::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
ci.iter_error_definitions().into_iter().map(|inner| {
|
||||
Box::new(error::SwiftError::new(inner, ci)) as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(
|
||||
ci.iter_callback_interface_definitions()
|
||||
.into_iter()
|
||||
.map(|inner| {
|
||||
Box::new(callback_interface::SwiftCallbackInterface::new(
|
||||
inner,
|
||||
ci,
|
||||
self.config.clone(),
|
||||
)) as Box<dyn CodeDeclaration>
|
||||
}),
|
||||
)
|
||||
.chain(ci.iter_custom_types().into_iter().map(|(name, type_)| {
|
||||
let config = self.config.custom_types.get(&name).cloned();
|
||||
Box::new(custom::SwiftCustomType::new(name, type_, config)) as Box<dyn CodeDeclaration>
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn initialization_code(&self) -> Vec<String> {
|
||||
let oracle = &self.oracle;
|
||||
self.members()
|
||||
.into_iter()
|
||||
.filter_map(|member| member.initialization_code(oracle))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn declaration_code(&self) -> Vec<String> {
|
||||
let oracle = &self.oracle;
|
||||
self.members()
|
||||
.into_iter()
|
||||
.filter_map(|member| member.definition_code(oracle))
|
||||
.chain(
|
||||
self.ci
|
||||
.iter_types()
|
||||
.into_iter()
|
||||
.filter_map(|type_| oracle.find(&type_).helper_code(oracle)),
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn imports(&self) -> Vec<String> {
|
||||
self.type_imports.iter().cloned().collect()
|
||||
}
|
||||
|
||||
pub fn initialization_fns(&self) -> Vec<String> {
|
||||
self.ci
|
||||
.iter_types()
|
||||
let oracle = &self.oracle;
|
||||
let mut imports: Vec<String> = self
|
||||
.members()
|
||||
.into_iter()
|
||||
.filter_map(|t| t.initialization_fn(&SwiftCodeOracle))
|
||||
.collect()
|
||||
.filter_map(|member| member.imports(oracle))
|
||||
.flatten()
|
||||
.chain(
|
||||
self.ci
|
||||
.iter_types()
|
||||
.into_iter()
|
||||
.filter_map(|type_| oracle.find(&type_).imports(oracle))
|
||||
.flatten(),
|
||||
)
|
||||
.collect::<HashSet<String>>()
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
imports.sort();
|
||||
imports
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,14 +309,11 @@ impl<'a> SwiftWrapper<'a> {
|
||||
pub struct SwiftCodeOracle;
|
||||
|
||||
impl SwiftCodeOracle {
|
||||
// Map `Type` instances to a `Box<dyn CodeType>` for that type.
|
||||
//
|
||||
// There is a companion match in `templates/Types.swift` which performs a similar function for the
|
||||
// template code.
|
||||
//
|
||||
// - When adding additional types here, make sure to also add a match arm to the `Types.swift` template.
|
||||
// - To keep things managable, let's try to limit ourselves to these 2 mega-matches
|
||||
fn create_code_type(&self, type_: TypeIdentifier) -> Box<dyn CodeType> {
|
||||
// I really want access to the ComponentInterface here so I can look up the interface::{Enum, Record, Error, Object, etc}
|
||||
// However, there's some violence and gore I need to do to (temporarily) make the oracle usable from filters.
|
||||
|
||||
// Some refactor of the templates is needed to make progress here: I think most of the filter functions need to take an &dyn CodeOracle
|
||||
match type_ {
|
||||
Type::UInt8 => Box::new(primitives::UInt8CodeType),
|
||||
Type::Int8 => Box::new(primitives::Int8CodeType),
|
||||
@ -320,9 +339,22 @@ impl SwiftCodeOracle {
|
||||
Box::new(callback_interface::CallbackInterfaceCodeType::new(id))
|
||||
}
|
||||
|
||||
Type::Optional(inner) => Box::new(compounds::OptionalCodeType::new(*inner)),
|
||||
Type::Sequence(inner) => Box::new(compounds::SequenceCodeType::new(*inner)),
|
||||
Type::Map(key, value) => Box::new(compounds::MapCodeType::new(*key, *value)),
|
||||
Type::Optional(ref inner) => {
|
||||
let outer = type_.clone();
|
||||
let inner = *inner.to_owned();
|
||||
Box::new(compounds::OptionalCodeType::new(inner, outer))
|
||||
}
|
||||
Type::Sequence(ref inner) => {
|
||||
let outer = type_.clone();
|
||||
let inner = *inner.to_owned();
|
||||
Box::new(compounds::SequenceCodeType::new(inner, outer))
|
||||
}
|
||||
Type::Map(ref key, ref value) => {
|
||||
let outer = type_.clone();
|
||||
let key = *key.to_owned();
|
||||
let value = *value.to_owned();
|
||||
Box::new(compounds::MapCodeType::new(key, value, outer))
|
||||
}
|
||||
Type::External { .. } => panic!("no support for external types yet"),
|
||||
Type::Custom { name, .. } => Box::new(custom::CustomCodeType::new(name)),
|
||||
}
|
||||
@ -371,7 +403,7 @@ impl CodeOracle for SwiftCodeOracle {
|
||||
FFIType::UInt64 => "uint64_t".into(),
|
||||
FFIType::Float32 => "float".into(),
|
||||
FFIType::Float64 => "double".into(),
|
||||
FFIType::RustArcPtr(_) => "void*_Nonnull".into(),
|
||||
FFIType::RustArcPtr => "void*_Nonnull".into(),
|
||||
FFIType::RustBuffer => "RustBuffer".into(),
|
||||
FFIType::ForeignBytes => "ForeignBytes".into(),
|
||||
FFIType::ForeignCallback => "ForeignCallback _Nonnull".to_string(),
|
||||
@ -443,7 +475,7 @@ pub mod filters {
|
||||
FFIType::UInt64 => "UInt64".into(),
|
||||
FFIType::Float32 => "float".into(),
|
||||
FFIType::Float64 => "double".into(),
|
||||
FFIType::RustArcPtr(_) => "void*_Nonnull".into(),
|
||||
FFIType::RustArcPtr => "void*_Nonnull".into(),
|
||||
FFIType::RustBuffer => "RustBuffer".into(),
|
||||
FFIType::ForeignBytes => "ForeignBytes".into(),
|
||||
FFIType::ForeignCallback => "ForeignCallback _Nonnull".to_string(),
|
||||
|
@ -2,7 +2,12 @@
|
||||
* 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::backend::{CodeOracle, CodeType};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Object};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
use super::Config;
|
||||
|
||||
pub struct ObjectCodeType {
|
||||
id: String,
|
||||
@ -22,4 +27,42 @@ impl CodeType for ObjectCodeType {
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
format!("Type{}", self.id)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"// Helper code for {} class is found in ObjectTemplate.swift",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = "ObjectTemplate.swift")]
|
||||
pub struct SwiftObject {
|
||||
config: Config,
|
||||
inner: Object,
|
||||
}
|
||||
|
||||
impl SwiftObject {
|
||||
pub fn new(inner: Object, _ci: &ComponentInterface, config: Config) -> Self {
|
||||
Self { inner, config }
|
||||
}
|
||||
|
||||
pub fn inner(&self) -> &Object {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftObject {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
|
||||
fn imports(&self, _oracle: &dyn CodeOracle) -> Option<Vec<String>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,12 @@
|
||||
|
||||
use crate::backend::{CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{types::Type, Radix};
|
||||
use askama::Template;
|
||||
use paste::paste;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use super::filters;
|
||||
|
||||
fn render_literal(oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
fn typed_number(oracle: &dyn CodeOracle, type_: &Type, num_str: String) -> String {
|
||||
match type_ {
|
||||
@ -56,8 +60,10 @@ fn render_literal(oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
}
|
||||
|
||||
macro_rules! impl_code_type_for_primitive {
|
||||
($T:ty, $class_name:literal) => {
|
||||
($T:ty, $class_name:literal, $template_file:literal) => {
|
||||
paste! {
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = $template_file)]
|
||||
pub struct $T;
|
||||
|
||||
impl CodeType for $T {
|
||||
@ -68,20 +74,24 @@ macro_rules! impl_code_type_for_primitive {
|
||||
fn literal(&self, oracle: &dyn CodeOracle, literal: &Literal) -> String {
|
||||
render_literal(oracle, &literal)
|
||||
}
|
||||
|
||||
fn helper_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_code_type_for_primitive!(BooleanCodeType, "Bool");
|
||||
impl_code_type_for_primitive!(StringCodeType, "String");
|
||||
impl_code_type_for_primitive!(Int8CodeType, "Int8");
|
||||
impl_code_type_for_primitive!(Int16CodeType, "Int16");
|
||||
impl_code_type_for_primitive!(Int32CodeType, "Int32");
|
||||
impl_code_type_for_primitive!(Int64CodeType, "Int64");
|
||||
impl_code_type_for_primitive!(UInt8CodeType, "UInt8");
|
||||
impl_code_type_for_primitive!(UInt16CodeType, "UInt16");
|
||||
impl_code_type_for_primitive!(UInt32CodeType, "UInt32");
|
||||
impl_code_type_for_primitive!(UInt64CodeType, "UInt64");
|
||||
impl_code_type_for_primitive!(Float32CodeType, "Float");
|
||||
impl_code_type_for_primitive!(Float64CodeType, "Double");
|
||||
impl_code_type_for_primitive!(BooleanCodeType, "Bool", "BooleanHelper.swift");
|
||||
impl_code_type_for_primitive!(StringCodeType, "String", "StringHelper.swift");
|
||||
impl_code_type_for_primitive!(Int8CodeType, "Int8", "Int8Helper.swift");
|
||||
impl_code_type_for_primitive!(Int16CodeType, "Int16", "Int16Helper.swift");
|
||||
impl_code_type_for_primitive!(Int32CodeType, "Int32", "Int32Helper.swift");
|
||||
impl_code_type_for_primitive!(Int64CodeType, "Int64", "Int64Helper.swift");
|
||||
impl_code_type_for_primitive!(UInt8CodeType, "UInt8", "UInt8Helper.swift");
|
||||
impl_code_type_for_primitive!(UInt16CodeType, "UInt16", "UInt16Helper.swift");
|
||||
impl_code_type_for_primitive!(UInt32CodeType, "UInt32", "UInt32Helper.swift");
|
||||
impl_code_type_for_primitive!(UInt64CodeType, "UInt64", "UInt64Helper.swift");
|
||||
impl_code_type_for_primitive!(Float32CodeType, "Float", "Float32Helper.swift");
|
||||
impl_code_type_for_primitive!(Float64CodeType, "Double", "Float64Helper.swift");
|
||||
|
@ -2,8 +2,11 @@
|
||||
* 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::backend::{CodeOracle, CodeType};
|
||||
use crate::backend::{CodeDeclaration, CodeOracle, CodeType, Literal};
|
||||
use crate::interface::{ComponentInterface, Record};
|
||||
use askama::Template;
|
||||
|
||||
use super::filters;
|
||||
pub struct RecordCodeType {
|
||||
id: String,
|
||||
}
|
||||
@ -22,4 +25,43 @@ impl CodeType for RecordCodeType {
|
||||
fn canonical_name(&self, _oracle: &dyn CodeOracle) -> String {
|
||||
format!("Type{}", self.id)
|
||||
}
|
||||
|
||||
fn literal(&self, _oracle: &dyn CodeOracle, _literal: &Literal) -> String {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
fn helper_code(&self, oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(format!(
|
||||
"// Helper code for {} record is found in RecordTemplate.swift",
|
||||
self.type_label(oracle)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(syntax = "swift", escape = "none", path = "RecordTemplate.swift")]
|
||||
pub struct SwiftRecord {
|
||||
inner: Record,
|
||||
contains_object_references: bool,
|
||||
}
|
||||
|
||||
impl SwiftRecord {
|
||||
pub fn new(inner: Record, ci: &ComponentInterface) -> Self {
|
||||
Self {
|
||||
contains_object_references: ci.item_contains_object_references(&inner),
|
||||
inner,
|
||||
}
|
||||
}
|
||||
pub fn inner(&self) -> &Record {
|
||||
&self.inner
|
||||
}
|
||||
pub fn contains_object_references(&self) -> bool {
|
||||
self.contains_object_references
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeDeclaration for SwiftRecord {
|
||||
fn definition_code(&self, _oracle: &dyn CodeOracle) -> Option<String> {
|
||||
Some(self.render().unwrap())
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,14 @@
|
||||
//! * How to read from and write into a byte buffer.
|
||||
//!
|
||||
|
||||
use std::{ffi::OsString, io::Write, process::Command};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use camino::Utf8Path;
|
||||
use fs_err::File;
|
||||
use std::{
|
||||
ffi::OsString,
|
||||
fs::File,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
|
||||
pub mod gen_swift;
|
||||
pub use gen_swift::{generate_bindings, Config};
|
||||
@ -59,35 +62,43 @@ pub struct Bindings {
|
||||
pub fn write_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
out_dir: &Path,
|
||||
try_format_code: bool,
|
||||
) -> Result<()> {
|
||||
let out_path = PathBuf::from(out_dir);
|
||||
|
||||
let Bindings {
|
||||
header,
|
||||
library,
|
||||
modulemap,
|
||||
} = generate_bindings(config, ci)?;
|
||||
|
||||
let source_file = out_dir.join(format!("{}.swift", config.module_name()));
|
||||
let mut l = File::create(&source_file)?;
|
||||
let mut source_file = out_path.clone();
|
||||
source_file.push(format!("{}.swift", config.module_name()));
|
||||
let mut l = File::create(&source_file).context("Failed to create .swift file for bindings")?;
|
||||
write!(l, "{}", library)?;
|
||||
|
||||
let mut h = File::create(out_dir.join(config.header_filename()))?;
|
||||
let mut header_file = out_path.clone();
|
||||
header_file.push(config.header_filename());
|
||||
let mut h = File::create(&header_file).context("Failed to create .h file for bindings")?;
|
||||
write!(h, "{}", header)?;
|
||||
|
||||
if let Some(modulemap) = modulemap {
|
||||
let mut m = File::create(out_dir.join(config.modulemap_filename()))?;
|
||||
let mut modulemap_file = out_path;
|
||||
modulemap_file.push(config.modulemap_filename());
|
||||
let mut m = File::create(&modulemap_file)
|
||||
.context("Failed to create .modulemap file for bindings")?;
|
||||
write!(m, "{}", modulemap)?;
|
||||
}
|
||||
|
||||
if try_format_code {
|
||||
if let Err(e) = Command::new("swiftformat")
|
||||
.arg(source_file.as_str())
|
||||
.arg(source_file.to_str().unwrap())
|
||||
.output()
|
||||
{
|
||||
println!(
|
||||
"Warning: Unable to auto-format {} using swiftformat: {:?}",
|
||||
source_file.file_name().unwrap(),
|
||||
source_file.file_name().unwrap().to_str().unwrap(),
|
||||
e
|
||||
)
|
||||
}
|
||||
@ -104,21 +115,23 @@ pub fn write_bindings(
|
||||
/// test scripts need to be able to import the generated bindings, we have to compile them
|
||||
/// ahead of time before running the tests.
|
||||
///
|
||||
pub fn compile_bindings(
|
||||
config: &Config,
|
||||
ci: &ComponentInterface,
|
||||
out_dir: &Utf8Path,
|
||||
) -> Result<()> {
|
||||
pub fn compile_bindings(config: &Config, ci: &ComponentInterface, out_dir: &Path) -> Result<()> {
|
||||
let out_path = PathBuf::from(out_dir);
|
||||
|
||||
if !config.generate_module_map() {
|
||||
bail!("Cannot compile Swift bindings when `generate_module_map` is `false`")
|
||||
}
|
||||
let mut module_map_file = out_path.clone();
|
||||
module_map_file.push(config.modulemap_filename());
|
||||
|
||||
let module_map_file = out_dir.join(config.modulemap_filename());
|
||||
let mut module_map_file_option = OsString::from("-fmodule-map-file=");
|
||||
module_map_file_option.push(module_map_file.as_os_str());
|
||||
|
||||
let source_file = out_dir.join(format!("{}.swift", config.module_name()));
|
||||
let dylib_file = out_dir.join(format!("lib{}.dylib", config.module_name()));
|
||||
let mut source_file = out_path.clone();
|
||||
source_file.push(format!("{}.swift", config.module_name()));
|
||||
|
||||
let mut dylib_file = out_path.clone();
|
||||
dylib_file.push(format!("lib{}.dylib", config.module_name()));
|
||||
|
||||
// `-emit-library -o <path>` generates a `.dylib`, so that we can use the
|
||||
// Swift module from the REPL. Otherwise, we'll get "Couldn't lookup
|
||||
@ -130,13 +143,13 @@ pub fn compile_bindings(
|
||||
.arg(ci.namespace())
|
||||
.arg("-emit-library")
|
||||
.arg("-o")
|
||||
.arg(dylib_file)
|
||||
.arg(&dylib_file)
|
||||
.arg("-emit-module")
|
||||
.arg("-emit-module-path")
|
||||
.arg(out_dir)
|
||||
.arg(&out_path)
|
||||
.arg("-parse-as-library")
|
||||
.arg("-L")
|
||||
.arg(out_dir)
|
||||
.arg(&out_path)
|
||||
.arg(format!("-l{}", config.cdylib_name()))
|
||||
.arg("-Xcc")
|
||||
.arg(module_map_file_option)
|
||||
@ -157,7 +170,7 @@ pub fn compile_bindings(
|
||||
/// Swift modules in the given output directory. The modules must have been pre-compiled
|
||||
/// using the [`compile_bindings`] function.
|
||||
///
|
||||
pub fn run_script(out_dir: &Utf8Path, script_file: &Utf8Path) -> Result<()> {
|
||||
pub fn run_script(out_dir: &Path, script_file: &Path) -> Result<()> {
|
||||
let mut cmd = Command::new("swift");
|
||||
|
||||
// Find any module maps and/or dylibs in the target directory, and tell swift to use them.
|
||||
@ -166,7 +179,7 @@ pub fn run_script(out_dir: &Utf8Path, script_file: &Utf8Path) -> Result<()> {
|
||||
// this test function doesn't allow us to pass that name in to the call.
|
||||
|
||||
cmd.arg("-I").arg(out_dir);
|
||||
for entry in out_dir
|
||||
for entry in PathBuf::from(out_dir)
|
||||
.read_dir()
|
||||
.context("Failed to list target directory when running script")?
|
||||
{
|
||||
|
@ -1,6 +1,9 @@
|
||||
{%- let cbi = ci.get_callback_interface_definition(name).unwrap() %}
|
||||
{% import "macros.swift" as swift %}
|
||||
{%- let cbi = self.inner() %}
|
||||
{%- let type_name = cbi|type_name %}
|
||||
{%- let canonical_type_name = cbi|canonical_name %}
|
||||
{%- let ffi_converter = cbi|ffi_converter_name %}
|
||||
{%- let foreign_callback = format!("foreignCallback{}", canonical_type_name) %}
|
||||
{%- if self.include_once_check("CallbackInterfaceRuntime.swift") %}{%- include "CallbackInterfaceRuntime.swift" %}{%- endif %}
|
||||
|
||||
// Declaration and FfiConverters for {{ type_name }} Callback Interface
|
||||
|
||||
@ -56,10 +59,10 @@ fileprivate let {{ foreign_callback }} : ForeignCallback =
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
let cb = try! {{ ffi_converter_name }}.lift(handle)
|
||||
let cb = try! {{ ffi_converter }}.lift(handle)
|
||||
switch method {
|
||||
case IDX_CALLBACK_FREE:
|
||||
{{ ffi_converter_name }}.drop(handle: handle)
|
||||
{{ ffi_converter }}.drop(handle: handle)
|
||||
// No return value.
|
||||
// See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs`
|
||||
return 0
|
||||
@ -83,7 +86,7 @@ fileprivate let {{ foreign_callback }} : ForeignCallback =
|
||||
}
|
||||
|
||||
// FFIConverter protocol for callback interfaces
|
||||
fileprivate struct {{ ffi_converter_name }} {
|
||||
fileprivate struct {{ ffi_converter }} {
|
||||
// Initialize our callback method with the scaffolding code
|
||||
private static var callbackInitialized = false
|
||||
private static func initCallback() {
|
||||
@ -105,7 +108,7 @@ fileprivate struct {{ ffi_converter_name }} {
|
||||
private static var handleMap = ConcurrentHandleMap<{{ type_name }}>()
|
||||
}
|
||||
|
||||
extension {{ ffi_converter_name }} : FfiConverter {
|
||||
extension {{ ffi_converter }} : FfiConverter {
|
||||
typealias SwiftType = {{ type_name }}
|
||||
// We can use Handle as the FFIType because it's a typealias to UInt64
|
||||
typealias FfiType = Handle
|
||||
|
@ -1,5 +1,4 @@
|
||||
{%- let ffi_type_name=builtin.ffi_type().borrow()|ffi_type_name %}
|
||||
{%- match config.custom_types.get(name.as_str()) %}
|
||||
{%- match config %}
|
||||
{%- when None %}
|
||||
{#- No config, just forward all methods to our builtin type #}
|
||||
/**
|
||||
@ -22,14 +21,6 @@ public typealias {{ name }} = {{ concrete_type_name }}
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
{%- match config.imports %}
|
||||
{%- when Some(imports) %}
|
||||
{%- for import_name in imports %}
|
||||
{{ self.add_import(import_name) }}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
|
||||
fileprivate struct FfiConverterType{{ name }} {
|
||||
{#- Custom type config supplied, use it to convert the builtin type #}
|
||||
|
||||
@ -43,12 +34,12 @@ fileprivate struct FfiConverterType{{ name }} {
|
||||
return {{ builtin|write_fn }}(builtinValue, into: buf)
|
||||
}
|
||||
|
||||
static func lift(_ value: {{ ffi_type_name }}) throws -> {{ name }} {
|
||||
static func lift(_ value: {{ self.builtin_ffi_type().borrow()|type_ffi_lowered }}) throws -> {{ name }} {
|
||||
let builtinValue = try {{ builtin|lift_fn }}(value)
|
||||
return {{ config.into_custom.render("builtinValue") }}
|
||||
}
|
||||
|
||||
static func lower(_ value: {{ name }}) -> {{ ffi_type_name }} {
|
||||
static func lower(_ value: {{ name }}) -> {{ self.builtin_ffi_type().borrow()|type_ffi_lowered }} {
|
||||
let builtinValue = {{ config.from_custom.render("value") }}
|
||||
return {{ builtin|lower_fn }}(builtinValue)
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
|
||||
// Note that we don't yet support `indirect` for enums.
|
||||
// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion.
|
||||
{%- let e = ci.get_enum_definition(name).unwrap() %}
|
||||
public enum {{ type_name }} {
|
||||
{% import "macros.swift" as swift %}
|
||||
{%- let e = self.inner() %}
|
||||
public enum {{ e|type_name }} {
|
||||
{% for variant in e.variants() %}
|
||||
case {{ variant.name()|enum_variant_swift }}{% if variant.fields().len() > 0 %}({% call swift::field_list_decl(variant) %}){% endif -%}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ type_name }}
|
||||
fileprivate struct {{ e|ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ e|type_name }}
|
||||
|
||||
static func read(from buf: Reader) throws -> {{ type_name }} {
|
||||
static func read(from buf: Reader) throws -> {{ e|type_name }} {
|
||||
let variant: Int32 = try buf.readInt()
|
||||
switch variant {
|
||||
{% for variant in e.variants() %}
|
||||
@ -25,7 +27,7 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
static func write(_ value: {{ type_name }}, into buf: Writer) {
|
||||
static func write(_ value: {{ e|type_name }}, into buf: Writer) {
|
||||
switch value {
|
||||
{% for variant in e.variants() %}
|
||||
{% if variant.has_fields() %}
|
||||
@ -43,6 +45,6 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
{% if !contains_object_references %}
|
||||
extension {{ type_name }}: Equatable, Hashable {}
|
||||
{% if ! self.contains_object_references() %}
|
||||
extension {{ e|type_name }}: Equatable, Hashable {}
|
||||
{% endif %}
|
||||
|
@ -1,5 +1,6 @@
|
||||
{%- let e = ci.get_error_definition(name).unwrap() %}
|
||||
public enum {{ type_name }} {
|
||||
{% import "macros.swift" as swift %}
|
||||
{%- let e = self.inner() %}
|
||||
public enum {{ e|type_name }} {
|
||||
|
||||
{% if e.is_flat() %}
|
||||
{% for variant in e.variants() %}
|
||||
@ -15,10 +16,10 @@ public enum {{ type_name }} {
|
||||
{%- endif %}
|
||||
}
|
||||
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ type_name }}
|
||||
fileprivate struct {{ e|ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ e|type_name }}
|
||||
|
||||
static func read(from buf: Reader) throws -> {{ type_name }} {
|
||||
static func read(from buf: Reader) throws -> {{ e|type_name }} {
|
||||
let variant: Int32 = try buf.readInt()
|
||||
switch variant {
|
||||
|
||||
@ -46,7 +47,7 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
static func write(_ value: {{ type_name }}, into buf: Writer) {
|
||||
static func write(_ value: {{ e|type_name }}, into buf: Writer) {
|
||||
switch value {
|
||||
|
||||
{% if e.is_flat() %}
|
||||
@ -77,7 +78,7 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
{% if !contains_object_references %}
|
||||
extension {{ type_name }}: Equatable, Hashable {}
|
||||
{% if !self.contains_object_references() %}
|
||||
extension {{ e|type_name }}: Equatable, Hashable {}
|
||||
{% endif %}
|
||||
extension {{ type_name }}: Error { }
|
||||
extension {{ e|type_name }}: Error { }
|
||||
|
@ -1,5 +1,11 @@
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
fileprivate static func write(_ value: {{ type_name }}, into buf: Writer) {
|
||||
{%- import "macros.swift" as swift -%}
|
||||
{%- let outer_type = self.outer() %}
|
||||
{%- let dict_type = outer_type|type_name %}
|
||||
{%- let key_type = self.key() %}
|
||||
{%- let value_type = self.value() %}
|
||||
|
||||
fileprivate struct {{ outer_type|ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
fileprivate static func write(_ value: {{ dict_type }}, into buf: Writer) {
|
||||
let len = Int32(value.count)
|
||||
buf.writeInt(len)
|
||||
for (key, value) in value {
|
||||
@ -8,9 +14,9 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate static func read(from buf: Reader) throws -> {{ type_name }} {
|
||||
fileprivate static func read(from buf: Reader) throws -> {{ dict_type }} {
|
||||
let len: Int32 = try buf.readInt()
|
||||
var dict = {{ type_name }}()
|
||||
var dict = {{ dict_type }}()
|
||||
dict.reserveCapacity(Int(len))
|
||||
for _ in 0..<len {
|
||||
let key = try {{ key_type|read_fn }}(from: buf)
|
||||
|
@ -1,4 +1,5 @@
|
||||
{%- let obj = ci.get_object_definition(name).unwrap() %}
|
||||
{% import "macros.swift" as swift %}
|
||||
{%- let obj = self.inner() %}
|
||||
public protocol {{ obj.name() }}Protocol {
|
||||
{% for meth in obj.methods() -%}
|
||||
func {{ meth.name()|fn_name }}({% call swift::arg_list_protocol(meth) %}) {% call swift::throws(meth) -%}
|
||||
@ -9,7 +10,7 @@ public protocol {{ obj.name() }}Protocol {
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
public class {{ type_name }}: {{ obj.name() }}Protocol {
|
||||
public class {{ obj|type_name }}: {{ obj.name() }}Protocol {
|
||||
fileprivate let pointer: UnsafeMutableRawPointer
|
||||
|
||||
// TODO: We'd like this to be `private` but for Swifty reasons,
|
||||
@ -32,8 +33,8 @@ public class {{ type_name }}: {{ obj.name() }}Protocol {
|
||||
}
|
||||
|
||||
{% for cons in obj.alternate_constructors() %}
|
||||
public static func {{ cons.name()|fn_name }}({% call swift::arg_list_decl(cons) %}) {% call swift::throws(cons) %} -> {{ type_name }} {
|
||||
return {{ type_name }}(unsafeFromRawPointer: {% call swift::to_ffi_call(cons) %})
|
||||
public static func {{ cons.name()|fn_name }}({% call swift::arg_list_decl(cons) %}) {% call swift::throws(cons) %} -> {{ obj|type_name }} {
|
||||
return {{ obj|type_name }}(unsafeFromRawPointer: {% call swift::to_ffi_call(cons) %})
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
@ -57,11 +58,11 @@ public class {{ type_name }}: {{ obj.name() }}Protocol {
|
||||
}
|
||||
|
||||
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverter {
|
||||
fileprivate struct {{ obj|ffi_converter_name }}: FfiConverter {
|
||||
typealias FfiType = UnsafeMutableRawPointer
|
||||
typealias SwiftType = {{ type_name }}
|
||||
typealias SwiftType = {{ obj|type_name }}
|
||||
|
||||
static func read(from buf: Reader) throws -> {{ type_name }} {
|
||||
static func read(from buf: Reader) throws -> {{ obj|type_name }} {
|
||||
let v: UInt64 = try buf.readInt()
|
||||
// The Rust code won't compile if a pointer won't fit in a UInt64.
|
||||
// We have to go via `UInt` because that's the thing that's the size of a pointer.
|
||||
@ -72,17 +73,17 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverter {
|
||||
return try lift(ptr!)
|
||||
}
|
||||
|
||||
static func write(_ value: {{ type_name }}, into buf: Writer) {
|
||||
static func write(_ value: {{ obj|type_name }}, into buf: Writer) {
|
||||
// This fiddling is because `Int` is the thing that's the same size as a pointer.
|
||||
// The Rust code won't compile if a pointer won't fit in a `UInt64`.
|
||||
buf.writeInt(UInt64(bitPattern: Int64(Int(bitPattern: lower(value)))))
|
||||
}
|
||||
|
||||
static func lift(_ pointer: UnsafeMutableRawPointer) throws -> {{ type_name }} {
|
||||
return {{ type_name}}(unsafeFromRawPointer: pointer)
|
||||
static func lift(_ pointer: UnsafeMutableRawPointer) throws -> {{ obj|type_name }} {
|
||||
return {{ obj|type_name}}(unsafeFromRawPointer: pointer)
|
||||
}
|
||||
|
||||
static func lower(_ value: {{ type_name }}) -> UnsafeMutableRawPointer {
|
||||
static func lower(_ value: {{ obj|type_name }}) -> UnsafeMutableRawPointer {
|
||||
return value.pointer
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ type_name }}
|
||||
{%- let inner_type = self.inner() %}
|
||||
{%- let outer_type = self.outer() %}
|
||||
fileprivate struct {{ outer_type|ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ outer_type|type_name }}
|
||||
|
||||
static func write(_ value: SwiftType, into buf: Writer) {
|
||||
guard let value = value else {
|
||||
|
@ -1,5 +1,6 @@
|
||||
{%- let rec = ci.get_record_definition(name).unwrap() %}
|
||||
public struct {{ type_name }} {
|
||||
{% import "macros.swift" as swift %}
|
||||
{%- let rec = self.inner() %}
|
||||
public struct {{ rec|type_name }} {
|
||||
{%- for field in rec.fields() %}
|
||||
public var {{ field.name()|var_name }}: {{ field|type_name }}
|
||||
{%- endfor %}
|
||||
@ -13,9 +14,9 @@ public struct {{ type_name }} {
|
||||
}
|
||||
}
|
||||
|
||||
{% if !contains_object_references %}
|
||||
extension {{ type_name }}: Equatable, Hashable {
|
||||
public static func ==(lhs: {{ type_name }}, rhs: {{ type_name }}) -> Bool {
|
||||
{% if ! self.contains_object_references() %}
|
||||
extension {{ rec|type_name }}: Equatable, Hashable {
|
||||
public static func ==(lhs: {{ rec|type_name }}, rhs: {{ rec|type_name }}) -> Bool {
|
||||
{%- for field in rec.fields() %}
|
||||
if lhs.{{ field.name()|var_name }} != rhs.{{ field.name()|var_name }} {
|
||||
return false
|
||||
@ -32,9 +33,9 @@ extension {{ type_name }}: Equatable, Hashable {
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
fileprivate static func read(from buf: Reader) throws -> {{ type_name }} {
|
||||
return try {{ type_name }}(
|
||||
fileprivate struct {{ rec|ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
fileprivate static func read(from buf: Reader) throws -> {{ rec|type_name }} {
|
||||
return try {{ rec|type_name }}(
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field.name()|var_name }}: {{ field|read_fn }}(from: buf)
|
||||
{%- if !loop.last %}, {% endif %}
|
||||
@ -42,7 +43,7 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
)
|
||||
}
|
||||
|
||||
fileprivate static func write(_ value: {{ type_name }}, into buf: Writer) {
|
||||
fileprivate static func write(_ value: {{ rec|type_name }}, into buf: Writer) {
|
||||
{%- for field in rec.fields() %}
|
||||
{{ field|write_fn }}(value.{{ field.name()|var_name }}, into: buf)
|
||||
{%- endfor %}
|
||||
|
@ -1,7 +1,10 @@
|
||||
fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ type_name }}
|
||||
{%- import "macros.swift" as swift -%}
|
||||
{%- let inner_type = self.inner() %}
|
||||
{%- let outer_type = self.outer() %}
|
||||
fileprivate struct {{ outer_type|ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
typealias SwiftType = {{ outer_type|type_name }}
|
||||
|
||||
static func write(_ value: {{ type_name }}, into buf: Writer) {
|
||||
static func write(_ value: {{ outer_type|type_name }}, into buf: Writer) {
|
||||
let len = Int32(value.count)
|
||||
buf.writeInt(len)
|
||||
for item in value {
|
||||
@ -9,9 +12,9 @@ fileprivate struct {{ ffi_converter_name }}: FfiConverterRustBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
static func read(from buf: Reader) throws -> {{ type_name }} {
|
||||
static func read(from buf: Reader) throws -> {{ outer_type|type_name }} {
|
||||
let len: Int32 = try buf.readInt()
|
||||
var seq = {{ type_name }}()
|
||||
var seq = {{ outer_type|type_name }}()
|
||||
seq.reserveCapacity(Int(len))
|
||||
for _ in 0 ..< len {
|
||||
seq.append(try {{ inner_type|read_fn }}(from: buf))
|
||||
|
@ -1,3 +1,5 @@
|
||||
{% import "macros.swift" as swift %}
|
||||
{%- let func = self.inner() %}
|
||||
{%- match func.return_type() -%}
|
||||
{%- when Some with (return_type) %}
|
||||
|
||||
@ -7,7 +9,7 @@ public func {{ func.name()|fn_name }}({%- call swift::arg_list_decl(func) -%}) {
|
||||
)
|
||||
}
|
||||
|
||||
{% when None %}
|
||||
{% when None -%}
|
||||
|
||||
public func {{ func.name()|fn_name }}({% call swift::arg_list_decl(func) %}) {% call swift::throws(func) %} {
|
||||
{% call swift::to_ffi_call(func) %}
|
||||
|
@ -1,91 +0,0 @@
|
||||
{%- import "macros.swift" as swift %}
|
||||
{%- for type_ in ci.iter_types() %}
|
||||
{%- let type_name = type_|type_name %}
|
||||
{%- let ffi_converter_name = type_|ffi_converter_name %}
|
||||
{%- let canonical_type_name = type_|canonical_name %}
|
||||
{%- let contains_object_references = ci.item_contains_object_references(type_) %}
|
||||
|
||||
{#
|
||||
# Map `Type` instances to an include statement for that type.
|
||||
#
|
||||
# There is a companion match in `KotlinCodeOracle::create_code_type()` which performs a similar function for the
|
||||
# Rust code.
|
||||
#
|
||||
# - When adding additional types here, make sure to also add a match arm to that function.
|
||||
# - To keep things managable, let's try to limit ourselves to these 2 mega-matches
|
||||
#}
|
||||
{%- match type_ %}
|
||||
|
||||
{%- when Type::Boolean %}
|
||||
{%- include "BooleanHelper.swift" %}
|
||||
|
||||
{%- when Type::String %}
|
||||
{%- include "StringHelper.swift" %}
|
||||
|
||||
{%- when Type::Int8 %}
|
||||
{%- include "Int8Helper.swift" %}
|
||||
|
||||
{%- when Type::Int16 %}
|
||||
{%- include "Int16Helper.swift" %}
|
||||
|
||||
{%- when Type::Int32 %}
|
||||
{%- include "Int32Helper.swift" %}
|
||||
|
||||
{%- when Type::Int64 %}
|
||||
{%- include "Int64Helper.swift" %}
|
||||
|
||||
{%- when Type::UInt8 %}
|
||||
{%- include "UInt8Helper.swift" %}
|
||||
|
||||
{%- when Type::UInt16 %}
|
||||
{%- include "UInt16Helper.swift" %}
|
||||
|
||||
{%- when Type::UInt32 %}
|
||||
{%- include "UInt32Helper.swift" %}
|
||||
|
||||
{%- when Type::UInt64 %}
|
||||
{%- include "UInt64Helper.swift" %}
|
||||
|
||||
{%- when Type::Float32 %}
|
||||
{%- include "Float32Helper.swift" %}
|
||||
|
||||
{%- when Type::Float64 %}
|
||||
{%- include "Float64Helper.swift" %}
|
||||
|
||||
{%- when Type::Timestamp %}
|
||||
{%- include "TimestampHelper.swift" %}
|
||||
|
||||
{%- when Type::Duration %}
|
||||
{%- include "DurationHelper.swift" %}
|
||||
|
||||
{%- when Type::CallbackInterface(name) %}
|
||||
{%- include "CallbackInterfaceTemplate.swift" %}
|
||||
|
||||
{%- when Type::Custom { name, builtin } %}
|
||||
{%- include "CustomType.swift" %}
|
||||
|
||||
{%- when Type::Enum(name) %}
|
||||
{%- include "EnumTemplate.swift" %}
|
||||
|
||||
{%- when Type::Error(name) %}
|
||||
{%- include "ErrorTemplate.swift" %}
|
||||
|
||||
{%- when Type::Object(name) %}
|
||||
{%- include "ObjectTemplate.swift" %}
|
||||
|
||||
{%- when Type::Record(name) %}
|
||||
{%- include "RecordTemplate.swift" %}
|
||||
|
||||
{%- when Type::Optional(inner_type) %}
|
||||
{%- include "OptionalTemplate.swift" %}
|
||||
|
||||
{%- when Type::Sequence(inner_type) %}
|
||||
{%- include "SequenceTemplate.swift" %}
|
||||
|
||||
{%- when Type::Map(key_type, value_type) %}
|
||||
{%- include "MapTemplate.swift" %}
|
||||
|
||||
|
||||
{%- else %}
|
||||
{%- endmatch %}
|
||||
{%- endfor %}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user