bitwarden_core/client/from_client_part.rs
1//! Traits for extracting dependencies from a Client.
2//!
3//! This module provides:
4//! - [`FromClientPart`] trait which enables uniform extraction of dependencies from a [`Client`],
5//! facilitating macro-based generation of `from_client` methods for feature clients.
6//! - [`FromClient`] trait which can be derived using `#[derive(FromClient)]` from the
7//! `bitwarden_core_macro` crate to automatically implement `from_client`.
8
9use std::sync::Arc;
10
11use bitwarden_crypto::KeyStore;
12#[cfg(feature = "internal")]
13use bitwarden_state::repository::{Repository, RepositoryItem};
14
15use super::Client;
16use crate::{client::ApiConfigurations, key_management::KeyIds};
17
18/// Trait for types that can be constructed from a [`Client`].
19///
20/// This trait is typically derived using `#[derive(FromClient)]` from
21/// the `bitwarden_core_macro` crate, which generates the implementation
22/// by extracting all struct fields from the Client using [`FromClientPart`].
23///
24/// # Example
25///
26/// ```ignore
27/// use bitwarden_core::client::FromClient;
28/// use bitwarden_core_macro::FromClient;
29///
30/// #[derive(FromClient)]
31/// pub struct FoldersClient {
32/// key_store: KeyStore<KeyIds>,
33/// api_configurations: Arc<ApiConfigurations>,
34/// repository: Arc<dyn Repository<Folder>>,
35/// }
36///
37/// // Usage:
38/// let folders_client = FoldersClient::from_client(&client)?;
39/// ```
40pub trait FromClient: Sized {
41 /// Construct this type from a [`Client`] reference.
42 fn from_client(client: &Client) -> Result<Self, String>;
43}
44
45/// Trait for extracting parts/dependencies from a [`Client`].
46///
47/// Implemented by [`Client`] for each dependency type that can be extracted. Used internally by
48/// `#[derive(FromClient)]` - users should derive [`FromClient`] rather than using this trait
49/// directly.
50pub trait FromClientPart<T> {
51 /// The error type returned when extraction fails.
52 type Error;
53
54 /// Extract a dependency of type `T` from self.
55 fn get_part(&self) -> Result<T, Self::Error>;
56}
57
58impl FromClientPart<KeyStore<KeyIds>> for Client {
59 type Error = std::convert::Infallible;
60
61 fn get_part(&self) -> Result<KeyStore<KeyIds>, Self::Error> {
62 Ok(self.internal.get_key_store().clone())
63 }
64}
65
66impl FromClientPart<Arc<ApiConfigurations>> for Client {
67 type Error = std::convert::Infallible;
68
69 fn get_part(&self) -> Result<Arc<ApiConfigurations>, Self::Error> {
70 Ok(self.internal.get_api_configurations())
71 }
72}
73
74#[cfg(feature = "internal")]
75impl<T: RepositoryItem> FromClientPart<Arc<dyn Repository<T>>> for Client {
76 type Error = bitwarden_state::registry::StateRegistryError;
77
78 fn get_part(&self) -> Result<Arc<dyn Repository<T>>, Self::Error> {
79 self.platform().state().get::<T>()
80 }
81}