• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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