diff --git a/Cargo.lock b/Cargo.lock index 38bf49c3f90..41eb8fd4d7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,9 +159,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.95" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "anymap2" @@ -212,43 +212,44 @@ checksum = "9dbc3a507a82b17ba0d98f6ce8fd6954ea0c8152e98009d36a40d8dcc8ce078a" [[package]] name = "askama" -version = "0.12.1" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" dependencies = [ "askama_derive", - "askama_escape", + "itoa", + "percent-encoding", + "serde", + "serde_json", ] [[package]] name = "askama_derive" -version = "0.12.5" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" dependencies = [ "askama_parser", "basic-toml", - "mime", - "mime_guess", + "memchr", "proc-macro2", "quote", + "rustc-hash 2.0.0", "serde", + "serde_derive", "syn", ] -[[package]] -name = "askama_escape" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" - [[package]] name = "askama_parser" -version = "0.2.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" dependencies = [ - "nom", + "memchr", + "serde", + "serde_derive", + "winnow 0.7.11", ] [[package]] @@ -498,15 +499,6 @@ dependencies = [ "wiremock", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -635,16 +627,16 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.15.4" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" dependencies = [ "camino", "cargo-platform", "semver", "serde", "serde_json", - "thiserror 1.0.63", + "thiserror 2.0.11", ] [[package]] @@ -877,6 +869,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -3094,6 +3096,7 @@ dependencies = [ "anyhow", "as_variant", "async-compat", + "console_error_panic_hook", "extension-trait", "eyeball-im", "futures-util", @@ -3133,6 +3136,14 @@ dependencies = [ "syn", ] +[[package]] +name = "matrix-sdk-ffi-web" +version = "0.1.0" +dependencies = [ + "matrix-sdk-ffi", + "uniffi", +] + [[package]] name = "matrix-sdk-indexeddb" version = "0.12.0" @@ -3369,16 +3380,6 @@ version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "515a63dc9666c865e848b043ab52fe9a5c713ae89cde4b5fbaae67cfd614b93a" -[[package]] -name = "mime_guess" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "minicov" version = "0.3.7" @@ -4660,7 +4661,6 @@ version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ - "log", "once_cell", "ring", "rustls-pki-types", @@ -4796,7 +4796,6 @@ dependencies = [ "httpdate", "native-tls", "reqwest", - "rustls", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -4804,7 +4803,6 @@ dependencies = [ "sentry-tracing", "tokio", "ureq", - "webpki-roots", ] [[package]] @@ -5576,7 +5574,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.20", ] [[package]] @@ -5824,17 +5822,18 @@ checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "uniffi" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31bff6daf87277a9014bcdefbc2842b0553392919d1096843c5aad899ca4588" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", "camino", + "cargo_metadata", "clap", "uniffi_bindgen", "uniffi_build", "uniffi_core", "uniffi_macros", + "uniffi_pipeline", ] [[package]] @@ -5846,9 +5845,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96061d7e01b185aa405f7c9b134741ab3e50cc6796a47d6fd8ab9a5364b5feed" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", "askama", @@ -5858,60 +5856,58 @@ dependencies = [ "glob", "goblin", "heck", + "indexmap", "once_cell", - "paste", "serde", + "tempfile", "textwrap", "toml 0.5.11", + "uniffi_internal_macros", "uniffi_meta", + "uniffi_pipeline", "uniffi_testing", "uniffi_udl", ] [[package]] name = "uniffi_build" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6b86f9b221046af0c533eafe09ece04e2f1ded04ccdc9bba0ec09aec1c52bd" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", "camino", "uniffi_bindgen", ] -[[package]] -name = "uniffi_checksum_derive" -version = "0.28.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "802d2051a700e3ec894c79f80d2705b69d85844dafbbe5d1a92776f8f48b563a" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "uniffi_core" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3210d57d6ab6065ab47a2898dacdb7c606fd6a4156196831fa3bf82e34ac58a6" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", "async-compat", "bytes", - "camino", - "log", "once_cell", - "paste", "static_assertions", ] +[[package]] +name = "uniffi_internal_macros" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" +dependencies = [ + "anyhow", + "indexmap", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "uniffi_macros" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58691741080935437dc862122e68d7414432a11824ac1137868de46181a0bd2" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ - "bincode", "camino", "fs-err", "once_cell", @@ -5925,21 +5921,31 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7663eacdbd9fbf4a88907ddcfe2e6fa85838eb6dc2418a7d91eebb3786f8e20b" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", - "bytes", "siphasher", - "uniffi_checksum_derive", + "uniffi_internal_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_pipeline" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "tempfile", + "uniffi_internal_macros", ] [[package]] name = "uniffi_testing" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f922465f7566f25f8fe766920205fdfa9a3fcdc209c6bfb7557f0b5bf45b04dd" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", "camino", @@ -5950,14 +5956,12 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cef408229a3a407fafa4c36dc4f6ece78a6fb258ab28d2b64bddd49c8cb680f6" +version = "0.29.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "anyhow", "textwrap", "uniffi_meta", - "uniffi_testing", "weedle2", ] @@ -5987,10 +5991,7 @@ dependencies = [ "log", "native-tls", "once_cell", - "rustls", - "rustls-pki-types", "url", - "webpki-roots", ] [[package]] @@ -6280,8 +6281,7 @@ dependencies = [ [[package]] name = "weedle2" version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" +source = "git+https://github.com/mozilla/uniffi-rs?rev=c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f#c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" dependencies = [ "nom", ] @@ -6588,6 +6588,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +dependencies = [ + "memchr", +] + [[package]] name = "wiremock" version = "0.6.2" @@ -6664,11 +6673,14 @@ checksum = "88301b56c26dd9bf5c43d858538f82d6f3f7764767defbc5d34e59459901c41a" name = "xtask" version = "0.1.0" dependencies = [ + "anyhow", "camino", + "cargo_metadata", "clap", "fs_extra", "serde", "serde_json", + "toml 0.5.11", "uniffi_bindgen", "xshell", ] diff --git a/Cargo.toml b/Cargo.toml index 7d902ec41bd..cf685de77dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "benchmarks", "bindings/matrix-sdk-crypto-ffi", "bindings/matrix-sdk-ffi", + "bindings/matrix-sdk-ffi-web", "crates/*", "examples/*", "labs/*", @@ -94,8 +95,9 @@ tracing = { version = "0.1.40", default-features = false, features = ["std"] } tracing-core = "0.1.32" tracing-subscriber = "0.3.18" unicode-normalization = "0.1.24" -uniffi = { version = "0.28.0" } -uniffi_bindgen = { version = "0.28.0" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "c7f6caa3d1bf20f934346cefd8e82b5093f0dc6f" } url = "2.5.4" uuid = "1.12.1" vodozemac = { version = "0.9.0", features = ["insecure-pk-encryption"] } diff --git a/bindings/matrix-sdk-ffi-web/Cargo.toml b/bindings/matrix-sdk-ffi-web/Cargo.toml new file mode 100644 index 00000000000..d8f11e8bfd5 --- /dev/null +++ b/bindings/matrix-sdk-ffi-web/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "matrix-sdk-ffi-web" +version = "0.1.0" +edition = "2021" + +[dependencies] +matrix-sdk-ffi = { path = "../matrix-sdk-ffi/", features = ["js"] } +uniffi = { workspace = true } + +[build-dependencies] +uniffi = { workspace = true, features = ["build"] } + +[dev-dependencies] +uniffi = { workspace = true, features = ["bindgen-tests"] } + +[lib] +crate-type = ["lib", "staticlib", "cdylib"] diff --git a/bindings/matrix-sdk-ffi-web/src/lib.rs b/bindings/matrix-sdk-ffi-web/src/lib.rs new file mode 100644 index 00000000000..76861103124 --- /dev/null +++ b/bindings/matrix-sdk-ffi-web/src/lib.rs @@ -0,0 +1 @@ +pub use matrix_sdk_ffi; diff --git a/bindings/matrix-sdk-ffi/Cargo.toml b/bindings/matrix-sdk-ffi/Cargo.toml index 19854168745..4755644b540 100644 --- a/bindings/matrix-sdk-ffi/Cargo.toml +++ b/bindings/matrix-sdk-ffi/Cargo.toml @@ -14,17 +14,17 @@ publish = false release = true [lib] -crate-type = ["cdylib", "staticlib"] +crate-type = ["lib", "cdylib", "staticlib"] [features] default = ["bundled-sqlite", "unstable-msc4274"] bundled-sqlite = ["matrix-sdk/bundled-sqlite"] unstable-msc4274 = ["matrix-sdk-ui/unstable-msc4274"] +js = [] [dependencies] anyhow.workspace = true as_variant.workspace = true -async-compat = "0.2.4" extension-trait = "1.0.1" eyeball-im.workspace = true futures-util.workspace = true @@ -36,35 +36,18 @@ matrix-sdk-ui = { workspace = true, features = ["uniffi"] } mime = "0.3.16" once_cell.workspace = true ruma = { workspace = true, features = ["html", "unstable-unspecified", "unstable-msc3488", "compat-unset-avatar", "unstable-msc3245-v1-compat", "unstable-msc4278"] } -sentry-tracing = "0.36.0" serde.workspace = true serde_json.workspace = true thiserror.workspace = true -tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } tracing.workspace = true tracing-appender = { version = "0.2.2" } tracing-core.workspace = true tracing-subscriber = { workspace = true, features = ["env-filter"] } -uniffi = { workspace = true, features = ["tokio"] } url.workspace = true uuid = { version = "1.4.1", features = ["v4"] } zeroize.workspace = true -[target.'cfg(not(target_os = "android"))'.dependencies.matrix-sdk] -workspace = true -features = [ - "anyhow", - "e2e-encryption", - "experimental-widgets", - "markdown", - # note: differ from block below - "native-tls", - "socks", - "sqlite", - "uniffi", -] - -[target.'cfg(not(target_os = "android"))'.dependencies.sentry] +[target.'cfg(all(not(target_os = "android"), not(target_family = "wasm")))'.dependencies.sentry] version = "0.36.0" default-features = false features = [ @@ -80,6 +63,17 @@ features = [ [target.'cfg(target_os = "android")'.dependencies] paranoid-android = "0.2.1" +[target.'cfg(target_family = "wasm")'.dependencies] +console_error_panic_hook = "0.1.7" +tokio = { workspace = true, features = ["sync", "macros"] } +uniffi = { workspace = true, features = ["wasm-unstable-single-threaded"] } + +[target.'cfg(not(target_family = "wasm"))'.dependencies] +async-compat.workspace = true +sentry-tracing = "0.36.0" +tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } +uniffi = { workspace = true, features = ["tokio"] } + [target.'cfg(target_os = "android")'.dependencies.matrix-sdk] workspace = true features = [ @@ -94,19 +88,34 @@ features = [ "uniffi", ] -[target.'cfg(target_os = "android")'.dependencies.sentry] -version = "0.36.0" -default-features = false +[target.'cfg(all(not(target_os = "android"), not(target_family = "wasm")))'.dependencies.matrix-sdk] +workspace = true features = [ - # TLS lib specific for Android. - "rustls", - # Most default features enabled otherwise. - "backtrace", - "contexts", - "panic", - "reqwest", + "anyhow", + "e2e-encryption", + "experimental-widgets", + "markdown", + # note: differ from block above + "native-tls", + "socks", + "sqlite", + "uniffi", +] + +[target.'cfg(target_family = "wasm")'.dependencies.matrix-sdk] +workspace = true +features = [ + "anyhow", + "e2e-encryption", + "experimental-widgets", + "markdown", + "native-tls", + "socks", + "indexeddb", + "uniffi", ] + [build-dependencies] uniffi = { workspace = true, features = ["build"] } vergen = { version = "8.1.3", features = ["build", "git", "gitcl"] } diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl index c7caa1afb0b..c5fa1c1ffbb 100644 --- a/bindings/matrix-sdk-ffi/src/api.udl +++ b/bindings/matrix-sdk-ffi/src/api.udl @@ -1,10 +1,12 @@ namespace matrix_sdk_ffi {}; +[Remote] dictionary Mentions { sequence user_ids; boolean room; }; +[Remote] interface RoomMessageEventContentWithoutRelation { RoomMessageEventContentWithoutRelation with_mentions(Mentions mentions); }; diff --git a/bindings/matrix-sdk-ffi/src/client.rs b/bindings/matrix-sdk-ffi/src/client.rs index cb6dac3c7ed..2dabe08871c 100644 --- a/bindings/matrix-sdk-ffi/src/client.rs +++ b/bindings/matrix-sdk-ffi/src/client.rs @@ -6,17 +6,18 @@ use std::{ time::Duration, }; -use anyhow::{anyhow, Context as _}; +use anyhow::{anyhow, Context}; use futures_util::pin_mut; +#[cfg(not(any(target_family = "wasm", feature = "js")))] +use matrix_sdk::media::MediaFileHandle as SdkMediaFileHandle; +#[cfg(not(target_family = "wasm"))] +use matrix_sdk::STATE_STORE_DATABASE_NAME; use matrix_sdk::{ authentication::oauth::{ AccountManagementActionFull, ClientId, OAuthAuthorizationData, OAuthSession, }, event_cache::EventCacheError, - media::{ - MediaFileHandle as SdkMediaFileHandle, MediaFormat, MediaRequestParameters, - MediaRetentionPolicy, MediaThumbnailSettings, - }, + media::{MediaFormat, MediaRequestParameters, MediaRetentionPolicy, MediaThumbnailSettings}, ruma::{ api::client::{ discovery::get_authorization_server_metadata::msc2965::Prompt as RumaOidcPrompt, @@ -38,7 +39,6 @@ use matrix_sdk::{ sliding_sync::Version as SdkSlidingSyncVersion, store::RoomLoadSettings as SdkRoomLoadSettings, AuthApi, AuthSession, Client as MatrixClient, SessionChange, SessionTokens, - STATE_STORE_DATABASE_NAME, }; use matrix_sdk_common::{stream::StreamExt, SendOutsideWasm, SyncOutsideWasm}; use matrix_sdk_ui::{ @@ -498,22 +498,35 @@ impl Client { use_cache: bool, temp_dir: Option, ) -> Result, ClientError> { - let source = (*media_source).clone(); - let mime_type: mime::Mime = mime_type.parse()?; + #[cfg(any(target_family = "wasm", feature = "js"))] + { + return Err(ClientError::Generic { + msg: "get_media_file is not supported on wasm32".to_string(), + details: None, + }); + } + #[cfg(not(any(target_family = "wasm", feature = "js")))] + { + let source = (*media_source).clone(); + let mime_type: mime::Mime = mime_type.parse()?; - let handle = self - .inner - .media() - .get_media_file( - &MediaRequestParameters { source: source.media_source, format: MediaFormat::File }, - filename, - &mime_type, - use_cache, - temp_dir, - ) - .await?; + let handle = self + .inner + .media() + .get_media_file( + &MediaRequestParameters { + source: source.media_source, + format: MediaFormat::File, + }, + filename, + &mime_type, + use_cache, + temp_dir, + ) + .await?; - Ok(Arc::new(MediaFileHandle::new(handle))) + Ok(Arc::new(MediaFileHandle::new(handle))) + } } /// Restores the client from a `Session`. @@ -735,7 +748,7 @@ impl Client { impl Client { /// Whether or not the client's homeserver supports the password login flow. - pub(crate) async fn supports_password_login(&self) -> anyhow::Result { + pub(crate) async fn supports_password_login(&self) -> Result { let login_types = self.inner.matrix_auth().get_login_types().await?; let supports_password = login_types .flows @@ -882,7 +895,7 @@ impl Client { .account() .set_display_name(Some(name.as_str())) .await - .context("Unable to set display name")?; + .map_err(|e| anyhow!("Unable to set display name: {}", e))?; Ok(()) } @@ -1432,56 +1445,62 @@ impl Client { /// - This will empty the media cache according to the current media /// retention policy. pub async fn clear_caches(&self) -> Result<(), ClientError> { - let closure = async || -> Result<_, ClientError> { - // Clean up the media cache according to the current media retention policy. - self.inner - .event_cache_store() - .lock() - .await - .map_err(EventCacheError::from)? - .clean_up_media_cache() - .await - .map_err(EventCacheError::from)?; - - // Clear all the room chunks. It's important to *not* call - // `EventCacheStore::clear_all_linked_chunks` here, because there might be live - // observers of the linked chunks, and that would cause some very bad state - // mismatch. - self.inner.event_cache().clear_all_rooms().await?; - - // Delete the state store file, if it exists. - if let Some(store_path) = &self.store_path { - debug!("Removing the state store: {}", store_path.display()); - - // The state store and the crypto store both live in the same store path, so we - // can't blindly delete the directory. - // - // Delete the state store SQLite file, as well as the write-ahead log (WAL) and - // shared-memory (SHM) files, if they exist. - - for file_name in [ - PathBuf::from(STATE_STORE_DATABASE_NAME), - PathBuf::from(format!("{STATE_STORE_DATABASE_NAME}.wal")), - PathBuf::from(format!("{STATE_STORE_DATABASE_NAME}.shm")), - ] { - let file_path = store_path.join(file_name); - if file_path.exists() { - debug!("Removing file: {}", file_path.display()); - std::fs::remove_file(&file_path).map_err(|err| ClientError::Generic { - msg: format!( - "couldn't delete the state store file {}: {err}", - file_path.display() - ), - details: None, - })?; + #[cfg(not(target_family = "wasm"))] + { + let closure = async || -> Result<_, ClientError> { + // Clean up the media cache according to the current media retention policy. + self.inner + .event_cache_store() + .lock() + .await + .map_err(EventCacheError::from)? + .clean_up_media_cache() + .await + .map_err(EventCacheError::from)?; + + // Clear all the room chunks. It's important to *not* call + // `EventCacheStore::clear_all_rooms_chunks` here, because there might be live + // observers of the linked chunks, and that would cause some very bad state + // mismatch. + self.inner.event_cache().clear_all_rooms().await?; + + // Delete the state store file, if it exists. + if let Some(store_path) = &self.store_path { + debug!("Removing the state store: {}", store_path.display()); + + // The state store and the crypto store both live in the same store path, so we + // can't blindly delete the directory. + // + // Delete the state store SQLite file, as well as the write-ahead log (WAL) and + // shared-memory (SHM) files, if they exist. + + for file_name in [ + PathBuf::from(STATE_STORE_DATABASE_NAME), + PathBuf::from(format!("{STATE_STORE_DATABASE_NAME}.wal")), + PathBuf::from(format!("{STATE_STORE_DATABASE_NAME}.shm")), + ] { + let file_path = store_path.join(file_name); + if file_path.exists() { + debug!("Removing file: {}", file_path.display()); + std::fs::remove_file(&file_path).map_err(|err| { + ClientError::Generic { + msg: format!( + "couldn't delete the state store file {}: {err}", + file_path.display() + ), + details: None, + } + })?; + } } } - } - Ok(()) - }; + Ok(()) + }; - closure().await + return closure().await; + } + Ok(()) } /// Checks if the server supports the report room API. @@ -2155,10 +2174,12 @@ fn gen_transaction_id() -> String { /// is dropped, the file will be removed from the disk. #[derive(uniffi::Object)] pub struct MediaFileHandle { + #[cfg(not(any(target_family = "wasm", feature = "js")))] inner: RwLock>, } impl MediaFileHandle { + #[cfg(not(any(target_family = "wasm", feature = "js")))] fn new(handle: SdkMediaFileHandle) -> Self { Self { inner: RwLock::new(Some(handle)) } } @@ -2168,7 +2189,8 @@ impl MediaFileHandle { impl MediaFileHandle { /// Get the media file's path. pub fn path(&self) -> Result { - Ok(self + #[cfg(not(any(target_family = "wasm", feature = "js")))] + return Ok(self .inner .read() .unwrap() @@ -2177,24 +2199,37 @@ impl MediaFileHandle { .path() .to_str() .unwrap() - .to_owned()) + .to_owned()); + #[cfg(any(target_family = "wasm", feature = "js"))] + return Err(ClientError::Generic { + msg: "MediaFileHandle is not supported on wasm".to_string(), + details: None, + }); } pub fn persist(&self, path: String) -> Result { - let mut guard = self.inner.write().unwrap(); - Ok( - match guard - .take() - .context("MediaFileHandle was already persisted")? - .persist(path.as_ref()) - { - Ok(_) => true, - Err(e) => { - *guard = Some(e.file); - false - } - }, - ) + #[cfg(not(any(target_family = "wasm", feature = "js")))] + { + let mut guard = self.inner.write().unwrap(); + return Ok( + match guard + .take() + .context("MediaFileHandle was already persisted")? + .persist(path.as_ref()) + { + Ok(_) => true, + Err(e) => { + *guard = Some(e.file); + false + } + }, + ); + } + #[cfg(any(target_family = "wasm", feature = "js"))] + return Err(ClientError::Generic { + msg: "MediaFileHandle is not supported on wasm".to_string(), + details: None, + }); } } diff --git a/bindings/matrix-sdk-ffi/src/client_builder.rs b/bindings/matrix-sdk-ffi/src/client_builder.rs index 460bc2edbc6..e764ce5509c 100644 --- a/bindings/matrix-sdk-ffi/src/client_builder.rs +++ b/bindings/matrix-sdk-ffi/src/client_builder.rs @@ -9,16 +9,20 @@ use matrix_sdk::{ }, encryption::{BackupDownloadStrategy, EncryptionSettings}, event_cache::EventCacheError, - reqwest::Certificate, ruma::{ServerName, UserId}, sliding_sync::{ Error as MatrixSlidingSyncError, VersionBuilder as MatrixSlidingSyncVersionBuilder, VersionBuilderError, }, Client as MatrixClient, ClientBuildError as MatrixClientBuildError, HttpError, IdParseError, - RumaApiError, SqliteStoreConfig, + RumaApiError, SendOutsideWasm, SyncOutsideWasm, }; -use matrix_sdk_common::{SendOutsideWasm, SyncOutsideWasm}; +#[cfg(not(target_family = "wasm"))] +use matrix_sdk::{ + reqwest::{Certificate, Proxy}, + SqliteStoreConfig, +}; +use matrix_sdk_common::runtime::get_runtime_handle; use ruma::api::error::{DeserializationError, FromHttpResponseError}; use tracing::{debug, error}; use zeroize::Zeroizing; @@ -577,56 +581,61 @@ impl ClientBuilder { pub async fn build(self: Arc) -> Result, ClientBuildError> { let builder = unwrap_or_clone_arc(self); let mut inner_builder = MatrixClient::builder(); + let store_path; if let Some(holder_name) = &builder.cross_process_store_locks_holder_name { inner_builder = inner_builder.cross_process_store_locks_holder_name(holder_name.clone()); } - let store_path = if let Some(session_paths) = &builder.session_paths { - // This is the path where both the state store and the crypto store will live. - let data_path = Path::new(&session_paths.data_path); - // This is the path where the event cache store will live. - let cache_path = Path::new(&session_paths.cache_path); - - debug!( - data_path = %data_path.to_string_lossy(), - event_cache_path = %cache_path.to_string_lossy(), - "Creating directories for data (state and crypto) and cache stores.", - ); - - fs::create_dir_all(data_path)?; - fs::create_dir_all(cache_path)?; + if let Some(session_paths) = &builder.session_paths { + #[cfg(target_family = "wasm")] + { + panic!("Session paths are not supported on wasm32."); + } + #[cfg(not(target_family = "wasm"))] + { + let data_path = Path::new(&session_paths.data_path); + store_path = Some(data_path.to_path_buf()); + let cache_path = Path::new(&session_paths.cache_path); + + debug!( + data_path = %data_path.to_string_lossy(), + cache_path = %cache_path.to_string_lossy(), + "Creating directories for data and cache stores.", + ); + + fs::create_dir_all(data_path)?; + fs::create_dir_all(cache_path)?; + + let mut sqlite_store_config = if builder.system_is_memory_constrained { + SqliteStoreConfig::with_low_memory_config(data_path) + } else { + SqliteStoreConfig::new(data_path) + }; - let mut sqlite_store_config = if builder.system_is_memory_constrained { - SqliteStoreConfig::with_low_memory_config(data_path) - } else { - SqliteStoreConfig::new(data_path) - }; + sqlite_store_config = + sqlite_store_config.passphrase(builder.session_passphrase.as_deref()); - sqlite_store_config = - sqlite_store_config.passphrase(builder.session_passphrase.as_deref()); + if let Some(size) = builder.session_pool_max_size { + sqlite_store_config = sqlite_store_config.pool_max_size(size); + } - if let Some(size) = builder.session_pool_max_size { - sqlite_store_config = sqlite_store_config.pool_max_size(size); - } + if let Some(size) = builder.session_cache_size { + sqlite_store_config = sqlite_store_config.cache_size(size); + } - if let Some(size) = builder.session_cache_size { - sqlite_store_config = sqlite_store_config.cache_size(size); - } + if let Some(limit) = builder.session_journal_size_limit { + sqlite_store_config = sqlite_store_config.journal_size_limit(limit); + } - if let Some(limit) = builder.session_journal_size_limit { - sqlite_store_config = sqlite_store_config.journal_size_limit(limit); + inner_builder = inner_builder + .sqlite_store_with_config_and_cache_path(sqlite_store_config, Some(cache_path)); } - - inner_builder = inner_builder - .sqlite_store_with_config_and_cache_path(sqlite_store_config, Some(cache_path)); - - Some(data_path.to_owned()) } else { debug!("Not using a store path."); - None - }; + store_path = None; + } // Determine server either from URL, server name or user ID. inner_builder = match builder.homeserver_cfg { @@ -650,48 +659,59 @@ impl ClientBuilder { } }; - let mut certificates = Vec::new(); + #[cfg(not(target_family = "wasm"))] + { + let mut certificates = Vec::new(); - for certificate in builder.additional_root_certificates { - // We don't really know what type of certificate we may get here, so let's try - // first one type, then the other. - match Certificate::from_der(&certificate) { - Ok(cert) => { - certificates.push(cert); - } - Err(der_error) => { - let cert = Certificate::from_pem(&certificate).map_err(|pem_error| { + for certificate in builder.additional_root_certificates { + // We don't really know what type of certificate we may get here, so let's try + // first one type, then the other. + match Certificate::from_der(&certificate) { + Ok(cert) => { + certificates.push(cert); + } + Err(der_error) => { + let cert = Certificate::from_pem(&certificate).map_err(|pem_error| { ClientBuildError::Generic { message: format!("Failed to add a root certificate as DER ({der_error:?}) or PEM ({pem_error:?})"), } })?; - certificates.push(cert); + certificates.push(cert); + } } } - } - inner_builder = inner_builder.add_root_certificates(certificates); - - if builder.disable_built_in_root_certificates { - inner_builder = inner_builder.disable_built_in_root_certificates(); - } - - if let Some(proxy) = builder.proxy { - inner_builder = inner_builder.proxy(proxy); - } + inner_builder = inner_builder.add_root_certificates(certificates); + if builder.disable_built_in_root_certificates { + inner_builder = inner_builder.disable_built_in_root_certificates(); + } + if let Some(proxy) = builder.proxy { + let Ok(proxy) = Proxy::all(proxy) else { + return Err(ClientBuildError::Generic { + message: "Proxy configuration is invalid.".to_owned(), + }); + }; + let Ok(http_client) = matrix_sdk::reqwest::Client::builder().proxy(proxy).build() + else { + return Err(ClientBuildError::Generic { + message: "Http client for proxy is invalid.".to_owned(), + }); + }; + inner_builder = inner_builder.http_client(http_client); + } + if builder.disable_ssl_verification { + inner_builder = inner_builder.disable_ssl_verification(); + } - if builder.disable_ssl_verification { - inner_builder = inner_builder.disable_ssl_verification(); + if let Some(user_agent) = builder.user_agent { + inner_builder = inner_builder.user_agent(user_agent); + } } if !builder.disable_automatic_token_refresh { inner_builder = inner_builder.handle_refresh_tokens(); } - if let Some(user_agent) = builder.user_agent { - inner_builder = inner_builder.user_agent(user_agent); - } - inner_builder = inner_builder .with_encryption_settings(builder.encryption_settings) .with_room_key_recipient_strategy(builder.room_key_recipient_strategy) diff --git a/bindings/matrix-sdk-ffi/src/platform.rs b/bindings/matrix-sdk-ffi/src/platform.rs index bf36b0c2491..f2759589734 100644 --- a/bindings/matrix-sdk-ffi/src/platform.rs +++ b/bindings/matrix-sdk-ffi/src/platform.rs @@ -340,6 +340,7 @@ impl TraceLogPacks { } } +#[cfg(not(target_family = "wasm"))] struct SentryLoggingCtx { /// The Sentry client guard, which keeps the Sentry context alive. _guard: sentry::ClientInitGuard, @@ -349,6 +350,7 @@ struct SentryLoggingCtx { } struct LoggingCtx { + #[cfg(not(target_family = "wasm"))] sentry: Option, } @@ -390,6 +392,7 @@ impl TracingConfiguration { log_panics::init(); // Prepare the Sentry layer, if a DSN is provided. + #[cfg(not(target_family = "wasm"))] let (sentry_layer, sentry_logging_ctx) = if let Some(sentry_dsn) = self.sentry_dsn.take() { // Initialize the Sentry client with the given options. let sentry_guard = sentry::init(( @@ -446,16 +449,21 @@ impl TracingConfiguration { let env_filter = build_tracing_filter(&self); - tracing_subscriber::registry() + let registry = tracing_subscriber::registry() .with(tracing_subscriber::EnvFilter::new(&env_filter)) - .with(crate::platform::text_layers(self)) - .with(sentry_layer) - .init(); + .with(crate::platform::text_layers(self)); + #[cfg(not(target_family = "wasm"))] + registry.with(sentry_layer).init(); + #[cfg(target_family = "wasm")] + registry.init(); // Log the log levels 🧠. tracing::info!(env_filter, "Logging has been set up"); - LoggingCtx { sentry: sentry_logging_ctx } + #[cfg(not(target_family = "wasm"))] + return LoggingCtx { sentry: sentry_logging_ctx }; + #[cfg(target_family = "wasm")] + LoggingCtx {} } } @@ -505,15 +513,22 @@ pub fn init_platform( config: TracingConfiguration, use_lightweight_tokio_runtime: bool, ) -> Result<(), ClientError> { - LOGGING.set(config.build()).map_err(|_| ClientError::Generic { - msg: "logger already initialized".to_owned(), - details: None, - })?; + #[cfg(target_family = "wasm")] + { + console_error_panic_hook::set_once(); + } - if use_lightweight_tokio_runtime { - setup_lightweight_tokio_runtime(); - } else { - setup_multithreaded_tokio_runtime(); + #[cfg(not(target_family = "wasm"))] + { + LOGGING.set(config.build()).map_err(|_| ClientError::Generic { + msg: "logger already initialized".to_owned(), + details: None, + })?; + if use_lightweight_tokio_runtime { + setup_lightweight_tokio_runtime(); + } else { + setup_multithreaded_tokio_runtime(); + } } Ok(()) @@ -524,6 +539,7 @@ pub fn init_platform( #[matrix_sdk_ffi_macros::export] pub fn enable_sentry_logging(enabled: bool) { if let Some(ctx) = LOGGING.get() { + #[cfg(not(target_family = "wasm"))] if let Some(sentry_ctx) = &ctx.sentry { sentry_ctx.enabled.store(enabled, std::sync::atomic::Ordering::SeqCst); } else { @@ -535,6 +551,7 @@ pub fn enable_sentry_logging(enabled: bool) { }; } +#[cfg(not(target_family = "wasm"))] fn setup_multithreaded_tokio_runtime() { async_compat::set_runtime_builder(Box::new(|| { eprintln!("spawning a multithreaded tokio runtime"); @@ -545,6 +562,7 @@ fn setup_multithreaded_tokio_runtime() { })); } +#[cfg(not(target_family = "wasm"))] fn setup_lightweight_tokio_runtime() { async_compat::set_runtime_builder(Box::new(|| { eprintln!("spawning a lightweight tokio runtime"); diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index d84e10efa88..7ad42e15e55 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -378,7 +378,7 @@ impl Timeline { Ok(handle) => Ok(Arc::new(SendHandle::new(handle))), Err(err) => { error!("error when sending a message: {err}"); - Err(anyhow::anyhow!(err).into()) + Err(err.into()) } } } @@ -531,10 +531,7 @@ impl Timeline { msg: Arc, reply_params: ReplyParameters, ) -> Result<(), ClientError> { - self.inner - .send_reply((*msg).clone(), reply_params.try_into()?) - .await - .map_err(|err| anyhow::anyhow!(err))?; + self.inner.send_reply((*msg).clone(), reply_params.try_into()?).await?; Ok(()) } @@ -634,7 +631,10 @@ impl Timeline { pub async fn fetch_details_for_event(&self, event_id: String) -> Result<(), ClientError> { let event_id = <&EventId>::try_from(event_id.as_str())?; - self.inner.fetch_details_for_event(event_id).await.context("Fetching event details")?; + self.inner + .fetch_details_for_event(event_id) + .await + .map_err(|_| ClientError::from_str("Fetching event details".to_string(), None))?; Ok(()) } @@ -1233,7 +1233,10 @@ impl SendAttachmentJoinHandle { return Ok(()); } error!("task panicked! resuming panic from here."); + #[cfg(not(target_family = "wasm"))] panic::resume_unwind(err.into_panic()); + #[cfg(target_family = "wasm")] + panic!("task panicked! {err}"); } } } diff --git a/bindings/matrix-sdk-ffi/uniffi.toml b/bindings/matrix-sdk-ffi/uniffi.toml index 92ed4de9c63..0284aee488f 100644 --- a/bindings/matrix-sdk-ffi/uniffi.toml +++ b/bindings/matrix-sdk-ffi/uniffi.toml @@ -1,4 +1,14 @@ [bindings.kotlin] package_name = "org.matrix.rustcomponents.sdk" cdylib_name = "matrix_sdk_ffi" -android_cleaner = true \ No newline at end of file +android_cleaner = true + +[bindings.typescript] +[bindings.typescript.customTypes.Date64] +typeName = "Date" +intoCustom = """((v: FfiType) => { + return new Date(Number(v)); +})({})""" +fromCustom = """((v: TsType) => { + return BigInt(v.getTime()); +})({})""" diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index c30927e1784..64af82c696b 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -41,7 +41,10 @@ sqlite = [ "matrix-sdk-sqlite?/event-cache", ] bundled-sqlite = ["sqlite", "matrix-sdk-sqlite?/bundled"] -indexeddb = ["matrix-sdk-indexeddb/state-store"] +indexeddb = [ + "dep:matrix-sdk-indexeddb", + "matrix-sdk-indexeddb/state-store" +] qrcode = ["e2e-encryption", "matrix-sdk-base/qrcode"] automatic-room-key-forwarding = ["e2e-encryption", "matrix-sdk-base/automatic-room-key-forwarding"] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 3e4f689c9aa..c94790abab9 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -13,10 +13,13 @@ name = "xtask" test = false [dependencies] +anyhow = "1.0.96" camino = "1.0.8" +cargo_metadata = "0.19.2" clap = { version = "4.0.18", features = ["derive"] } fs_extra = "1" serde = { workspace = true, features = ["derive"] } serde_json.workspace = true +toml = "0.5.11" uniffi_bindgen.workspace = true xshell = "0.2.2" diff --git a/xtask/src/config_supplier.rs b/xtask/src/config_supplier.rs new file mode 100644 index 00000000000..c85edbb6a77 --- /dev/null +++ b/xtask/src/config_supplier.rs @@ -0,0 +1,74 @@ +use std::{collections::HashMap, fs}; + +use anyhow::{bail, Context}; +use camino::Utf8PathBuf; +use cargo_metadata::Metadata; +use toml::value::Table; +use uniffi_bindgen::BindgenCrateConfigSupplier; + +#[derive(Debug, Clone, Default)] +pub struct CrateConfigSupplier { + paths: HashMap, +} + +fn load_toml_file(path: Option<&Utf8PathBuf>) -> anyhow::Result> { + if let Some(path) = path { + if path.exists() { + let contents = fs::read_to_string(path)?; + let table: Table = toml::from_str(&contents)?; + Ok(Some(table)) + } else { + Ok(None) + } + } else { + Ok(None) + } +} + +impl BindgenCrateConfigSupplier for CrateConfigSupplier { + fn get_toml(&self, crate_name: &str) -> anyhow::Result> { + load_toml_file(self.get_toml_path(crate_name).as_ref()) + } + + fn get_toml_path(&self, crate_name: &str) -> Option { + self.paths.get(crate_name).map(|p| p.join("uniffi.toml")) + } + + fn get_udl(&self, crate_name: &str, udl_name: &str) -> anyhow::Result { + let path = self + .paths + .get(crate_name) + .context(format!("No path known to UDL files for '{crate_name}'"))? + .join("src") + .join(format!("{udl_name}.udl")); + if path.exists() { + Ok(fs::read_to_string(path)?) + } else { + bail!(format!("No UDL file found at '{path}'")); + } + } +} + +impl From for CrateConfigSupplier { + fn from(metadata: Metadata) -> Self { + let paths: HashMap = metadata + .packages + .iter() + .flat_map(|p| { + p.targets + .iter() + .filter(|t| { + !t.is_bin() + && !t.is_example() + && !t.is_test() + && !t.is_bench() + && !t.is_custom_build() + }) + .filter_map(|t| { + p.manifest_path.parent().map(|p| (t.name.replace('-', "_"), p.to_owned())) + }) + }) + .collect(); + Self { paths } + } +} diff --git a/xtask/src/kotlin.rs b/xtask/src/kotlin.rs index 6ee768bce17..e13a5e3ddc0 100644 --- a/xtask/src/kotlin.rs +++ b/xtask/src/kotlin.rs @@ -1,11 +1,12 @@ use std::fs::create_dir_all; use camino::{Utf8Path, Utf8PathBuf}; +use cargo_metadata::MetadataCommand; use clap::{Args, Subcommand, ValueEnum}; use uniffi_bindgen::{bindings::KotlinBindingGenerator, library_mode::generate_bindings}; use xshell::cmd; -use crate::{sh, workspace, Result}; +use crate::{config_supplier::CrateConfigSupplier, sh, workspace, Result}; struct PackageValues { name: &'static str, @@ -121,7 +122,24 @@ fn build_android_library( fn generate_uniffi_bindings(library_path: &Utf8Path, ffi_generated_dir: &Utf8Path) -> Result<()> { println!("-- library_path = {library_path}"); - generate_bindings(library_path, None, &KotlinBindingGenerator, None, ffi_generated_dir, false)?; + let manifest_path = std::env::current_dir()?.join("Cargo.toml"); + println!("manifest path {:?}", manifest_path); + + // Get metadata using cargo_metadata + let metadata = MetadataCommand::new().manifest_path(&manifest_path).exec()?; + + // Convert the Metadata into a CrateConfigSupplier using From + let config_supplier = CrateConfigSupplier::from(metadata); + + generate_bindings( + library_path, + None, + &KotlinBindingGenerator, + &config_supplier, + None, + ffi_generated_dir, + false, + )?; Ok(()) } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 12f29df96c2..7254c951a3a 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,6 +1,7 @@ #![allow(unexpected_cfgs)] mod ci; +mod config_supplier; mod fixup; mod kotlin; mod release; diff --git a/xtask/src/swift.rs b/xtask/src/swift.rs index cf41e2600a6..4ec22bafce9 100644 --- a/xtask/src/swift.rs +++ b/xtask/src/swift.rs @@ -4,11 +4,12 @@ use std::{ }; use camino::{Utf8Path, Utf8PathBuf}; +use cargo_metadata::MetadataCommand; use clap::{Args, Subcommand}; use uniffi_bindgen::{bindings::SwiftBindingGenerator, library_mode::generate_bindings}; use xshell::cmd; -use crate::{sh, workspace, Result}; +use crate::{config_supplier::CrateConfigSupplier, sh, workspace, Result}; /// Builds the SDK for Swift as a Static Library or XCFramework. #[derive(Args)] @@ -168,7 +169,24 @@ fn build_library() -> Result<()> { } fn generate_uniffi(library_path: &Utf8Path, ffi_directory: &Utf8Path) -> Result<()> { - generate_bindings(library_path, None, &SwiftBindingGenerator, None, ffi_directory, false)?; + let manifest_path = std::env::current_dir()?.join("Cargo.toml"); + println!("manifest path {:?}", manifest_path); + + // Get metadata using cargo_metadata + let metadata = MetadataCommand::new().manifest_path(&manifest_path).exec()?; + + // Convert the Metadata into a CrateConfigSupplier using From + let config_supplier = CrateConfigSupplier::from(metadata); + + generate_bindings( + library_path, + None, + &SwiftBindingGenerator, + &config_supplier, + None, + ffi_directory, + false, + )?; Ok(()) }