1use crate::{
10 cipher_suite::CipherSuite,
11 client::Client,
12 client_config::ClientConfig,
13 extension::ExtensionType,
14 group::{
15 mls_rules::{DefaultMlsRules, MlsRules},
16 proposal::ProposalType,
17 },
18 identity::CredentialType,
19 identity::SigningIdentity,
20 protocol_version::ProtocolVersion,
21 psk::{ExternalPskId, PreSharedKey},
22 storage_provider::in_memory::{
23 InMemoryGroupStateStorage, InMemoryKeyPackageStorage, InMemoryPreSharedKeyStorage,
24 },
25 tree_kem::{Capabilities, Lifetime},
26 Sealed,
27};
28
29#[cfg(feature = "std")]
30use crate::time::MlsTime;
31
32use alloc::vec::Vec;
33
34#[cfg(feature = "sqlite")]
35use mls_rs_provider_sqlite::{
36 SqLiteDataStorageEngine, SqLiteDataStorageError,
37 {
38 connection_strategy::ConnectionStrategy,
39 storage::{SqLiteGroupStateStorage, SqLiteKeyPackageStorage, SqLitePreSharedKeyStorage},
40 },
41};
42
43#[cfg(feature = "private_message")]
44pub use crate::group::padding::PaddingMode;
45
46pub type BaseConfig = Config<
48 InMemoryKeyPackageStorage,
49 InMemoryPreSharedKeyStorage,
50 InMemoryGroupStateStorage,
51 Missing,
52 DefaultMlsRules,
53 Missing,
54>;
55
56pub type BaseInMemoryConfig = Config<
58 InMemoryKeyPackageStorage,
59 InMemoryPreSharedKeyStorage,
60 InMemoryGroupStateStorage,
61 Missing,
62 Missing,
63 Missing,
64>;
65
66pub type EmptyConfig = Config<Missing, Missing, Missing, Missing, Missing, Missing>;
67
68#[cfg(feature = "sqlite")]
70pub type BaseSqlConfig = Config<
71 SqLiteKeyPackageStorage,
72 SqLitePreSharedKeyStorage,
73 SqLiteGroupStateStorage,
74 Missing,
75 DefaultMlsRules,
76 Missing,
77>;
78
79#[derive(Debug)]
178pub struct ClientBuilder<C>(C);
179
180impl Default for ClientBuilder<BaseConfig> {
181 fn default() -> Self {
182 Self::new()
183 }
184}
185
186impl<C> ClientBuilder<C> {
187 pub(crate) fn from_config(c: C) -> Self {
188 Self(c)
189 }
190}
191
192impl ClientBuilder<BaseConfig> {
193 pub fn new() -> Self {
195 Self(Config(ConfigInner {
196 settings: Default::default(),
197 key_package_repo: Default::default(),
198 psk_store: Default::default(),
199 group_state_storage: Default::default(),
200 identity_provider: Missing,
201 mls_rules: DefaultMlsRules::new(),
202 crypto_provider: Missing,
203 signer: Default::default(),
204 signing_identity: Default::default(),
205 version: ProtocolVersion::MLS_10,
206 }))
207 }
208}
209
210impl ClientBuilder<EmptyConfig> {
211 pub fn new_empty() -> Self {
212 Self(Config(ConfigInner {
213 settings: Default::default(),
214 key_package_repo: Missing,
215 psk_store: Missing,
216 group_state_storage: Missing,
217 identity_provider: Missing,
218 mls_rules: Missing,
219 crypto_provider: Missing,
220 signer: Default::default(),
221 signing_identity: Default::default(),
222 version: ProtocolVersion::MLS_10,
223 }))
224 }
225}
226
227#[cfg(feature = "sqlite")]
228impl ClientBuilder<BaseSqlConfig> {
229 pub fn new_sqlite<CS: ConnectionStrategy>(
231 storage: SqLiteDataStorageEngine<CS>,
232 ) -> Result<Self, SqLiteDataStorageError> {
233 Ok(Self(Config(ConfigInner {
234 settings: Default::default(),
235 key_package_repo: storage.key_package_storage()?,
236 psk_store: storage.pre_shared_key_storage()?,
237 group_state_storage: storage.group_state_storage()?,
238 identity_provider: Missing,
239 mls_rules: DefaultMlsRules::new(),
240 crypto_provider: Missing,
241 signer: Default::default(),
242 signing_identity: Default::default(),
243 version: ProtocolVersion::MLS_10,
244 })))
245 }
246}
247
248impl<C: IntoConfig> ClientBuilder<C> {
249 pub fn extension_type(self, type_: ExtensionType) -> ClientBuilder<IntoConfigOutput<C>> {
251 self.extension_types(Some(type_))
252 }
253
254 pub fn extension_types<I>(self, types: I) -> ClientBuilder<IntoConfigOutput<C>>
256 where
257 I: IntoIterator<Item = ExtensionType>,
258 {
259 let mut c = self.0.into_config();
260 c.0.settings.extension_types.extend(types);
261 ClientBuilder(c)
262 }
263
264 pub fn custom_proposal_type(self, type_: ProposalType) -> ClientBuilder<IntoConfigOutput<C>> {
266 self.custom_proposal_types(Some(type_))
267 }
268
269 pub fn custom_proposal_types<I>(self, types: I) -> ClientBuilder<IntoConfigOutput<C>>
271 where
272 I: IntoIterator<Item = ProposalType>,
273 {
274 let mut c = self.0.into_config();
275 c.0.settings.custom_proposal_types.extend(types);
276 ClientBuilder(c)
277 }
278
279 pub fn protocol_version(self, version: ProtocolVersion) -> ClientBuilder<IntoConfigOutput<C>> {
284 self.protocol_versions(Some(version))
285 }
286
287 pub fn protocol_versions<I>(self, versions: I) -> ClientBuilder<IntoConfigOutput<C>>
292 where
293 I: IntoIterator<Item = ProtocolVersion>,
294 {
295 let mut c = self.0.into_config();
296 c.0.settings.protocol_versions.extend(versions);
297 ClientBuilder(c)
298 }
299
300 pub fn key_package_lifetime(self, duration_in_s: u64) -> ClientBuilder<IntoConfigOutput<C>> {
302 let mut c = self.0.into_config();
303 c.0.settings.lifetime_in_s = duration_in_s;
304 ClientBuilder(c)
305 }
306
307 pub fn key_package_repo<K>(self, key_package_repo: K) -> ClientBuilder<WithKeyPackageRepo<K, C>>
311 where
312 K: KeyPackageStorage,
313 {
314 let Config(c) = self.0.into_config();
315
316 ClientBuilder(Config(ConfigInner {
317 settings: c.settings,
318 key_package_repo,
319 psk_store: c.psk_store,
320 group_state_storage: c.group_state_storage,
321 identity_provider: c.identity_provider,
322 mls_rules: c.mls_rules,
323 crypto_provider: c.crypto_provider,
324 signer: c.signer,
325 signing_identity: c.signing_identity,
326 version: c.version,
327 }))
328 }
329
330 pub fn psk_store<P>(self, psk_store: P) -> ClientBuilder<WithPskStore<P, C>>
334 where
335 P: PreSharedKeyStorage,
336 {
337 let Config(c) = self.0.into_config();
338
339 ClientBuilder(Config(ConfigInner {
340 settings: c.settings,
341 key_package_repo: c.key_package_repo,
342 psk_store,
343 group_state_storage: c.group_state_storage,
344 identity_provider: c.identity_provider,
345 mls_rules: c.mls_rules,
346 crypto_provider: c.crypto_provider,
347 signer: c.signer,
348 signing_identity: c.signing_identity,
349 version: c.version,
350 }))
351 }
352
353 pub fn group_state_storage<G>(
357 self,
358 group_state_storage: G,
359 ) -> ClientBuilder<WithGroupStateStorage<G, C>>
360 where
361 G: GroupStateStorage,
362 {
363 let Config(c) = self.0.into_config();
364
365 ClientBuilder(Config(ConfigInner {
366 settings: c.settings,
367 key_package_repo: c.key_package_repo,
368 psk_store: c.psk_store,
369 group_state_storage,
370 identity_provider: c.identity_provider,
371 crypto_provider: c.crypto_provider,
372 mls_rules: c.mls_rules,
373 signer: c.signer,
374 signing_identity: c.signing_identity,
375 version: c.version,
376 }))
377 }
378
379 pub fn identity_provider<I>(
381 self,
382 identity_provider: I,
383 ) -> ClientBuilder<WithIdentityProvider<I, C>>
384 where
385 I: IdentityProvider,
386 {
387 let Config(c) = self.0.into_config();
388
389 ClientBuilder(Config(ConfigInner {
390 settings: c.settings,
391 key_package_repo: c.key_package_repo,
392 psk_store: c.psk_store,
393 group_state_storage: c.group_state_storage,
394 identity_provider,
395 mls_rules: c.mls_rules,
396 crypto_provider: c.crypto_provider,
397 signer: c.signer,
398 signing_identity: c.signing_identity,
399 version: c.version,
400 }))
401 }
402
403 pub fn crypto_provider<Cp>(
405 self,
406 crypto_provider: Cp,
407 ) -> ClientBuilder<WithCryptoProvider<Cp, C>>
408 where
409 Cp: CryptoProvider,
410 {
411 let Config(c) = self.0.into_config();
412
413 ClientBuilder(Config(ConfigInner {
414 settings: c.settings,
415 key_package_repo: c.key_package_repo,
416 psk_store: c.psk_store,
417 group_state_storage: c.group_state_storage,
418 identity_provider: c.identity_provider,
419 mls_rules: c.mls_rules,
420 crypto_provider,
421 signer: c.signer,
422 signing_identity: c.signing_identity,
423 version: c.version,
424 }))
425 }
426
427 pub fn mls_rules<Pr>(self, mls_rules: Pr) -> ClientBuilder<WithMlsRules<Pr, C>>
435 where
436 Pr: MlsRules,
437 {
438 let Config(c) = self.0.into_config();
439
440 ClientBuilder(Config(ConfigInner {
441 settings: c.settings,
442 key_package_repo: c.key_package_repo,
443 psk_store: c.psk_store,
444 group_state_storage: c.group_state_storage,
445 identity_provider: c.identity_provider,
446 mls_rules,
447 crypto_provider: c.crypto_provider,
448 signer: c.signer,
449 signing_identity: c.signing_identity,
450 version: c.version,
451 }))
452 }
453
454 pub fn used_protocol_version(
456 self,
457 version: ProtocolVersion,
458 ) -> ClientBuilder<IntoConfigOutput<C>> {
459 let mut c = self.0.into_config();
460 c.0.version = version;
461 ClientBuilder(c)
462 }
463
464 pub fn signing_identity(
467 self,
468 signing_identity: SigningIdentity,
469 signer: SignatureSecretKey,
470 cipher_suite: CipherSuite,
471 ) -> ClientBuilder<IntoConfigOutput<C>> {
472 let mut c = self.0.into_config();
473 c.0.signer = Some(signer);
474 c.0.signing_identity = Some((signing_identity, cipher_suite));
475 ClientBuilder(c)
476 }
477
478 pub fn signer(self, signer: SignatureSecretKey) -> ClientBuilder<IntoConfigOutput<C>> {
480 let mut c = self.0.into_config();
481 c.0.signer = Some(signer);
482 ClientBuilder(c)
483 }
484
485 #[cfg(any(test, feature = "test_util"))]
486 pub(crate) fn key_package_not_before(
487 self,
488 key_package_not_before: u64,
489 ) -> ClientBuilder<IntoConfigOutput<C>> {
490 let mut c = self.0.into_config();
491 c.0.settings.key_package_not_before = Some(key_package_not_before);
492 ClientBuilder(c)
493 }
494}
495
496impl<C: IntoConfig> ClientBuilder<C>
497where
498 C::KeyPackageRepository: KeyPackageStorage + Clone,
499 C::PskStore: PreSharedKeyStorage + Clone,
500 C::GroupStateStorage: GroupStateStorage + Clone,
501 C::IdentityProvider: IdentityProvider + Clone,
502 C::MlsRules: MlsRules + Clone,
503 C::CryptoProvider: CryptoProvider + Clone,
504{
505 pub(crate) fn build_config(self) -> IntoConfigOutput<C> {
506 let mut c = self.0.into_config();
507
508 if c.0.settings.protocol_versions.is_empty() {
509 c.0.settings.protocol_versions = ProtocolVersion::all().collect();
510 }
511
512 c
513 }
514
515 pub fn build(self) -> Client<IntoConfigOutput<C>> {
520 let mut c = self.build_config();
521 let version = c.0.version;
522 let signer = c.0.signer.take();
523 let signing_identity = c.0.signing_identity.take();
524
525 Client::new(c, signer, signing_identity, version)
526 }
527}
528
529impl<C: IntoConfig<PskStore = InMemoryPreSharedKeyStorage>> ClientBuilder<C> {
530 pub fn psk(
532 self,
533 psk_id: ExternalPskId,
534 psk: PreSharedKey,
535 ) -> ClientBuilder<IntoConfigOutput<C>> {
536 let mut c = self.0.into_config();
537 c.0.psk_store.insert(psk_id, psk);
538 ClientBuilder(c)
539 }
540}
541
542#[derive(Debug)]
544pub struct Missing;
545
546pub type WithKeyPackageRepo<K, C> = Config<
550 K,
551 <C as IntoConfig>::PskStore,
552 <C as IntoConfig>::GroupStateStorage,
553 <C as IntoConfig>::IdentityProvider,
554 <C as IntoConfig>::MlsRules,
555 <C as IntoConfig>::CryptoProvider,
556>;
557
558pub type WithPskStore<P, C> = Config<
562 <C as IntoConfig>::KeyPackageRepository,
563 P,
564 <C as IntoConfig>::GroupStateStorage,
565 <C as IntoConfig>::IdentityProvider,
566 <C as IntoConfig>::MlsRules,
567 <C as IntoConfig>::CryptoProvider,
568>;
569
570pub type WithGroupStateStorage<G, C> = Config<
574 <C as IntoConfig>::KeyPackageRepository,
575 <C as IntoConfig>::PskStore,
576 G,
577 <C as IntoConfig>::IdentityProvider,
578 <C as IntoConfig>::MlsRules,
579 <C as IntoConfig>::CryptoProvider,
580>;
581
582pub type WithIdentityProvider<I, C> = Config<
586 <C as IntoConfig>::KeyPackageRepository,
587 <C as IntoConfig>::PskStore,
588 <C as IntoConfig>::GroupStateStorage,
589 I,
590 <C as IntoConfig>::MlsRules,
591 <C as IntoConfig>::CryptoProvider,
592>;
593
594pub type WithMlsRules<Pr, C> = Config<
598 <C as IntoConfig>::KeyPackageRepository,
599 <C as IntoConfig>::PskStore,
600 <C as IntoConfig>::GroupStateStorage,
601 <C as IntoConfig>::IdentityProvider,
602 Pr,
603 <C as IntoConfig>::CryptoProvider,
604>;
605
606pub type WithCryptoProvider<Cp, C> = Config<
610 <C as IntoConfig>::KeyPackageRepository,
611 <C as IntoConfig>::PskStore,
612 <C as IntoConfig>::GroupStateStorage,
613 <C as IntoConfig>::IdentityProvider,
614 <C as IntoConfig>::MlsRules,
615 Cp,
616>;
617
618pub type IntoConfigOutput<C> = Config<
620 <C as IntoConfig>::KeyPackageRepository,
621 <C as IntoConfig>::PskStore,
622 <C as IntoConfig>::GroupStateStorage,
623 <C as IntoConfig>::IdentityProvider,
624 <C as IntoConfig>::MlsRules,
625 <C as IntoConfig>::CryptoProvider,
626>;
627
628pub type MakeConfig<C> = Config<
630 <C as ClientConfig>::KeyPackageRepository,
631 <C as ClientConfig>::PskStore,
632 <C as ClientConfig>::GroupStateStorage,
633 <C as ClientConfig>::IdentityProvider,
634 <C as ClientConfig>::MlsRules,
635 <C as ClientConfig>::CryptoProvider,
636>;
637
638impl<Kpr, Ps, Gss, Ip, Pr, Cp> ClientConfig for ConfigInner<Kpr, Ps, Gss, Ip, Pr, Cp>
639where
640 Kpr: KeyPackageStorage + Clone,
641 Ps: PreSharedKeyStorage + Clone,
642 Gss: GroupStateStorage + Clone,
643 Ip: IdentityProvider + Clone,
644 Pr: MlsRules + Clone,
645 Cp: CryptoProvider + Clone,
646{
647 type KeyPackageRepository = Kpr;
648 type PskStore = Ps;
649 type GroupStateStorage = Gss;
650 type IdentityProvider = Ip;
651 type MlsRules = Pr;
652 type CryptoProvider = Cp;
653
654 fn supported_extensions(&self) -> Vec<ExtensionType> {
655 self.settings.extension_types.clone()
656 }
657
658 fn supported_protocol_versions(&self) -> Vec<ProtocolVersion> {
659 self.settings.protocol_versions.clone()
660 }
661
662 fn key_package_repo(&self) -> Self::KeyPackageRepository {
663 self.key_package_repo.clone()
664 }
665
666 fn mls_rules(&self) -> Self::MlsRules {
667 self.mls_rules.clone()
668 }
669
670 fn secret_store(&self) -> Self::PskStore {
671 self.psk_store.clone()
672 }
673
674 fn group_state_storage(&self) -> Self::GroupStateStorage {
675 self.group_state_storage.clone()
676 }
677
678 fn identity_provider(&self) -> Self::IdentityProvider {
679 self.identity_provider.clone()
680 }
681
682 fn crypto_provider(&self) -> Self::CryptoProvider {
683 self.crypto_provider.clone()
684 }
685
686 fn lifetime(&self) -> Lifetime {
687 #[cfg(feature = "std")]
688 let now_timestamp = MlsTime::now().seconds_since_epoch();
689
690 #[cfg(not(feature = "std"))]
691 let now_timestamp = 0;
692
693 #[cfg(test)]
694 let now_timestamp = self
695 .settings
696 .key_package_not_before
697 .unwrap_or(now_timestamp);
698
699 Lifetime {
700 not_before: now_timestamp,
701 not_after: now_timestamp + self.settings.lifetime_in_s,
702 }
703 }
704
705 fn supported_custom_proposals(&self) -> Vec<crate::group::proposal::ProposalType> {
706 self.settings.custom_proposal_types.clone()
707 }
708}
709
710impl<Kpr, Ps, Gss, Ip, Pr, Cp> Sealed for Config<Kpr, Ps, Gss, Ip, Pr, Cp> {}
711
712impl<Kpr, Ps, Gss, Ip, Pr, Cp> MlsConfig for Config<Kpr, Ps, Gss, Ip, Pr, Cp>
713where
714 Kpr: KeyPackageStorage + Clone,
715
716 Ps: PreSharedKeyStorage + Clone,
717 Gss: GroupStateStorage + Clone,
718 Ip: IdentityProvider + Clone,
719 Pr: MlsRules + Clone,
720 Cp: CryptoProvider + Clone,
721{
722 type Output = ConfigInner<Kpr, Ps, Gss, Ip, Pr, Cp>;
723
724 fn get(&self) -> &Self::Output {
725 &self.0
726 }
727}
728
729pub trait MlsConfig: Clone + Send + Sync + Sealed {
733 #[doc(hidden)]
734 type Output: ClientConfig;
735
736 #[doc(hidden)]
737 fn get(&self) -> &Self::Output;
738}
739
740impl<T: MlsConfig> ClientConfig for T {
742 type KeyPackageRepository = <T::Output as ClientConfig>::KeyPackageRepository;
743 type PskStore = <T::Output as ClientConfig>::PskStore;
744 type GroupStateStorage = <T::Output as ClientConfig>::GroupStateStorage;
745 type IdentityProvider = <T::Output as ClientConfig>::IdentityProvider;
746 type MlsRules = <T::Output as ClientConfig>::MlsRules;
747 type CryptoProvider = <T::Output as ClientConfig>::CryptoProvider;
748
749 fn supported_extensions(&self) -> Vec<ExtensionType> {
750 self.get().supported_extensions()
751 }
752
753 fn supported_custom_proposals(&self) -> Vec<ProposalType> {
754 self.get().supported_custom_proposals()
755 }
756
757 fn supported_protocol_versions(&self) -> Vec<ProtocolVersion> {
758 self.get().supported_protocol_versions()
759 }
760
761 fn key_package_repo(&self) -> Self::KeyPackageRepository {
762 self.get().key_package_repo()
763 }
764
765 fn mls_rules(&self) -> Self::MlsRules {
766 self.get().mls_rules()
767 }
768
769 fn secret_store(&self) -> Self::PskStore {
770 self.get().secret_store()
771 }
772
773 fn group_state_storage(&self) -> Self::GroupStateStorage {
774 self.get().group_state_storage()
775 }
776
777 fn identity_provider(&self) -> Self::IdentityProvider {
778 self.get().identity_provider()
779 }
780
781 fn crypto_provider(&self) -> Self::CryptoProvider {
782 self.get().crypto_provider()
783 }
784
785 fn lifetime(&self) -> Lifetime {
786 self.get().lifetime()
787 }
788
789 fn capabilities(&self) -> Capabilities {
790 self.get().capabilities()
791 }
792
793 fn version_supported(&self, version: ProtocolVersion) -> bool {
794 self.get().version_supported(version)
795 }
796
797 fn supported_credential_types(&self) -> Vec<CredentialType> {
798 self.get().supported_credential_types()
799 }
800}
801
802#[derive(Clone, Debug)]
803pub(crate) struct Settings {
804 pub(crate) extension_types: Vec<ExtensionType>,
805 pub(crate) protocol_versions: Vec<ProtocolVersion>,
806 pub(crate) custom_proposal_types: Vec<ProposalType>,
807 pub(crate) lifetime_in_s: u64,
808 #[cfg(any(test, feature = "test_util"))]
809 pub(crate) key_package_not_before: Option<u64>,
810}
811
812impl Default for Settings {
813 fn default() -> Self {
814 Self {
815 extension_types: Default::default(),
816 protocol_versions: Default::default(),
817 lifetime_in_s: 365 * 24 * 3600,
818 custom_proposal_types: Default::default(),
819 #[cfg(any(test, feature = "test_util"))]
820 key_package_not_before: None,
821 }
822 }
823}
824
825pub(crate) fn recreate_config<T: ClientConfig>(
826 c: T,
827 signer: Option<SignatureSecretKey>,
828 signing_identity: Option<(SigningIdentity, CipherSuite)>,
829 version: ProtocolVersion,
830) -> MakeConfig<T> {
831 Config(ConfigInner {
832 settings: Settings {
833 extension_types: c.supported_extensions(),
834 protocol_versions: c.supported_protocol_versions(),
835 custom_proposal_types: c.supported_custom_proposals(),
836 lifetime_in_s: {
837 let l = c.lifetime();
838 l.not_after - l.not_before
839 },
840 #[cfg(any(test, feature = "test_util"))]
841 key_package_not_before: None,
842 },
843 key_package_repo: c.key_package_repo(),
844 psk_store: c.secret_store(),
845 group_state_storage: c.group_state_storage(),
846 identity_provider: c.identity_provider(),
847 mls_rules: c.mls_rules(),
848 crypto_provider: c.crypto_provider(),
849 signer,
850 signing_identity,
851 version,
852 })
853}
854
855mod private {
858 use mls_rs_core::{
859 crypto::{CipherSuite, SignatureSecretKey},
860 identity::SigningIdentity,
861 protocol_version::ProtocolVersion,
862 };
863
864 use crate::client_builder::{IntoConfigOutput, Settings};
865
866 #[derive(Clone, Debug)]
867 pub struct Config<Kpr, Ps, Gss, Ip, Pr, Cp>(pub(crate) ConfigInner<Kpr, Ps, Gss, Ip, Pr, Cp>);
868
869 #[derive(Clone, Debug)]
870 pub struct ConfigInner<Kpr, Ps, Gss, Ip, Pr, Cp> {
871 pub(crate) settings: Settings,
872 pub(crate) key_package_repo: Kpr,
873 pub(crate) psk_store: Ps,
874 pub(crate) group_state_storage: Gss,
875 pub(crate) identity_provider: Ip,
876 pub(crate) mls_rules: Pr,
877 pub(crate) crypto_provider: Cp,
878 pub(crate) signer: Option<SignatureSecretKey>,
879 pub(crate) signing_identity: Option<(SigningIdentity, CipherSuite)>,
880 pub(crate) version: ProtocolVersion,
881 }
882
883 pub trait IntoConfig {
884 type KeyPackageRepository;
885 type PskStore;
886 type GroupStateStorage;
887 type IdentityProvider;
888 type MlsRules;
889 type CryptoProvider;
890
891 fn into_config(self) -> IntoConfigOutput<Self>;
892 }
893
894 impl<Kpr, Ps, Gss, Ip, Pr, Cp> IntoConfig for Config<Kpr, Ps, Gss, Ip, Pr, Cp> {
895 type KeyPackageRepository = Kpr;
896 type PskStore = Ps;
897 type GroupStateStorage = Gss;
898 type IdentityProvider = Ip;
899 type MlsRules = Pr;
900 type CryptoProvider = Cp;
901
902 fn into_config(self) -> Self {
903 self
904 }
905 }
906}
907
908use mls_rs_core::{
909 crypto::{CryptoProvider, SignatureSecretKey},
910 group::GroupStateStorage,
911 identity::IdentityProvider,
912 key_package::KeyPackageStorage,
913 psk::PreSharedKeyStorage,
914};
915use private::{Config, ConfigInner, IntoConfig};
916
917#[cfg(test)]
918pub(crate) mod test_utils {
919 use crate::{
920 client_builder::{BaseConfig, ClientBuilder, WithIdentityProvider},
921 crypto::test_utils::TestCryptoProvider,
922 identity::{
923 basic::BasicIdentityProvider,
924 test_utils::{get_test_signing_identity, BasicWithCustomProvider},
925 },
926 CipherSuite,
927 };
928
929 use super::WithCryptoProvider;
930
931 pub type TestClientConfig = WithIdentityProvider<
932 BasicWithCustomProvider,
933 WithCryptoProvider<TestCryptoProvider, BaseConfig>,
934 >;
935
936 pub type TestClientBuilder = ClientBuilder<TestClientConfig>;
937
938 impl TestClientBuilder {
939 pub fn new_for_test() -> Self {
940 ClientBuilder::new()
941 .crypto_provider(TestCryptoProvider::new())
942 .identity_provider(BasicWithCustomProvider::new(BasicIdentityProvider::new()))
943 }
944
945 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
946 pub async fn with_random_signing_identity(
947 self,
948 identity: &str,
949 cipher_suite: CipherSuite,
950 ) -> Self {
951 let (signing_identity, signer) =
952 get_test_signing_identity(cipher_suite, identity.as_bytes()).await;
953 self.signing_identity(signing_identity, signer, cipher_suite)
954 }
955 }
956}