bitwarden_uniffi/platform/
repository.rs1use 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
23impl 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
40macro_rules! create_uniffi_repositories {
43 ( $container_name:ident ; $( $qualified_type_name:ty, $type_name:ident, $field_name:ident, $repo_name:ident );+ $(;)? ) => {
44
45 #[derive(::uniffi::Record)]
46 pub struct $container_name {
47 $(
48 pub $field_name: Option<::std::sync::Arc<dyn $repo_name>>,
49 )+
50 }
51
52 impl $container_name {
53 pub fn register_all(self, client: &bitwarden_core::platform::StateClient) {
54 $(
55 if let Some(repo) = self.$field_name {
56 let bridge = $crate::platform::repository::UniffiRepositoryBridge::new(repo);
57 client.register_client_managed(bridge);
58 }
59 )+
60 }
61 }
62
63 $(
64 #[::uniffi::export(with_foreign)]
65 #[::async_trait::async_trait]
66 pub trait $repo_name: Send + Sync {
67 async fn get(
68 &self,
69 id: String,
70 ) -> Result<Option<$qualified_type_name>, $crate::platform::repository::RepositoryError>;
71 async fn list(&self)
72 -> Result<Vec<$qualified_type_name>, $crate::platform::repository::RepositoryError>;
73 async fn set(
74 &self,
75 id: String,
76 value: $qualified_type_name,
77 ) -> Result<(), $crate::platform::repository::RepositoryError>;
78 async fn set_bulk(
79 &self,
80 values: std::collections::HashMap<String, $qualified_type_name>,
81 ) -> Result<(), $crate::platform::repository::RepositoryError>;
82 async fn remove(
83 &self,
84 id: String,
85 ) -> Result<(), $crate::platform::repository::RepositoryError>;
86 async fn remove_bulk(
87 &self,
88 keys: Vec<String>,
89 ) -> Result<(), $crate::platform::repository::RepositoryError>;
90 async fn remove_all(&self)
91 -> Result<(), $crate::platform::repository::RepositoryError>;
92
93 async fn has(
94 &self,
95 id: String,
96 ) -> Result<bool, $crate::platform::repository::RepositoryError>;
97 }
98
99 #[async_trait::async_trait]
100 impl bitwarden_state::repository::Repository<$qualified_type_name>
101 for $crate::platform::repository::UniffiRepositoryBridge<Arc<dyn $repo_name>>
102 {
103 async fn get(
104 &self,
105 key: <$qualified_type_name as bitwarden_state::repository::RepositoryItem>::Key,
106 ) -> Result<Option<$qualified_type_name>, bitwarden_state::repository::RepositoryError> {
107 let key = key.to_string();
108 self.0.get(key).await.map_err(Into::into)
109 }
110 async fn list(&self) -> Result<Vec<$qualified_type_name>, bitwarden_state::repository::RepositoryError> {
111 self.0.list().await.map_err(Into::into)
112 }
113 async fn set(
114 &self,
115 key: <$qualified_type_name as bitwarden_state::repository::RepositoryItem>::Key,
116 value: $qualified_type_name,
117 ) -> Result<(), bitwarden_state::repository::RepositoryError> {
118 let key = key.to_string();
119 self.0.set(key, value).await.map_err(Into::into)
120 }
121 async fn set_bulk(
122 &self,
123 values: Vec<(<$qualified_type_name as bitwarden_state::repository::RepositoryItem>::Key, $qualified_type_name)>,
124 ) -> Result<(), bitwarden_state::repository::RepositoryError> {
125 let map = values.into_iter().map(|(k, v)| (k.to_string(), v)).collect();
126 self.0.set_bulk(map).await.map_err(Into::into)
127 }
128 async fn remove(
129 &self,
130 key: <$qualified_type_name as bitwarden_state::repository::RepositoryItem>::Key,
131 ) -> Result<(), bitwarden_state::repository::RepositoryError> {
132 let key = key.to_string();
133 self.0.remove(key).await.map_err(Into::into)
134 }
135 async fn remove_bulk(
136 &self,
137 keys: Vec<<$qualified_type_name as bitwarden_state::repository::RepositoryItem>::Key>,
138 ) -> Result<(), bitwarden_state::repository::RepositoryError> {
139 let keys = keys.into_iter().map(|k| k.to_string()).collect();
140 self.0.remove_bulk(keys).await.map_err(Into::into)
141 }
142 async fn remove_all(&self) -> Result<(), bitwarden_state::repository::RepositoryError> {
143 self.0.remove_all().await.map_err(Into::into)
144 }
145 }
146 )+
147 };
148}
149
150pub(super) use create_uniffi_repositories;