1 use std::fmt::Debug;
2 use std::sync::Arc;
3
4 use mls_rs::{
5 client_builder::{self, WithGroupStateStorage},
6 identity::basic,
7 storage_provider::in_memory::InMemoryGroupStateStorage,
8 };
9 use mls_rs_crypto_openssl::OpensslCryptoProvider;
10
11 use self::group_state::{GroupStateStorage, GroupStateStorageAdapter};
12 use crate::Error;
13
14 pub mod group_state;
15
16 #[derive(Debug, Clone)]
17 pub(crate) struct ClientGroupStorage(Arc<dyn GroupStateStorage>);
18
19 impl From<Arc<dyn GroupStateStorage>> for ClientGroupStorage {
from(value: Arc<dyn GroupStateStorage>) -> Self20 fn from(value: Arc<dyn GroupStateStorage>) -> Self {
21 Self(value)
22 }
23 }
24
25 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
26 #[cfg_attr(mls_build_async, maybe_async::must_be_async)]
27 impl mls_rs_core::group::GroupStateStorage for ClientGroupStorage {
28 type Error = Error;
29
state(&self, group_id: &[u8]) -> Result<Option<Vec<u8>>, Self::Error>30 async fn state(&self, group_id: &[u8]) -> Result<Option<Vec<u8>>, Self::Error> {
31 self.0.state(group_id.to_vec()).await
32 }
33
epoch(&self, group_id: &[u8], epoch_id: u64) -> Result<Option<Vec<u8>>, Self::Error>34 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).await
36 }
37
write( &mut self, state: mls_rs_core::group::GroupState, inserts: Vec<mls_rs_core::group::EpochRecord>, updates: Vec<mls_rs_core::group::EpochRecord>, ) -> Result<(), Self::Error>38 async fn write(
39 &mut self,
40 state: mls_rs_core::group::GroupState,
41 inserts: Vec<mls_rs_core::group::EpochRecord>,
42 updates: Vec<mls_rs_core::group::EpochRecord>,
43 ) -> Result<(), Self::Error> {
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
52 }
53
max_epoch_id(&self, group_id: &[u8]) -> Result<Option<u64>, Self::Error>54 async fn max_epoch_id(&self, group_id: &[u8]) -> Result<Option<u64>, Self::Error> {
55 self.0.max_epoch_id(group_id.to_vec()).await
56 }
57 }
58
59 pub type UniFFIConfig = client_builder::WithIdentityProvider<
60 basic::BasicIdentityProvider,
61 client_builder::WithCryptoProvider<
62 OpensslCryptoProvider,
63 WithGroupStateStorage<ClientGroupStorage, client_builder::BaseConfig>,
64 >,
65 >;
66
67 #[derive(Debug, Clone, uniffi::Record)]
68 pub struct ClientConfig {
69 pub group_state_storage: Arc<dyn GroupStateStorage>,
70 /// Use the ratchet tree extension. If this is false, then you
71 /// must supply `ratchet_tree` out of band to clients.
72 pub use_ratchet_tree_extension: bool,
73 }
74
75 impl Default for ClientConfig {
default() -> Self76 fn default() -> Self {
77 Self {
78 group_state_storage: Arc::new(GroupStateStorageAdapter::new(
79 InMemoryGroupStateStorage::new(),
80 )),
81 use_ratchet_tree_extension: true,
82 }
83 }
84 }
85
86 // TODO(mgeisler): turn into an associated function when UniFFI
87 // supports them: https://github.com/mozilla/uniffi-rs/issues/1074.
88 /// Create a client config with an in-memory group state storage.
89 #[uniffi::export]
client_config_default() -> ClientConfig90 pub fn client_config_default() -> ClientConfig {
91 ClientConfig::default()
92 }
93