Skip to main content

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}