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