Skip to content

Commit 2f69e73

Browse files
committed
[uniffi] Fix compilation under mls_build_async
UniFFI added support for async traits in mozilla/uniffi-rs#1981, but this is not yet released. This commit temporarily introduces a Git dependency on UniFFI to let us test the async functionality which was removed in awslabs#86. An unrelated UniFFI change (mozilla/uniffi-rs#1840) made our existing test fail.
1 parent 98cf9fe commit 2f69e73

File tree

7 files changed

+49
-21
lines changed

7 files changed

+49
-21
lines changed

mls-rs-uniffi/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ mls-rs = { version = "0.39.0", path = "../mls-rs" }
2121
mls-rs-core = { version = "0.18.0", path = "../mls-rs-core" }
2222
mls-rs-crypto-openssl = { version = "0.9.0", path = "../mls-rs-crypto-openssl" }
2323
thiserror = "1.0.57"
24-
uniffi = "0.26.0"
24+
uniffi = { git = "https://github.com/mozilla/uniffi-rs/", rev = "6b09f11", version = "0.26.0" }
2525

2626
[target.'cfg(mls_build_async)'.dependencies]
2727
tokio = { version = "1.36.0", features = ["sync"] }
2828

2929
[dev-dependencies]
30-
uniffi_bindgen = "0.26.0"
30+
uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs/", rev = "6b09f11", version = "0.26.0" }

mls-rs-uniffi/src/config.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ impl mls_rs_core::group::GroupStateStorage for ClientGroupStorage {
2828
type Error = Error;
2929

3030
async fn state(&self, group_id: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
31-
self.0.state(group_id.to_vec())
31+
self.0.state(group_id.to_vec()).await
3232
}
3333

3434
async fn epoch(&self, group_id: &[u8], epoch_id: u64) -> Result<Option<Vec<u8>>, Self::Error> {
35-
self.0.epoch(group_id.to_vec(), epoch_id)
35+
self.0.epoch(group_id.to_vec(), epoch_id).await
3636
}
3737

3838
async fn write(
@@ -41,16 +41,18 @@ impl mls_rs_core::group::GroupStateStorage for ClientGroupStorage {
4141
inserts: Vec<mls_rs_core::group::EpochRecord>,
4242
updates: Vec<mls_rs_core::group::EpochRecord>,
4343
) -> Result<(), Self::Error> {
44-
self.0.write(
45-
state.id,
46-
state.data,
47-
inserts.into_iter().map(Into::into).collect(),
48-
updates.into_iter().map(Into::into).collect(),
49-
)
44+
self.0
45+
.write(
46+
state.id,
47+
state.data,
48+
inserts.into_iter().map(Into::into).collect(),
49+
updates.into_iter().map(Into::into).collect(),
50+
)
51+
.await
5052
}
5153

5254
async fn max_epoch_id(&self, group_id: &[u8]) -> Result<Option<u64>, Self::Error> {
53-
self.0.max_epoch_id(group_id.to_vec())
55+
self.0.max_epoch_id(group_id.to_vec()).await
5456
}
5557
}
5658

mls-rs-uniffi/src/config/group_state.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use mls_rs::error::IntoAnyError;
22
use std::fmt::Debug;
3+
#[cfg(not(mls_build_async))]
34
use std::sync::Mutex;
5+
#[cfg(mls_build_async)]
6+
use tokio::sync::Mutex;
47

58
use crate::Error;
69

@@ -28,9 +31,13 @@ impl From<EpochRecord> for mls_rs_core::group::EpochRecord {
2831
}
2932
}
3033

31-
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
34+
// When building for async, uniffi::export has to be applied _after_
35+
// maybe-async's injection of the async trait. When building for sync,
36+
// the order has to be the opposite.
37+
#[cfg_attr(mls_build_async, uniffi::export(with_foreign))]
3238
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
33-
#[uniffi::export(with_foreign)]
39+
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
40+
#[cfg_attr(not(mls_build_async), uniffi::export(with_foreign))]
3441
pub trait GroupStateStorage: Send + Sync + Debug {
3542
async fn state(&self, group_id: Vec<u8>) -> Result<Option<Vec<u8>>, Error>;
3643
async fn epoch(&self, group_id: Vec<u8>, epoch_id: u64) -> Result<Option<Vec<u8>>, Error>;
@@ -59,9 +66,15 @@ impl<S> GroupStateStorageAdapter<S> {
5966
Self(Mutex::new(group_state_storage))
6067
}
6168

69+
#[cfg(not(mls_build_async))]
6270
fn inner(&self) -> std::sync::MutexGuard<'_, S> {
6371
self.0.lock().unwrap()
6472
}
73+
74+
#[cfg(mls_build_async)]
75+
async fn inner(&self) -> tokio::sync::MutexGuard<'_, S> {
76+
self.0.lock().await
77+
}
6578
}
6679

6780
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
@@ -73,13 +86,17 @@ where
7386
{
7487
async fn state(&self, group_id: Vec<u8>) -> Result<Option<Vec<u8>>, Error> {
7588
self.inner()
89+
.await
7690
.state(&group_id)
91+
.await
7792
.map_err(|err| err.into_any_error().into())
7893
}
7994

8095
async fn epoch(&self, group_id: Vec<u8>, epoch_id: u64) -> Result<Option<Vec<u8>>, Error> {
8196
self.inner()
97+
.await
8298
.epoch(&group_id, epoch_id)
99+
.await
83100
.map_err(|err| err.into_any_error().into())
84101
}
85102

@@ -91,17 +108,21 @@ where
91108
epoch_updates: Vec<EpochRecord>,
92109
) -> Result<(), Error> {
93110
self.inner()
111+
.await
94112
.write(
95113
mls_rs_core::group::GroupState { id, data },
96114
epoch_inserts.into_iter().map(Into::into).collect(),
97115
epoch_updates.into_iter().map(Into::into).collect(),
98116
)
117+
.await
99118
.map_err(|err| err.into_any_error().into())
100119
}
101120

102121
async fn max_epoch_id(&self, group_id: Vec<u8>) -> Result<Option<u64>, Error> {
103122
self.inner()
123+
.await
104124
.max_epoch_id(&group_id)
125+
.await
105126
.map_err(|err| err.into_any_error().into())
106127
}
107128
}

mls-rs-uniffi/src/lib.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ impl TryFrom<mls_rs::CipherSuite> for CipherSuite {
262262
/// See [`mls_rs::CipherSuiteProvider::signature_key_generate`]
263263
/// for details.
264264
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
265+
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
265266
#[uniffi::export]
266267
pub async fn generate_signature_keypair(
267268
cipher_suite: CipherSuite,
@@ -292,6 +293,7 @@ pub struct Client {
292293
}
293294

294295
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
296+
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
295297
#[uniffi::export]
296298
impl Client {
297299
/// Create a new client.
@@ -495,6 +497,7 @@ pub struct Group {
495497
}
496498

497499
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
500+
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
498501
impl Group {
499502
#[cfg(not(mls_build_async))]
500503
fn inner(&self) -> std::sync::MutexGuard<'_, mls_rs::Group<UniFFIConfig>> {
@@ -520,6 +523,7 @@ fn index_to_identity(
520523

521524
/// Extract the basic credential identifier from a from a key package.
522525
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
526+
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
523527
async fn signing_identity_to_identifier(
524528
signing_identity: &identity::SigningIdentity,
525529
) -> Result<Vec<u8>, Error> {
@@ -531,6 +535,7 @@ async fn signing_identity_to_identifier(
531535
}
532536

533537
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
538+
#[cfg_attr(mls_build_async, maybe_async::must_be_async)]
534539
#[uniffi::export]
535540
impl Group {
536541
/// Write the current state of the group to storage defined by
@@ -545,8 +550,9 @@ impl Group {
545550
/// This function is used to provide the current group tree to new
546551
/// members when `use_ratchet_tree_extension` is set to false in
547552
/// `ClientConfig`.
548-
pub fn export_tree(&self) -> Result<RatchetTree, Error> {
549-
self.inner().export_tree().try_into()
553+
pub async fn export_tree(&self) -> Result<RatchetTree, Error> {
554+
let group = self.inner().await;
555+
group.export_tree().try_into()
550556
}
551557

552558
/// Perform a commit of received proposals (or an empty commit).
@@ -703,8 +709,11 @@ impl Group {
703709

704710
#[cfg(test)]
705711
mod tests {
712+
#[cfg(not(mls_build_async))]
706713
use super::*;
714+
#[cfg(not(mls_build_async))]
707715
use crate::config::group_state::{EpochRecord, GroupStateStorage};
716+
#[cfg(not(mls_build_async))]
708717
use std::collections::HashMap;
709718

710719
#[test]

mls-rs-uniffi/tests/custom_storage_sync.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def max_epoch_id(self, group_id: bytes):
6262

6363

6464
group_state_storage = PythonGroupStateStorage()
65-
client_config = ClientConfig(group_state_storage,
65+
client_config = ClientConfig(group_state_storage=group_state_storage,
6666
use_ratchet_tree_extension=True)
6767

6868
key = generate_signature_keypair(CipherSuite.CURVE25519_AES128)

mls-rs-uniffi/tests/scenarios.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,5 @@ macro_rules! generate_python_tests {
4545
generate_python_tests!(generate_signature_keypair, None);
4646
generate_python_tests!(client_config_default_sync, None);
4747
generate_python_tests!(custom_storage_sync, None);
48-
49-
// TODO(mulmarta): it'll break if we use async trait which will be
50-
// supported in the next UniFFI release
51-
// TODO(mgeisler): add back simple_scenario_async
5248
generate_python_tests!(simple_scenario_sync, None);
5349
generate_python_tests!(ratchet_tree_sync, None);

mls-rs-uniffi/uniffi-bindgen/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ publish = false
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10-
uniffi = { version = "0.26.0", features = ["cli"] }
10+
uniffi = { git = "https://github.com/mozilla/uniffi-rs/", rev = "6b09f11", version = "0.26.0", features = ["cli"] }

0 commit comments

Comments
 (0)