bitwarden_uniffi/platform/
repository.rs

1use std::sync::Arc;
2
3pub struct UniffiRepositoryBridge<T>(pub T);
4
5impl<T: ?Sized> UniffiRepositoryBridge<Arc<T>> {
6    pub fn new(store: Arc<T>) -> Arc<Self> {
7        Arc::new(UniffiRepositoryBridge(store))
8    }
9}
10
11impl<T: std::fmt::Debug> std::fmt::Debug for UniffiRepositoryBridge<T> {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        self.0.fmt(f)
14    }
15}
16
17#[derive(uniffi::Error, thiserror::Error, Debug)]
18pub enum RepositoryError {
19    #[error("Internal error: {0}")]
20    Internal(String),
21}
22
23// Need to implement this From<> impl in order to handle unexpected callback errors.  See the
24// following page in the Uniffi user guide:
25// <https://mozilla.github.io/uniffi-rs/foreign_traits.html#error-handling>
26impl From<uniffi::UnexpectedUniFFICallbackError> for RepositoryError {
27    fn from(e: uniffi::UnexpectedUniFFICallbackError) -> Self {
28        Self::Internal(e.reason)
29    }
30}
31
32impl From<RepositoryError> for bitwarden_state::repository::RepositoryError {
33    fn from(e: RepositoryError) -> Self {
34        match e {
35            RepositoryError::Internal(msg) => Self::Internal(msg),
36        }
37    }
38}
39
40/// This macro creates a Uniffi repository trait and its implementation for the
41/// [bitwarden_state::repository::Repository] trait
42macro_rules! create_uniffi_repository {
43    ($name:ident, $ty:ty) => {
44        #[uniffi::export(with_foreign)]
45        #[async_trait::async_trait]
46        pub trait $name: Send + Sync {
47            async fn get(
48                &self,
49                id: String,
50            ) -> Result<Option<$ty>, $crate::platform::repository::RepositoryError>;
51            async fn list(&self)
52            -> Result<Vec<$ty>, $crate::platform::repository::RepositoryError>;
53            async fn set(
54                &self,
55                id: String,
56                value: $ty,
57            ) -> Result<(), $crate::platform::repository::RepositoryError>;
58            async fn remove(
59                &self,
60                id: String,
61            ) -> Result<(), $crate::platform::repository::RepositoryError>;
62
63            async fn has(
64                &self,
65                id: String,
66            ) -> Result<bool, $crate::platform::repository::RepositoryError>;
67        }
68
69        #[async_trait::async_trait]
70        impl bitwarden_state::repository::Repository<$ty>
71            for $crate::platform::repository::UniffiRepositoryBridge<Arc<dyn $name>>
72        {
73            async fn get(
74                &self,
75                key: String,
76            ) -> Result<Option<$ty>, bitwarden_state::repository::RepositoryError> {
77                self.0.get(key).await.map_err(Into::into)
78            }
79            async fn list(&self) -> Result<Vec<$ty>, bitwarden_state::repository::RepositoryError> {
80                self.0.list().await.map_err(Into::into)
81            }
82            async fn set(
83                &self,
84                key: String,
85                value: $ty,
86            ) -> Result<(), bitwarden_state::repository::RepositoryError> {
87                self.0.set(key, value).await.map_err(Into::into)
88            }
89            async fn remove(
90                &self,
91                key: String,
92            ) -> Result<(), bitwarden_state::repository::RepositoryError> {
93                self.0.remove(key).await.map_err(Into::into)
94            }
95        }
96    };
97}
98pub(super) use create_uniffi_repository;