bitwarden_state/
repository.rs

1use std::any::TypeId;
2
3use crate::registry::RepositoryNotFoundError;
4
5/// An error resulting from operations on a repository.
6#[derive(thiserror::Error, Debug)]
7pub enum RepositoryError {
8    /// An internal unspecified error.
9    #[error("Internal error: {0}")]
10    Internal(String),
11
12    /// Repository not found.
13    #[error(transparent)]
14    RepositoryNotFound(#[from] RepositoryNotFoundError),
15}
16
17/// This trait represents a generic repository interface, capable of storing and retrieving
18/// items using a key-value API.
19#[async_trait::async_trait]
20pub trait Repository<V: RepositoryItem>: Send + Sync {
21    /// Retrieves an item from the repository by its key.
22    async fn get(&self, key: String) -> Result<Option<V>, RepositoryError>;
23    /// Lists all items in the repository.
24    async fn list(&self) -> Result<Vec<V>, RepositoryError>;
25    /// Sets an item in the repository with the specified key.
26    async fn set(&self, key: String, value: V) -> Result<(), RepositoryError>;
27    /// Removes an item from the repository by its key.
28    async fn remove(&self, key: String) -> Result<(), RepositoryError>;
29}
30
31/// This trait is used to mark types that can be stored in a repository.
32/// It should not be implemented manually; instead, users should
33/// use the [crate::register_repository_item] macro to register their item types.
34pub trait RepositoryItem: Internal + Send + Sync + 'static {
35    /// The name of the type implementing this trait.
36    const NAME: &'static str;
37    /// Returns the `TypeId` of the type implementing this trait.
38    fn type_id() -> TypeId {
39        TypeId::of::<Self>()
40    }
41}
42
43/// Register a type for use in a repository. The type must only be registered once in the crate
44/// where it's defined. The provided name must be unique and not be changed.
45#[macro_export]
46macro_rules! register_repository_item {
47    ($ty:ty, $name:literal) => {
48        const _: () = {
49            impl $crate::repository::___internal::Internal for $ty {}
50            impl $crate::repository::RepositoryItem for $ty {
51                const NAME: &'static str = $name;
52            }
53        };
54    };
55}
56
57/// This code is not meant to be used directly, users of this crate should use the
58/// [crate::register_repository_item] macro to register their types.
59#[doc(hidden)]
60pub mod ___internal {
61
62    // This trait is just to try to discourage users from implementing `RepositoryItem` directly.
63    pub trait Internal {}
64}
65pub(crate) use ___internal::Internal;