diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 39dab03..b9a931c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,7 +27,7 @@ jobs: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: actions-rs/toolchain@b2417cde72dcf67f306c0ae8e0828a81bf0b189f with: - toolchain: 1.64.0 + toolchain: "1.72" default: true - uses: actions-rs/cargo@ae10961054e4aa8b4aa7dffede299aaf087aa33b with: diff --git a/Cargo.lock b/Cargo.lock index 142381f..922650d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,54 @@ dependencies = [ "memchr", ] +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.71" @@ -30,24 +78,28 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "askama" -version = "0.11.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" +checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" dependencies = [ "askama_derive", "askama_escape", - "askama_shared", ] [[package]] name = "askama_derive" -version = "0.11.2" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" +checksum = "9a0fc7dcf8bd4ead96b1d36b41df47c14beedf7b0301fc543d8f2384e66a2ec0" dependencies = [ - "askama_shared", + "askama_parser", + "basic-toml", + "mime", + "mime_guess", "proc-macro2", - "syn 1.0.109", + "quote", + "serde", + "syn", ] [[package]] @@ -57,39 +109,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" [[package]] -name = "askama_shared" -version = "0.12.2" +name = "askama_parser" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0" +checksum = "c268a96e01a4c47c8c5c2472aaa570707e006a875ea63e819f75474ceedaf7b4" dependencies = [ - "askama_escape", - "mime", - "mime_guess", "nom", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", - "toml", ] [[package]] -name = "atty" -version = "0.2.14" +name = "basic-toml" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "serde", ] -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - [[package]] name = "bincode" version = "1.3.3" @@ -99,12 +135,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bytes" version = "1.4.0" @@ -143,6 +173,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -151,42 +190,49 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "3.2.25" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ - "atty", - "bitflags", + "clap_builder", "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +dependencies = [ + "anstream", + "anstyle", "clap_lex", - "indexmap", - "once_cell", "strsim", - "termcolor", - "textwrap", ] [[package]] name = "clap_derive" -version = "3.2.25" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "compatibility-test" @@ -194,7 +240,7 @@ version = "0.22.0" dependencies = [ "once_cell", "thiserror", - "uniffi 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uniffi 0.25.1", ] [[package]] @@ -203,6 +249,19 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -246,31 +305,18 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - [[package]] name = "itoa" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.147" @@ -283,6 +329,29 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "pin-utils", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.5.0" @@ -321,6 +390,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -328,10 +407,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] -name = "os_str_bytes" -version = "6.5.1" +name = "oneshot" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" +dependencies = [ + "loom", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "paste" @@ -340,34 +428,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" [[package]] -name = "plain" -version = "0.2.3" +name = "pin-project-lite" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "pin-utils" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "proc-macro2" @@ -395,21 +471,48 @@ checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scroll" version = "0.11.0" @@ -427,7 +530,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn", ] [[package]] @@ -456,7 +559,7 @@ checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn", ] [[package]] @@ -470,12 +573,27 @@ dependencies = [ "serde", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "siphasher" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +[[package]] +name = "smallvec" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + [[package]] name = "smawk" version = "0.3.1" @@ -494,17 +612,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.23" @@ -516,15 +623,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "textwrap" version = "0.16.0" @@ -553,7 +651,17 @@ checksum = "d14928354b01c4d6a4f0e549069adef399a284e7995c7ccca94e8a07a5346c59" dependencies = [ "proc-macro2", "quote", - "syn 2.0.23", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] @@ -565,6 +673,67 @@ dependencies = [ "serde", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicase" version = "2.6.0" @@ -598,46 +767,46 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "uniffi" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71cc01459bc34cfe43fabf32b39f1228709bc6db1b3a664a92940af3d062376" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "anyhow", - "uniffi_build 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uniffi_core 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uniffi_macros 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "camino", + "clap", + "uniffi_bindgen 0.25.0", + "uniffi_core 0.25.0", + "uniffi_macros 0.25.0", ] [[package]] name = "uniffi" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba05e3479d824a75256ab5fd7d9cd957f3f19a14e2517546a1ca072a3443bf8" dependencies = [ "anyhow", - "camino", - "clap", - "uniffi_bindgen 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", - "uniffi_core 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", - "uniffi_macros 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", + "uniffi_build 0.25.1", + "uniffi_core 0.25.1", + "uniffi_macros 0.25.1", ] [[package]] name = "uniffi-bindgen" -version = "0.23.0" +version = "0.25.0" dependencies = [ - "uniffi 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", + "uniffi 0.25.0", ] [[package]] name = "uniffi_bindgen" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbbba5103051c18f10b22f80a74439ddf7100273f217a547005d2735b2498994" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "anyhow", "askama", - "bincode", "camino", + "cargo_metadata", + "clap", "fs-err", "glob", "goblin", @@ -645,22 +814,23 @@ dependencies = [ "once_cell", "paste", "serde", - "serde_json", + "textwrap", "toml", - "uniffi_meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uniffi_testing 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "weedle2 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uniffi_meta 0.25.0", + "uniffi_testing 0.25.0", + "uniffi_udl 0.25.0", ] [[package]] name = "uniffi_bindgen" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0ab1d77f56b0a0f8e9649975a37cee762e97d20630935c3b47779b1d77efd7" dependencies = [ "anyhow", "askama", - "bincode", "camino", + "cargo_metadata", "fs-err", "glob", "goblin", @@ -668,90 +838,87 @@ dependencies = [ "once_cell", "paste", "serde", - "serde_json", - "textwrap", "toml", - "uniffi_meta 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", - "uniffi_testing 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", - "weedle2 4.0.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", + "uniffi_meta 0.25.1", + "uniffi_testing 0.25.1", + "uniffi_udl 0.25.1", ] [[package]] name = "uniffi_build" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee1a28368ff3d83717e3d3e2e15a66269c43488c3f036914131bb68892f29fb" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "anyhow", "camino", - "uniffi_bindgen 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uniffi_bindgen 0.25.0", ] [[package]] name = "uniffi_build" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170621ba52f1917a6f2f78efb6a023b917ebc95c0194d533b3e1ee71a7e1f12f" dependencies = [ "anyhow", "camino", - "uniffi_bindgen 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", + "uniffi_bindgen 0.25.1", ] [[package]] name = "uniffi_checksum_derive" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03de61393a42b4ad4984a3763c0600594ac3e57e5aaa1d05cede933958987c03" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "uniffi_checksum_derive" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a189b3bbfdae832dd294befc8c871629833fbe283d89796960768b3e8d5684c8" dependencies = [ "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "uniffi_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2b4852d638d74ca2d70e450475efb6d91fe6d54a7cd8d6bd80ad2ee6cd7daa" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "anyhow", "bytes", "camino", - "cargo_metadata", "log", "once_cell", + "oneshot", "paste", "static_assertions", ] [[package]] name = "uniffi_core" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcd51aa85d355ce985c6e0c95b1340516b0fe565fb357845143aa29d02c8dda0" dependencies = [ "anyhow", "bytes", "camino", - "cargo_metadata", "log", "once_cell", + "oneshot", "paste", "static_assertions", ] [[package]] name = "uniffi_macros" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa03394de21e759e0022f1ea8d992d2e39290d735b9ed52b1f74b20a684f794e" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "bincode", "camino", @@ -760,16 +927,17 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 1.0.109", + "syn", "toml", - "uniffi_build 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uniffi_meta 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uniffi_build 0.25.0", + "uniffi_meta 0.25.0", ] [[package]] name = "uniffi_macros" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cb09cd1e2ede4a35186d1a6491a0376ab9d74f64194ebeb9b640cfd546377d" dependencies = [ "bincode", "camino", @@ -778,62 +946,95 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 1.0.109", + "syn", "toml", - "uniffi_build 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", - "uniffi_meta 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", + "uniffi_build 0.25.1", + "uniffi_meta 0.25.1", ] [[package]] name = "uniffi_meta" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66fdab2c436aed7a6391bec64204ec33948bfed9b11b303235740771f85c4ea6" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ - "serde", + "anyhow", + "bytes", "siphasher", - "uniffi_checksum_derive 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uniffi_checksum_derive 0.25.0", ] [[package]] name = "uniffi_meta" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afeeb9cc3b701cc84762e888a49366737e0487229abd298dd7f58ae58f7692e5" dependencies = [ - "serde", + "anyhow", + "bytes", "siphasher", - "uniffi_checksum_derive 0.23.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3)", + "uniffi_checksum_derive 0.25.1", ] [[package]] name = "uniffi_testing" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b0570953ec41d97ce23e3b92161ac18231670a1f97523258a6d2ab76d7f76c" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "anyhow", "camino", "cargo_metadata", "fs-err", "once_cell", - "serde", - "serde_json", ] [[package]] name = "uniffi_testing" -version = "0.23.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c60675fcc9ba5264a0c12ced2332e4b9203e5f1a8d1134cb72ffca6a048ea886" dependencies = [ "anyhow", "camino", "cargo_metadata", "fs-err", "once_cell", - "serde", - "serde_json", ] +[[package]] +name = "uniffi_udl" +version = "0.25.0" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" +dependencies = [ + "anyhow", + "uniffi_meta 0.25.0", + "uniffi_testing 0.25.0", + "weedle2 4.0.0 (git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1)", +] + +[[package]] +name = "uniffi_udl" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9c5950c95166692ca50ec77d5c9c026c9ccf83cfab563882f3df61502e211d" +dependencies = [ + "anyhow", + "uniffi_meta 0.25.1", + "uniffi_testing 0.25.1", + "weedle2 4.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "version_check" version = "0.9.4" @@ -858,7 +1059,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.23.0-3#8441959e02b9d78df0c3ea53202e5e0474cbfc76" +source = "git+https://github.com/NordSecurity/uniffi-rs.git?tag=v0.25.0-1#de1e773204d0ddcda58faac0a77570f1f8056679" dependencies = [ "nom", ] @@ -880,16 +1081,82 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "winapi-util" -version = "0.1.5" +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 = "windows" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "winapi", + "windows-targets", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-sys" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Dockerfile b/Dockerfile index 0f58f60..47e5756 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,18 @@ -FROM rust:1.64-bullseye as builder +FROM rust:1.72-bullseye as builder COPY . /project -RUN cd /project && cargo install --path uniffi-bindgen -RUN cargo install uniffi-bindgen-cs --tag v0.4.0+v0.23.0 --git https://github.com/NordSecurity/uniffi-bindgen-cs -RUN cargo install uniffi-bindgen-go --tag v0.1.5+v0.23.0 --git https://github.com/NordSecurity/uniffi-bindgen-go -FROM debian:bullseye +# Download crates.io index, saves time if subsequent steps change +RUN cargo search --limit 0 + +RUN cd /project && cargo install --path uniffi-bindgen +RUN cargo install uniffi-bindgen-cs --tag v0.7.0+v0.25.0 --git https://github.com/NordSecurity/uniffi-bindgen-cs +RUN cargo install uniffi-bindgen-go --tag v0.2.0+v0.25.0 --git https://github.com/NordSecurity/uniffi-bindgen-go +RUN cargo install uniffi-bindgen-cpp --tag v0.1.0+v0.25.0 --git https://github.com/NordSecurity/uniffi-bindgen-cpp +FROM rust:1.72-bullseye COPY --from=builder /usr/local/cargo/bin/uniffi-bindgen /bin COPY --from=builder /usr/local/cargo/bin/uniffi-bindgen-cs /bin COPY --from=builder /usr/local/cargo/bin/uniffi-bindgen-go /bin +COPY --from=builder /usr/local/cargo/bin/uniffi-bindgen-cpp /bin RUN apt-get update && apt-get install -y --no-install-recommends python3 && apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/README.md b/README.md index 12e76ca..9426415 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,15 @@ each time one of the generators is updated e.g. because of the bug fix. The tabl shows which versions of each generator are inside the docker image. -| Docker image | uniffi-rs version | uniffi-bindgen-cs version | uniffi-bindgen-go version | -|------------------------|-------------------|---------------------------|---------------------------| -| v0.23.0-6 | v0.23.0-3 (FORK) | v0.4.0+v0.23.0 | v0.1.5+v0.23.0 | -| v0.23.0-5 | v0.23.0-3 (FORK) | v0.4.0+v0.23.0 | v0.1.5+v0.23.0 | -| v0.23.0-4 | v0.23.0 (FORK) | v0.2.3+v0.23.0 | v0.1.3+v0.23.0 | -| v0.23.0-3 (DO NOT USE) | v0.23.0 (FORK) | v0.2.2+v0.23.0 | v0.1.0+v0.23.0 | -| v0.23.0-2 (DO NOT USE) | v0.23.0 | v0.2.1+v0.23.0 | v0.1.0+v0.23.0 | -| v0.23.0-1 | v0.23.0 | v0.2.1+v0.23.0 | not present | +| Docker image | uniffi-rs version | uniffi-bindgen-cs version | uniffi-bindgen-go version | uniffi-bindgen-cpp version | +|------------------------|-----------------------|---------------------------|---------------------------|----------------------------| +| v0.25.0-1 | **v0.25.0-1 (FORK)** | **v0.7.0+v0.25.0** | **v0.2.0+v0.25.0** | **v0.1.0+v0.25.0** | +| v0.23.0-6 | v0.23.0-3 (FORK) | v0.4.0+v0.23.0 | v0.1.5+v0.23.0 | not present | +| v0.23.0-5 | v0.23.0-3 (FORK) | **v0.4.0+v0.23.0** | **v0.1.5+v0.23.0** | not present | +| v0.23.0-4 | v0.23.0 (FORK) | **v0.2.3+v0.23.0** | **v0.1.3+v0.23.0** | not present | +| v0.23.0-3 (DO NOT USE) | v0.23.0 (FORK) | **v0.2.2+v0.23.0** | v0.1.0+v0.23.0 | not present | +| v0.23.0-2 (DO NOT USE) | v0.23.0 | v0.2.1+v0.23.0 | **v0.1.0+v0.23.0** | not present | +| v0.23.0-1 | v0.23.0 | v0.2.1+v0.23.0 | not present | not present | ### v0.23.0-6 diff --git a/compatibility-test/Cargo.toml b/compatibility-test/Cargo.toml index 86eb8c2..e990bbc 100644 --- a/compatibility-test/Cargo.toml +++ b/compatibility-test/Cargo.toml @@ -11,9 +11,9 @@ crate-type = ["lib", "staticlib", "cdylib"] name = "uniffi_coverall" [dependencies] -uniffi = { version = "0.23.0" } +uniffi = { version = "0.25.0" } once_cell = "1.12" thiserror = "1.0" [build-dependencies] -uniffi = { version = "0.23.0", features = ["build"] } +uniffi = { version = "0.25.0", features = ["build"] } diff --git a/compatibility-test/src/coverall.udl b/compatibility-test/src/coverall.udl index 9f12676..2c0d955 100644 --- a/compatibility-test/src/coverall.udl +++ b/compatibility-test/src/coverall.udl @@ -4,15 +4,27 @@ namespace coverall { u64 get_num_alive(); + sequence get_traits(); + + MaybeSimpleDict get_maybe_simple_dict(i8 index); + // void returning error throwing namespace function to catch clippy warnings (eg, #1330) [Throws=CoverallError] void println(string text); + + [Throws=CoverallFlatError] + void throw_flat_error(); + + [Throws=CoverallRichErrorNoVariantData] + void throw_rich_error_no_variant_data(); }; dictionary SimpleDict { string text; string? maybe_text; - boolean a_bool; + bytes some_bytes; + bytes? maybe_some_bytes; + boolean a_bool; boolean? maybe_a_bool; u8 unsigned8; u8? maybe_unsigned8; @@ -29,6 +41,7 @@ dictionary SimpleDict { double float64; double? maybe_float64; Coveralls? coveralls; + TestTrait? test_trait; }; dictionary DictWithDefaults { @@ -43,15 +56,38 @@ interface MaybeSimpleDict { Nah(); }; +// Note that UDL *can not* express flat enums (ie, those with variants that carry data which +// should be ignored for the ffi), only flat errors? +//enum SimpleFlatEnum { +// "First", +// "Second", +//}; + [Error] enum CoverallError { "TooManyHoles" }; +// This error is described in Rust with variants, but because it's declared +// here via an `enum` it's considered "flat" +[Error] +enum CoverallFlatError { + "TooManyVariants" +}; + +// This error is for an enum that's still "flat" on the Rust side (ie, no +// variants have associated data), but it behaves differently on the bindings +// side than had it been described via `enum` +[Error] +interface CoverallRichErrorNoVariantData { + TooManyPlainVariants(); +}; + [Error] interface ComplexError { - OsError(i16 code, i16 extended_code); - PermissionDenied(string reason); + OsError(i16 code, i16 extended_code); + PermissionDenied(string reason); + UnknownError(); }; interface Coveralls { @@ -128,6 +164,9 @@ interface Coveralls { /// Returns all repairs made. sequence get_repairs(); + + /// Reverses the bytes. + bytes reverse(bytes value); }; // coveralls keep track of their repairs (an interface in a dict) @@ -150,3 +189,41 @@ interface ThreadsafeCounter { void busy_wait(i32 ms); i32 increment_if_busy(); }; + +// This is a trait implemented on the Rust side. +[Trait] +interface TestTrait { + string name(); // The name of the implementation + + [Self=ByArc] + u64 number(); + + /// Calls `Arc::strong_count()` on the `Arc` containing `self`. + [Self=ByArc] + u64 strong_count(); + + /// Takes an `Arc` and stores it in `self`, dropping the existing + /// reference. Note you can create circular references by passing `self`. + void take_other(TestTrait? other); + + /// Returns what was previously set via `take_other()`, or null. + TestTrait? get_other(); +}; + +// Forward/backward declarations are fine in UDL. +// Running the Python tests & type checks will ensure this works, +// no function calls needed + +interface IFirst { + constructor(); + + // Handling optional with a default value + boolean compare(optional ISecond? other = null); +}; + +interface ISecond { + constructor(); + + // Default only + boolean compare(IFirst? other); +}; diff --git a/compatibility-test/src/lib.rs b/compatibility-test/src/lib.rs index ad30703..e591c0d 100644 --- a/compatibility-test/src/lib.rs +++ b/compatibility-test/src/lib.rs @@ -9,6 +9,9 @@ use std::time::SystemTime; use once_cell::sync::Lazy; +mod traits; +pub use traits::{get_traits, TestTrait}; + static NUM_ALIVE: Lazy> = Lazy::new(|| RwLock::new(0)); #[derive(Debug, thiserror::Error)] @@ -17,6 +20,50 @@ pub enum CoverallError { TooManyHoles, } +#[derive(Debug, thiserror::Error)] +pub enum CoverallFlatError { + #[error("Too many variants: {num}")] + TooManyVariants { num: i16 }, +} + +fn throw_flat_error() -> Result<(), CoverallFlatError> { + Err(CoverallFlatError::TooManyVariants { num: 99 }) +} + +#[derive(Debug, thiserror::Error, uniffi::Error)] +#[uniffi(flat_error)] // "flat" isn't really the correct terminology here. +pub enum CoverallMacroError { + #[error("The coverall has too many macros")] + TooManyMacros, +} + +#[uniffi::export] +fn throw_macro_error() -> Result<(), CoverallMacroError> { + Err(CoverallMacroError::TooManyMacros) +} + +#[derive(Debug, thiserror::Error, uniffi::Error)] +#[uniffi(flat_error)] +pub enum CoverallFlatMacroError { + #[error("Too many variants: {num}")] + TooManyVariants { num: i16 }, +} + +#[uniffi::export] +fn throw_flat_macro_error() -> Result<(), CoverallFlatMacroError> { + Err(CoverallFlatMacroError::TooManyVariants { num: 88 }) +} + +#[derive(Debug, thiserror::Error)] +pub enum CoverallRichErrorNoVariantData { + #[error("TooManyPlainVariants")] + TooManyPlainVariants, +} + +fn throw_rich_error_no_variant_data() -> Result<(), CoverallRichErrorNoVariantData> { + Err(CoverallRichErrorNoVariantData::TooManyPlainVariants) +} + /// This error doesn't appear in the interface, instead /// we rely on an `Into` impl to surface it to consumers. #[derive(Debug, thiserror::Error)] @@ -39,12 +86,34 @@ pub enum ComplexError { OsError { code: i16, extended_code: i16 }, #[error("PermissionDenied: {reason}")] PermissionDenied { reason: String }, + #[error("Unknown error")] + UnknownError, } -#[derive(Debug, Clone)] +#[derive(Debug, thiserror::Error, uniffi::Error)] +pub enum ComplexMacroError { + #[error("OsError: {code} ({extended_code})")] + OsError { code: i16, extended_code: i16 }, + #[error("PermissionDenied: {reason}")] + PermissionDenied { reason: String }, + #[error("Unknown error")] + UnknownError, +} + +#[uniffi::export] +fn throw_complex_macro_error() -> Result<(), ComplexMacroError> { + Err(ComplexMacroError::OsError { + code: 1, + extended_code: 2, + }) +} + +#[derive(Clone, Debug, Default)] pub struct SimpleDict { text: String, maybe_text: Option, + some_bytes: Vec, + maybe_some_bytes: Option>, a_bool: bool, maybe_a_bool: Option, unsigned8: u8, @@ -62,6 +131,7 @@ pub struct SimpleDict { float64: f64, maybe_float64: Option, coveralls: Option>, + test_trait: Option>, } #[derive(Debug, Clone)] @@ -77,10 +147,46 @@ pub enum MaybeSimpleDict { Nah, } +fn get_maybe_simple_dict(index: i8) -> MaybeSimpleDict { + match index { + 0 => MaybeSimpleDict::Yeah { + d: SimpleDict::default(), + }, + 1 => MaybeSimpleDict::Nah, + _ => unreachable!("invalid index: {index}"), + } +} + +// UDL can not describe this as a "flat" enum, but we'll keep it here to help demonstrate that! +#[derive(Debug, Clone)] +pub enum SimpleFlatEnum { + First { val: String }, + Second { num: u16 }, +} + +#[derive(Debug, Clone, uniffi::Enum)] +pub enum SimpleFlatMacroEnum { + First { val: String }, + Second { num: u16 }, +} + +#[uniffi::export] +fn get_simple_flat_macro_enum(index: i8) -> SimpleFlatMacroEnum { + match index { + 0 => SimpleFlatMacroEnum::First { + val: "the first".to_string(), + }, + 1 => SimpleFlatMacroEnum::Second { num: 2 }, + _ => unreachable!("invalid index: {index}"), + } +} + fn create_some_dict() -> SimpleDict { SimpleDict { text: "text".to_string(), maybe_text: Some("maybe_text".to_string()), + some_bytes: b"some_bytes".to_vec(), + maybe_some_bytes: Some(b"maybe_some_bytes".to_vec()), a_bool: true, maybe_a_bool: Some(false), unsigned8: 1, @@ -98,30 +204,22 @@ fn create_some_dict() -> SimpleDict { float64: 0.0, maybe_float64: Some(1.0), coveralls: Some(Arc::new(Coveralls::new("some_dict".to_string()))), + test_trait: Some(Arc::new(traits::Trait2 {})), } } fn create_none_dict() -> SimpleDict { SimpleDict { text: "text".to_string(), - maybe_text: None, + some_bytes: b"some_bytes".to_vec(), a_bool: true, - maybe_a_bool: None, unsigned8: 1, - maybe_unsigned8: None, unsigned16: 3, - maybe_unsigned16: None, unsigned64: u64::MAX, - maybe_unsigned64: None, signed8: 8, - maybe_signed8: None, signed64: i64::MAX, - maybe_signed64: None, float32: 1.2345, - maybe_float32: None, - float64: 0.0, - maybe_float64: None, - coveralls: None, + ..Default::default() } } @@ -203,6 +301,7 @@ impl Coveralls { 2 => Err(ComplexError::PermissionDenied { reason: "Forbidden".to_owned(), }), + 3 => Err(ComplexError::UnknownError), _ => panic!("Invalid input"), } } @@ -282,6 +381,11 @@ impl Coveralls { let repairs = self.repairs.lock().unwrap(); repairs.clone() } + + fn reverse(&self, mut value: Vec) -> Vec { + value.reverse(); + value + } } impl Drop for Coveralls { @@ -350,4 +454,30 @@ impl ThreadsafeCounter { } } -uniffi::include_scaffolding!("coverall"); \ No newline at end of file +#[derive(Default)] +pub struct IFirst; + +impl IFirst { + pub fn new() -> Self { + Self + } + + pub fn compare(&self, _other: Option>) -> bool { + false + } +} + +#[derive(Default)] +pub struct ISecond; + +impl ISecond { + pub fn new() -> Self { + Self + } + + pub fn compare(&self, _other: Option>) -> bool { + false + } +} + +uniffi::include_scaffolding!("coverall"); diff --git a/compatibility-test/src/traits.rs b/compatibility-test/src/traits.rs new file mode 100644 index 0000000..fe9694e --- /dev/null +++ b/compatibility-test/src/traits.rs @@ -0,0 +1,74 @@ +/* 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 std::sync::{Arc, Mutex}; + +// namespace functions. +pub fn get_traits() -> Vec> { + vec![ + Arc::new(Trait1 { + ..Default::default() + }), + Arc::new(Trait2 {}), + ] +} + +pub trait TestTrait: Send + Sync + std::fmt::Debug { + fn name(&self) -> String; + + fn number(self: Arc) -> u64; + + fn strong_count(self: Arc) -> u64 { + Arc::strong_count(&self) as u64 + } + + fn take_other(&self, other: Option>); + + fn get_other(&self) -> Option>; +} + +#[derive(Debug, Default)] +pub(crate) struct Trait1 { + // A reference to another trait. + other: Mutex>>, +} + +impl TestTrait for Trait1 { + fn name(&self) -> String { + "trait 1".to_string() + } + + fn number(self: Arc) -> u64 { + 1_u64 + } + + fn take_other(&self, other: Option>) { + *self.other.lock().unwrap() = other.map(|arc| Arc::clone(&arc)) + } + + fn get_other(&self) -> Option> { + (*self.other.lock().unwrap()).as_ref().map(Arc::clone) + } +} + +#[derive(Debug)] +pub(crate) struct Trait2 {} +impl TestTrait for Trait2 { + fn name(&self) -> String { + "trait 2".to_string() + } + + fn number(self: Arc) -> u64 { + 2_u64 + } + + // Don't bother implementing these here - the test on the struct above is ok. + fn take_other(&self, _other: Option>) { + unimplemented!(); + } + + fn get_other(&self) -> Option> { + unimplemented!() + } +} diff --git a/compatibility-test/tests/cpp/test_coverall.cpp b/compatibility-test/tests/cpp/test_coverall.cpp new file mode 100644 index 0000000..ff95e0d --- /dev/null +++ b/compatibility-test/tests/cpp/test_coverall.cpp @@ -0,0 +1,7 @@ +#include "coverall.hpp" + +int main() { + std::cout << "Running C++ coverall tests" << std::endl; + std::cout << "(tests not implemented yet)" << std::endl; + return 0; +} diff --git a/compatibility-test/tests/cs/test_coverall.cs b/compatibility-test/tests/cs/test_coverall.cs index e183a8f..08fc515 100644 --- a/compatibility-test/tests/cs/test_coverall.cs +++ b/compatibility-test/tests/cs/test_coverall.cs @@ -3,6 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ using Xunit; +using System.Collections.Generic; +using System.Threading; using System; using uniffi.coverall; @@ -16,7 +18,7 @@ public void FFIObjectSafeHandleDropsNativeReferenceOutsideOfUsingBlock() { }; closure(); GC.Collect(); - Thread.Sleep(1); + Thread.Sleep(10); Assert.Equal(0UL, CoverallMethods.GetNumAlive()); } @@ -70,7 +72,7 @@ public void TestArcs() { Assert.Throws(() => coveralls.FalliblePanic("Expected panic in a fallible function!")); coveralls.TakeOther(null); - Assert.Equal(2UL, coveralls.StrongCount()); + Assert.Equal(2UL, coveralls.StrongCount()); } Assert.Equal(0UL, CoverallMethods.GetNumAlive()); @@ -124,7 +126,9 @@ public void TestComplexErrors() { () => coveralls.MaybeThrowComplex(2)); Assert.Equal("Forbidden", permission_denied.reason); - Assert.Throws(() => coveralls.MaybeThrowComplex(3)); + Assert.Throws(() => coveralls.MaybeThrowComplex(3)); + + Assert.Throws(() => coveralls.MaybeThrowComplex(4)); } } @@ -142,17 +146,19 @@ public void MultiThreadedCallsWork() { // Make sure that there is no blocking during concurrent FFI calls. using (var counter = new ThreadsafeCounter()) { + const int WAIT_MILLIS = 20; + Thread blockingThread = new Thread(new ThreadStart(() => { - // block the thread for 100ms - counter.BusyWait(300); + counter.BusyWait(WAIT_MILLIS); })); var count = 0; Thread countingThread = new Thread(new ThreadStart(() => { - for (int i = 0; i < 100; i++) { + for (int i = 0; i < WAIT_MILLIS; i++) { // `count` is only incremented if another thread is blocking the counter. // This ensures that both calls are running concurrently. count = counter.IncrementIfBusy(); + Thread.Sleep(1); } })); @@ -164,4 +170,10 @@ public void MultiThreadedCallsWork() { } } + [Fact] + public void TestBytes() { + using (var coveralls = new Coveralls("test_bytes")) { + Assert.Equal(new byte[] { 3, 2, 1 }, coveralls.Reverse(new byte[] { 1, 2, 3})); + } + } } diff --git a/compatibility-test/tests/go/coverall_test.go b/compatibility-test/tests/go/coverall_test.go index e842501..32a54e1 100644 --- a/compatibility-test/tests/go/coverall_test.go +++ b/compatibility-test/tests/go/coverall_test.go @@ -2,187 +2,193 @@ * 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/. */ - package go_tests - - import ( - "testing" - "time" - - "test_coverall/uniffi/coverall" - "github.com/stretchr/testify/assert" - ) - - func TestCoverall(t *testing.T) { - d := coverall.CreateSomeDict() - defer d.Destroy() - - assert.Equal(t, "text", d.Text) - assert.Equal(t, "maybe_text", *d.MaybeText) - assert.True(t, d.ABool) - assert.False(t, *d.MaybeABool) - assert.Equal(t, uint8(1), d.Unsigned8) - assert.Equal(t, uint8(2), *d.MaybeUnsigned8) - - assert.Equal(t, uint16(3), d.Unsigned16) - assert.Equal(t, uint16(4), *d.MaybeUnsigned16) - assert.Equal(t, uint64(18446744073709551615), d.Unsigned64) - assert.Equal(t, uint64(0), *d.MaybeUnsigned64) - assert.Equal(t, int8(8), d.Signed8) - assert.Equal(t, int8(0), *d.MaybeSigned8) - assert.Equal(t, int64(9223372036854775807), d.Signed64) - assert.Equal(t, int64(0), *d.MaybeSigned64) - - assert.Equal(t, float32(1.2345), d.Float32) - assert.Equal(t, float32(22.0/7.0), *d.MaybeFloat32) - assert.Equal(t, 0.0, d.Float64) - assert.Equal(t, 1.0, *d.MaybeFloat64) - - assert.Equal(t, "some_dict", (*d.Coveralls).GetName()) - } - - func TestCoverallArcs(t *testing.T) { - coveralls := coverall.NewCoveralls("test_arcs") - - assert.Equal(t, uint64(1), coverall.GetNumAlive()) - // One ref held by the foreign-language code, one created for this method call. - assert.Equal(t, uint64(2), coveralls.StrongCount()) - assert.Nil(t, coveralls.GetOther()) - coveralls.TakeOther(&coveralls) - // Should now be a new strong ref, held by the object's reference to itself. - assert.Equal(t, uint64(3), coveralls.StrongCount()) - assert.Equal(t, uint64(1), coverall.GetNumAlive()) - - other := *coveralls.GetOther() - assert.Equal(t, "test_arcs", (*other).GetName()) - other.Destroy() - - assert.ErrorIs(t, coveralls.TakeOtherFallible(), coverall.ErrCoverallErrorTooManyHoles) - - assert.PanicsWithError(t, "expected panic: with an arc!", func() { - coveralls.TakeOtherPanic("expected panic: with an arc!") - }) - - assert.PanicsWithError(t, "Expected panic in a fallible function!", func() { - coveralls.FalliblePanic("Expected panic in a fallible function!") - }) - - coveralls.TakeOther(nil) - assert.Equal(t, uint64(2), coveralls.StrongCount()) - - coveralls.Destroy() - assert.Equal(t, uint64(0), coverall.GetNumAlive()) - } - - func TestCoverallReturnObjects(t *testing.T) { - coveralls := coverall.NewCoveralls("test_return_objects") - assert.Equal(t, uint64(1), coverall.GetNumAlive()) - assert.Equal(t, uint64(2), coveralls.StrongCount()) - - c2 := coveralls.CloneMe() - assert.Equal(t, coveralls.GetName(), c2.GetName()) - assert.Equal(t, uint64(2), coverall.GetNumAlive()) - assert.Equal(t, uint64(2), c2.StrongCount()) - - coveralls.TakeOther(&c2) - // same number alive but `c2` has an additional ref count. - assert.Equal(t, uint64(2), coverall.GetNumAlive()) - assert.Equal(t, uint64(2), coveralls.StrongCount()) - assert.Equal(t, uint64(3), c2.StrongCount()) - - c2.Destroy() - // Here we've dropped C# reference to `c2`, but the rust struct will not - // be dropped as coveralls hold an `Arc<>` to it. - assert.Equal(t, uint64(2), coverall.GetNumAlive()) - - coveralls.Destroy() - assert.Equal(t, uint64(0), coverall.GetNumAlive()) - } - - func TestCoverallSimpleErrors(t *testing.T) { - coveralls := coverall.NewCoveralls("test_simple_errors") - defer coveralls.Destroy() - - _, err := coveralls.MaybeThrow(true) - assert.ErrorIs(t, err, coverall.ErrCoverallErrorTooManyHoles) - - _, err = coveralls.MaybeThrowInto(true) - assert.ErrorIs(t, err, coverall.ErrCoverallErrorTooManyHoles) - - assert.PanicsWithError(t, "oops", func() { - coveralls.Panic("oops") - }) - } - - func TestCoverallComplexErrors(t *testing.T) { - coveralls := coverall.NewCoveralls("test_complex_errors") - defer coveralls.Destroy() - - { - v, err := coveralls.MaybeThrowComplex(0) - if assert.NoError(t, err) { - assert.True(t, v) - } - } - - { - _, err := coveralls.MaybeThrowComplex(1) - var osErr *coverall.ComplexErrorOsError - if assert.ErrorAs(t, err, &osErr) { - assert.Equal(t, int16(10), osErr.Code) - assert.Equal(t, int16(20), osErr.ExtendedCode) - } - } - - { - _, err := coveralls.MaybeThrowComplex(2) - var permissionErr *coverall.ComplexErrorPermissionDenied - if assert.ErrorAs(t, err, &permissionErr) { - assert.Equal(t, "Forbidden", permissionErr.Reason) - } - } - - assert.PanicsWithError(t, "Invalid input", func() { - coveralls.MaybeThrowComplex(3) - }) - } - - func TestCoverallInterfacesInDicts(t *testing.T) { - coveralls := coverall.NewCoveralls("test_interface_in_dicts") - defer coveralls.Destroy() - - coveralls.AddPatch(coverall.NewPatch(coverall.ColorRed)) - coveralls.AddRepair(coverall.Repair{time.Now(), coverall.NewPatch(coverall.ColorBlue)}) - assert.Equal(t, 2, len(coveralls.GetRepairs())) - } - - func TestCoverallMultiThreadedCallsWork(t *testing.T) { - // Make sure that there is no blocking during concurrent FFI calls. - - counter := coverall.NewThreadsafeCounter() - defer counter.Destroy() - - const waitMillis = 10 - - finished1 := make(chan struct{}) - go func() { - // block the thread - counter.BusyWait(waitMillis) - finished1 <- struct{}{} - }() - - count := int32(0) - finished2 := make(chan struct{}) - go func() { - for i := 0; i < waitMillis; i++ { - // `count` is only incremented if another thread is blocking the counter. - // This ensures that both calls are running concurrently. - count = counter.IncrementIfBusy() - time.Sleep(time.Millisecond) - } - finished2 <- struct{}{} - }() - - <-finished1 - <-finished2 - assert.True(t, count > 0) - } +package go_tests + +import ( + "testing" + "time" + + "test_coverall/coverall" + "github.com/stretchr/testify/assert" +) + +func TestCoverall(t *testing.T) { + d := coverall.CreateSomeDict() + defer d.Destroy() + + assert.Equal(t, "text", d.Text) + assert.Equal(t, "maybe_text", *d.MaybeText) + assert.True(t, d.ABool) + assert.False(t, *d.MaybeABool) + assert.Equal(t, uint8(1), d.Unsigned8) + assert.Equal(t, uint8(2), *d.MaybeUnsigned8) + + assert.Equal(t, uint16(3), d.Unsigned16) + assert.Equal(t, uint16(4), *d.MaybeUnsigned16) + assert.Equal(t, uint64(18446744073709551615), d.Unsigned64) + assert.Equal(t, uint64(0), *d.MaybeUnsigned64) + assert.Equal(t, int8(8), d.Signed8) + assert.Equal(t, int8(0), *d.MaybeSigned8) + assert.Equal(t, int64(9223372036854775807), d.Signed64) + assert.Equal(t, int64(0), *d.MaybeSigned64) + + assert.Equal(t, float32(1.2345), d.Float32) + assert.Equal(t, float32(22.0/7.0), *d.MaybeFloat32) + assert.Equal(t, 0.0, d.Float64) + assert.Equal(t, 1.0, *d.MaybeFloat64) + + assert.Equal(t, "some_dict", (*d.Coveralls).GetName()) +} + +func TestCoverallArcs(t *testing.T) { + coveralls := coverall.NewCoveralls("test_arcs") + + assert.Equal(t, uint64(1), coverall.GetNumAlive()) + // One ref held by the foreign-language code, one created for this method call. + assert.Equal(t, uint64(2), coveralls.StrongCount()) + assert.Nil(t, coveralls.GetOther()) + coveralls.TakeOther(&coveralls) + // Should now be a new strong ref, held by the object's reference to itself. + assert.Equal(t, uint64(3), coveralls.StrongCount()) + assert.Equal(t, uint64(1), coverall.GetNumAlive()) + + other := *coveralls.GetOther() + assert.Equal(t, "test_arcs", (*other).GetName()) + other.Destroy() + + assert.ErrorIs(t, coveralls.TakeOtherFallible(), coverall.ErrCoverallErrorTooManyHoles) + + assert.PanicsWithError(t, "expected panic: with an arc!", func() { + coveralls.TakeOtherPanic("expected panic: with an arc!") + }) + + assert.PanicsWithError(t, "Expected panic in a fallible function!", func() { + coveralls.FalliblePanic("Expected panic in a fallible function!") + }) + + coveralls.TakeOther(nil) + assert.Equal(t, uint64(2), coveralls.StrongCount()) + + coveralls.Destroy() + assert.Equal(t, uint64(0), coverall.GetNumAlive()) +} + +func TestCoverallReturnObjects(t *testing.T) { + coveralls := coverall.NewCoveralls("test_return_objects") + assert.Equal(t, uint64(1), coverall.GetNumAlive()) + assert.Equal(t, uint64(2), coveralls.StrongCount()) + + c2 := coveralls.CloneMe() + assert.Equal(t, coveralls.GetName(), c2.GetName()) + assert.Equal(t, uint64(2), coverall.GetNumAlive()) + assert.Equal(t, uint64(2), c2.StrongCount()) + + coveralls.TakeOther(&c2) + // same number alive but `c2` has an additional ref count. + assert.Equal(t, uint64(2), coverall.GetNumAlive()) + assert.Equal(t, uint64(2), coveralls.StrongCount()) + assert.Equal(t, uint64(3), c2.StrongCount()) + + c2.Destroy() + // Here we've dropped C# reference to `c2`, but the rust struct will not + // be dropped as coveralls hold an `Arc<>` to it. + assert.Equal(t, uint64(2), coverall.GetNumAlive()) + + coveralls.Destroy() + assert.Equal(t, uint64(0), coverall.GetNumAlive()) +} + +func TestCoverallSimpleErrors(t *testing.T) { + coveralls := coverall.NewCoveralls("test_simple_errors") + defer coveralls.Destroy() + + _, err := coveralls.MaybeThrow(true) + assert.ErrorIs(t, err, coverall.ErrCoverallErrorTooManyHoles) + + _, err = coveralls.MaybeThrowInto(true) + assert.ErrorIs(t, err, coverall.ErrCoverallErrorTooManyHoles) + + assert.PanicsWithError(t, "oops", func() { + coveralls.Panic("oops") + }) +} + +func TestCoverallComplexErrors(t *testing.T) { + coveralls := coverall.NewCoveralls("test_complex_errors") + defer coveralls.Destroy() + + { + v, err := coveralls.MaybeThrowComplex(0) + if assert.NoError(t, err) { + assert.True(t, v) + } + } + + { + _, err := coveralls.MaybeThrowComplex(1) + var osErr *coverall.ComplexErrorOsError + if assert.ErrorAs(t, err, &osErr) { + assert.Equal(t, int16(10), osErr.Code) + assert.Equal(t, int16(20), osErr.ExtendedCode) + } + } + + { + _, err := coveralls.MaybeThrowComplex(2) + var permissionErr *coverall.ComplexErrorPermissionDenied + if assert.ErrorAs(t, err, &permissionErr) { + assert.Equal(t, "Forbidden", permissionErr.Reason) + } + } + + { + _, err := coveralls.MaybeThrowComplex(3) + var unErr *coverall.ComplexErrorUnknownError + assert.ErrorAs(t, err, &unErr) + } + + assert.PanicsWithError(t, "Invalid input", func() { + coveralls.MaybeThrowComplex(4) + }) +} + +func TestCoverallInterfacesInDicts(t *testing.T) { + coveralls := coverall.NewCoveralls("test_interface_in_dicts") + defer coveralls.Destroy() + + coveralls.AddPatch(coverall.NewPatch(coverall.ColorRed)) + coveralls.AddRepair(coverall.Repair{time.Now(), coverall.NewPatch(coverall.ColorBlue)}) + assert.Equal(t, 2, len(coveralls.GetRepairs())) +} + +func TestCoverallMultiThreadedCallsWork(t *testing.T) { + // Make sure that there is no blocking during concurrent FFI calls. + + counter := coverall.NewThreadsafeCounter() + defer counter.Destroy() + + const waitMillis = 10 + + finished1 := make(chan struct{}) + go func() { + // block the thread + counter.BusyWait(waitMillis) + finished1 <- struct{}{} + }() + + count := int32(0) + finished2 := make(chan struct{}) + go func() { + for i := 0; i < waitMillis; i++ { + // `count` is only incremented if another thread is blocking the counter. + // This ensures that both calls are running concurrently. + count = counter.IncrementIfBusy() + time.Sleep(time.Millisecond) + } + finished2 <- struct{}{} + }() + + <-finished1 + <-finished2 + assert.True(t, count > 0) +} diff --git a/compatibility-test/tests/kotlin/test_coverall.kts b/compatibility-test/tests/kotlin/test_coverall.kts index 34f85c8..62fbbb5 100644 --- a/compatibility-test/tests/kotlin/test_coverall.kts +++ b/compatibility-test/tests/kotlin/test_coverall.kts @@ -12,10 +12,12 @@ import uniffi.coverall.* // Test some_dict(). // N.B. we need to `use` here to clean up the contained `Coveralls` reference. createSomeDict().use { d -> - assert(d.text == "text"); - assert(d.maybeText == "maybe_text"); - assert(d.aBool); - assert(d.maybeABool == false); + assert(d.text == "text") + assert(d.maybeText == "maybe_text") + assert(d.someBytes.contentEquals("some_bytes".toByteArray(Charsets.UTF_8))) + assert(d.maybeSomeBytes.contentEquals("maybe_some_bytes".toByteArray(Charsets.UTF_8))) + assert(d.aBool) + assert(d.maybeABool == false) assert(d.unsigned8 == 1.toUByte()) assert(d.maybeUnsigned8 == 2.toUByte()) assert(d.unsigned16 == 3.toUShort()) @@ -39,6 +41,36 @@ createSomeDict().use { d -> assert(d.coveralls!!.getName() == "some_dict") } +createNoneDict().use { d -> + assert(d.text == "text") + assert(d.maybeText == null) + assert(d.someBytes.contentEquals("some_bytes".toByteArray(Charsets.UTF_8))) + assert(d.maybeSomeBytes == null) + assert(d.aBool) + assert(d.maybeABool == null) + assert(d.unsigned8 == 1.toUByte()) + assert(d.maybeUnsigned8 == null) + assert(d.unsigned16 == 3.toUShort()) + assert(d.maybeUnsigned16 == null) + assert(d.unsigned64 == 18446744073709551615UL) + assert(d.maybeUnsigned64 == null) + assert(d.signed8 == 8.toByte()) + assert(d.maybeSigned8 == null) + assert(d.signed64 == 9223372036854775807L) + assert(d.maybeSigned64 == null) + + // floats should be "close enough". + fun Float.almostEquals(other: Float) = Math.abs(this - other) < 0.000001 + fun Double.almostEquals(other: Double) = Math.abs(this - other) < 0.000001 + + assert(d.float32.almostEquals(1.2345F)) + assert(d.maybeFloat32 == null) + assert(d.float64.almostEquals(0.0)) + assert(d.maybeFloat64 == null) + + assert(d.coveralls == null) +} + // Test arcs. @@ -139,7 +171,7 @@ Coveralls("test_complex_errors").use { coveralls -> assert(e.code == 10.toShort()) assert(e.extendedCode == 20.toShort()) assert(e.toString() == "uniffi.coverall.ComplexException\$OsException: code=10, extendedCode=20") { - "Unexpected ComplexError.OsError.toString() value: ${e.toString()}" + "Unexpected ComplexException.OsError.toString() value: ${e.toString()}" } } @@ -149,13 +181,22 @@ Coveralls("test_complex_errors").use { coveralls -> } catch(e: ComplexException.PermissionDenied) { assert(e.reason == "Forbidden") assert(e.toString() == "uniffi.coverall.ComplexException\$PermissionDenied: reason=Forbidden") { - "Unexpected ComplexError.PermissionDenied.toString() value: ${e.toString()}" + "Unexpected ComplexException.PermissionDenied.toString() value: ${e.toString()}" } } try { coveralls.maybeThrowComplex(3) throw RuntimeException("Expected method to throw exception") + } catch(e: ComplexException.UnknownException) { + assert(e.toString() == "uniffi.coverall.ComplexException\$UnknownException: ") { + "Unexpected ComplexException.UnknownException.toString() value: ${e.toString()}" + } + } + + try { + coveralls.maybeThrowComplex(4) + throw RuntimeException("Expected method to throw exception") } catch(e: InternalException) { // Expected result } @@ -216,3 +257,8 @@ d = DictWithDefaults(name = "this", category = "that", integer = 42UL) assert(d.name == "this") assert(d.category == "that") assert(d.integer == 42UL) + +// Test bytes +Coveralls("test_bytes").use { coveralls -> + assert(coveralls.reverse("123".toByteArray(Charsets.UTF_8)).toString(Charsets.UTF_8) == "321") +} diff --git a/compatibility-test/tests/python/test_coverall.py b/compatibility-test/tests/python/test_coverall.py index a8fd0c8..a63a2e8 100644 --- a/compatibility-test/tests/python/test_coverall.py +++ b/compatibility-test/tests/python/test_coverall.py @@ -16,6 +16,8 @@ def test_some_dict(self): d = create_some_dict() self.assertEqual(d.text, "text") self.assertEqual(d.maybe_text, "maybe_text") + self.assertEqual(d.some_bytes, b"some_bytes") + self.assertEqual(d.maybe_some_bytes, b"maybe_some_bytes") self.assertTrue(d.a_bool) self.assertFalse(d.maybe_a_bool) self.assertEqual(d.unsigned8, 1) @@ -29,6 +31,7 @@ def test_some_dict(self): self.assertEqual(d.signed64, 9223372036854775807) self.assertEqual(d.maybe_signed64, 0) self.assertEqual(d.coveralls.get_name(), "some_dict") + self.assertEqual(d.test_trait.name(), "trait 2") # floats should be "close enough" - although it's mildly surprising that # we need to specify `places=6` whereas the default is 7. @@ -41,6 +44,8 @@ def test_none_dict(self): d = create_none_dict() self.assertEqual(d.text, "text") self.assertIsNone(d.maybe_text) + self.assertEqual(d.some_bytes, b"some_bytes") + self.assertIsNone(d.maybe_some_bytes) self.assertTrue(d.a_bool) self.assertIsNone(d.maybe_a_bool) self.assertEqual(d.unsigned8, 1) @@ -59,6 +64,7 @@ def test_none_dict(self): self.assertAlmostEqual(d.float64, 0.0) self.assertIsNone(d.maybe_float64) self.assertIsNone(d.coveralls) + self.assertIsNone(d.test_trait) def test_constructors(self): self.assertEqual(get_num_alive(), 0) @@ -87,19 +93,57 @@ def test_constructors(self): def test_simple_errors(self): + # This is testing enums which have been described in UDL via `enum` or via + # procmacros with `#[uniffi(flat_error)]`. Whether the variants have fields or not + # in Rust, these are treated as though each variant uses a single string. coveralls = Coveralls("test_errors") self.assertEqual(coveralls.get_name(), "test_errors") - with self.assertRaisesRegex(CoverallError.TooManyHoles, "The coverall has too many holes"): + with self.assertRaisesRegex(CoverallError.TooManyHoles, "The coverall has too many holes") as cm: coveralls.maybe_throw(True) - - with self.assertRaises(CoverallError.TooManyHoles): + self.assertEqual(len(cm.exception.args), 1) + self.assertEqual(type(cm.exception.args[0]), str) + self.assertEqual(str(cm.exception), "The coverall has too many holes") + self.assertEqual(repr(cm.exception), "CoverallError.TooManyHoles('The coverall has too many holes')") + + with self.assertRaisesRegex(CoverallMacroError.TooManyMacros, "The coverall has too many macros") as cm: + throw_macro_error() + self.assertEqual(len(cm.exception.args), 1) + self.assertEqual(type(cm.exception.args[0]), str) + self.assertEqual(str(cm.exception), "The coverall has too many macros") + self.assertEqual(repr(cm.exception), "CoverallMacroError.TooManyMacros('The coverall has too many macros')") + + with self.assertRaises(CoverallError.TooManyHoles) as cm: coveralls.maybe_throw_into(True) + self.assertEqual(len(cm.exception.args), 1) + self.assertEqual(type(cm.exception.args[0]), str) with self.assertRaisesRegex(InternalError, "expected panic: oh no"): coveralls.panic("expected panic: oh no") + def test_flat_errors(self): + # This is testing enums which have fields in Rust but are marked as "flat" for the ffi. + with self.assertRaisesRegex(CoverallFlatError.TooManyVariants, "Too many variants: 99") as cm: + throw_flat_error() + self.assertEqual(len(cm.exception.args), 1) + self.assertEqual(type(cm.exception.args[0]), str) + + with self.assertRaisesRegex(CoverallFlatMacroError.TooManyVariants, "Too many variants: 88") as cm: + throw_flat_macro_error() + self.assertEqual(len(cm.exception.args), 1) + self.assertEqual(type(cm.exception.args[0]), str) + + # CoverallRichErrorNoVariantData is "flat" on the Rust side, but because it was + # described in the UDL via `[Error]interface`, it doesn't get the "flat" (ie, lowered as though + # each variant had a simple string) semantics. + with self.assertRaises(CoverallRichErrorNoVariantData.TooManyPlainVariants) as cm: + throw_rich_error_no_variant_data() + self.assertEqual(len(cm.exception.args), 0) + self.assertEqual(str(cm.exception), "") # probably not ideal! + self.assertEqual(repr(cm.exception), "CoverallRichErrorNoVariantData.TooManyPlainVariants()") + def test_complex_errors(self): + # This is testing fields with variants which are exposed via the FFI. coveralls = Coveralls("test_complex_errors") # Test success @@ -110,16 +154,34 @@ def test_complex_errors(self): coveralls.maybe_throw_complex(1) self.assertEqual(cm.exception.code, 10) self.assertEqual(cm.exception.extended_code, 20) - self.assertEqual(str(cm.exception), "ComplexError.OsError(code=10, extended_code=20)") + self.assertEqual(str(cm.exception), "code=10, extended_code=20") + self.assertEqual(repr(cm.exception), "ComplexError.OsError(code=10, extended_code=20)") + + with self.assertRaises(ComplexMacroError.OsError) as cm: + throw_complex_macro_error() + self.assertEqual(cm.exception.code, 1) + self.assertEqual(cm.exception.extended_code, 2) + self.assertEqual(str(cm.exception), "code=1, extended_code=2") + self.assertEqual(repr(cm.exception), "ComplexMacroError.OsError(code=1, extended_code=2)") with self.assertRaises(ComplexError.PermissionDenied) as cm: coveralls.maybe_throw_complex(2) self.assertEqual(cm.exception.reason, "Forbidden") - self.assertEqual(str(cm.exception), "ComplexError.PermissionDenied(reason='Forbidden')") + self.assertEqual(str(cm.exception), "reason='Forbidden'") + self.assertEqual(repr(cm.exception), "ComplexError.PermissionDenied(reason='Forbidden')") + + with self.assertRaises(ComplexError.UnknownError) as cm: + coveralls.maybe_throw_complex(3) + self.assertEqual(str(cm.exception), "") + self.assertEqual(repr(cm.exception), "ComplexError.UnknownError()") # Test panics, which should cause InternalError to be raised with self.assertRaises(InternalError) as cm: - coveralls.maybe_throw_complex(3) + coveralls.maybe_throw_complex(4) + + def test_enums(self): + e = get_simple_flat_macro_enum(0) + self.assertTrue(isinstance(e, SimpleFlatMacroEnum.FIRST)) def test_self_by_arc(self): coveralls = Coveralls("test_self_by_arc") @@ -212,5 +274,25 @@ def test_dict_with_non_string_keys(self): dict3 = coveralls.get_dict3(key=31, value=42) assert dict3[31] == 42 + def test_bytes(self): + coveralls = Coveralls("test_bytes") + self.assertEqual(coveralls.reverse(b"123"), b"321") + +class TraitsTest(unittest.TestCase): + def test_simple(self): + traits = get_traits() + self.assertEqual(traits[0].name(), "trait 1") + self.assertEqual(traits[0].number(), 1) + self.assertEqual(traits[0].strong_count(), 2) + + self.assertEqual(traits[1].name(), "trait 2") + self.assertEqual(traits[1].number(), 2) + self.assertEqual(traits[1].strong_count(), 2) + + traits[0].take_other(traits[1]) + self.assertEqual(traits[1].strong_count(), 3) + self.assertEqual(traits[0].get_other().name(), "trait 2") + traits[0].take_other(None) + if __name__=='__main__': unittest.main() diff --git a/compatibility-test/tests/swift/test_coverall.swift b/compatibility-test/tests/swift/test_coverall.swift index e24103a..d380881 100644 --- a/compatibility-test/tests/swift/test_coverall.swift +++ b/compatibility-test/tests/swift/test_coverall.swift @@ -26,6 +26,8 @@ do { let d = createSomeDict() assert(d.text == "text") assert(d.maybeText == "maybe_text") + assert(d.someBytes == Data("some_bytes".utf8)) + assert(d.maybeSomeBytes == Data("maybe_some_bytes".utf8)) assert(d.aBool) assert(d.maybeABool == false); assert(d.unsigned8 == 1) @@ -45,6 +47,32 @@ do { assert(d.coveralls!.getName() == "some_dict") } +// Test none_dict(). +do { + let d = createNoneDict() + assert(d.text == "text") + assert(d.maybeText == nil) + assert(d.someBytes == Data("some_bytes".utf8)) + assert(d.maybeSomeBytes == nil) + assert(d.aBool) + assert(d.maybeABool == nil); + assert(d.unsigned8 == 1) + assert(d.maybeUnsigned8 == nil) + assert(d.unsigned16 == 3) + assert(d.maybeUnsigned16 == nil) + assert(d.unsigned64 == 18446744073709551615) + assert(d.maybeUnsigned64 == nil) + assert(d.signed8 == 8) + assert(d.maybeSigned8 == nil) + assert(d.signed64 == 9223372036854775807) + assert(d.maybeSigned64 == nil) + assert(d.float32.almostEquals(1.2345)) + assert(d.maybeFloat32 == nil) + assert(d.float64.almostEquals(0.0)) + assert(d.maybeFloat64 == nil) + assert(d.coveralls == nil) +} + // Test arcs. do { let coveralls = Coveralls(name: "test_arcs") @@ -134,6 +162,17 @@ do { do { let _ = try coveralls.maybeThrowComplex(input: 3) fatalError("should have thrown") + } catch let e as ComplexError { + if case .UnknownError = e { + } else { + fatalError("wrong error variant: \(e)") + } + assert(String(describing: e) == "UnknownError", "Unexpected ComplexError.UnknownError description: \(e)") + } + + do { + let _ = try coveralls.maybeThrowComplex(input: 4) + fatalError("should have thrown") } catch { assert(String(describing: error) == "rustPanic(\"Invalid input\")") } @@ -202,3 +241,9 @@ do { coveralls.addRepair(repair: Repair(when: Date.init(), patch: Patch(color: Color.blue))) assert(coveralls.getRepairs().count == 2) } + +// Test bytes +do { + let coveralls = Coveralls(name: "test_bytes") + assert(coveralls.reverse(value: Data("123".utf8)) == Data("321".utf8)) +} diff --git a/compatibility-test/uniffi.toml b/compatibility-test/uniffi.toml deleted file mode 100644 index 8af8c34..0000000 --- a/compatibility-test/uniffi.toml +++ /dev/null @@ -1,2 +0,0 @@ -[bindings.csharp] -cdylib_name = "uniffi_coverall" diff --git a/test_generators.sh b/test_generators.sh index 68115a1..b656517 100755 --- a/test_generators.sh +++ b/test_generators.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -euo pipefail +set -euxo pipefail # Run compatibility tests for all generators @@ -54,10 +54,11 @@ TMP_DIR="$ROOT_DIR/compatibility-test/tmp" # Build test library: function build_docker() { - docker run --rm \ + docker run --rm -it \ + -v $HOME/.cargo/registry:/usr/local/cargo/registry \ -v $ROOT_DIR:/workspace \ -w /workspace \ - rust:1.64.0-slim-bullseye \ + rust:1.72-bullseye \ $* } @@ -74,24 +75,25 @@ fi # Generate bindings for all languages: function bindings_docker() { - docker run --rm \ + docker run --rm -it \ -v $ROOT_DIR:/workspace \ -w /workspace/compatibility-test \ generators:test \ $* } -UDL_FILE="src/coverall.udl" -bindings_docker uniffi-bindgen generate $UDL_FILE --language python --out-dir "tmp/python" -bindings_docker uniffi-bindgen generate $UDL_FILE --language kotlin --out-dir "tmp/kotlin" -bindings_docker uniffi-bindgen generate $UDL_FILE --language swift --out-dir "tmp/swift" -bindings_docker uniffi-bindgen-cs $UDL_FILE --out-dir "tmp/cs" --config="uniffi.toml" -bindings_docker uniffi-bindgen-go $UDL_FILE --out-dir "tmp/go" - +LIBRARY="/workspace/target/debug/libuniffi_coverall.so" +rm -rf compatibility-test/tmp +bindings_docker uniffi-bindgen generate $LIBRARY --library --language python --out-dir "tmp/python" +bindings_docker uniffi-bindgen generate $LIBRARY --library --language kotlin --out-dir "tmp/kotlin" +bindings_docker uniffi-bindgen generate $LIBRARY --library --language swift --out-dir "tmp/swift" +bindings_docker uniffi-bindgen-cs $LIBRARY --library --out-dir "tmp/cs" +bindings_docker uniffi-bindgen-go $LIBRARY --library --out-dir "tmp/go" +bindings_docker uniffi-bindgen-cpp $LIBRARY --library --out-dir "tmp/cpp" # Python tests: function python_docker() { - docker run --rm \ + docker run --rm -it \ -v $ROOT_DIR:/workspace \ -w /workspace/compatibility-test/tmp/python \ python:3.10-slim-bookworm \ @@ -105,7 +107,7 @@ python_docker python3 -m unittest discover -v # Kotlin tests: function kotlin_docker() { - docker run --rm \ + docker run --rm -it \ -v $ROOT_DIR:/workspace \ -w /workspace/compatibility-test/tmp/kotlin \ -e LD_LIBRARY_PATH=/workspace/target/debug \ @@ -121,7 +123,7 @@ kotlin_docker kotlinc -Werror -classpath ".:jna.jar:coverall.jar" -J-ea -script # Swift tests: function swift_docker() { - docker run --rm \ + docker run --rm -it \ -v $ROOT_DIR:/workspace \ -w /workspace/compatibility-test/tmp/swift \ -e LD_LIBRARY_PATH=/workspace/target/debug \ @@ -142,7 +144,7 @@ swift_docker swift -I . -L . -ltestmod -luniffi_coverall -Xcc -fmodule-map-file= # C# tests: function cs_docker() { - docker run --rm \ + docker run --rm -it \ -v $ROOT_DIR:/workspace \ -w /workspace/compatibility-test/tmp/cs \ -e LD_LIBRARY_PATH=/workspace/target/debug \ @@ -156,7 +158,7 @@ cs_docker dotnet test -l "console;verbosity=normal" # Go tests: function go_docker() { - docker run --rm \ + docker run --rm -it \ -v $ROOT_DIR:/workspace \ -w /workspace/compatibility-test/tmp/go \ -e CGO_ENABLED=1 \ @@ -169,6 +171,19 @@ function go_docker() { cp $TESTS_DIR/go/* $TMP_DIR/go go_docker go test -v +# C++ tests: +function cpp_docker() { + docker run --rm -it \ + -v $ROOT_DIR:/workspace \ + -w /workspace/compatibility-test/tmp/cpp \ + -e LD_LIBRARY_PATH=/workspace/target/debug \ + gcc:10-bullseye \ + $* +} + +cp $TESTS_DIR/cpp/* $TMP_DIR/cpp +cpp_docker g++ -std=c++20 test_coverall.cpp -o test_coverall +cpp_docker ./test_coverall # Clean up: rm -rf $TMP_DIR diff --git a/uniffi-bindgen/Cargo.toml b/uniffi-bindgen/Cargo.toml index 15783e6..b67f17d 100644 --- a/uniffi-bindgen/Cargo.toml +++ b/uniffi-bindgen/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "uniffi-bindgen" -version = "0.23.0" +version = "0.25.0" edition = "2021" [dependencies] -uniffi = { git = "https://github.com/NordSecurity/uniffi-rs.git", tag = "v0.23.0-3", features = ["cli"] } +uniffi = { git = "https://github.com/NordSecurity/uniffi-rs.git", tag = "v0.25.0-1", features = ["cli"] }