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;