1
1
use std:: {
2
2
any:: { Any , TypeId } ,
3
3
collections:: HashMap ,
4
- sync:: Arc ,
4
+ sync:: { Arc , RwLock } ,
5
5
} ;
6
6
7
7
use bitwarden_error:: bitwarden_error;
@@ -13,14 +13,12 @@ use crate::repository::{Repository, RepositoryItem};
13
13
/// A registry that contains repositories for different types of items.
14
14
/// These repositories can be either managed by the client or by the SDK itself.
15
15
pub struct StateRegistry {
16
- client_managed : HashMap < TypeId , Box < dyn Any + Send + Sync > > ,
16
+ client_managed : RwLock < HashMap < TypeId , Box < dyn Any + Send + Sync > > > ,
17
17
}
18
18
19
19
impl std:: fmt:: Debug for StateRegistry {
20
20
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
21
- f. debug_struct ( "StateRegistry" )
22
- . field ( "client_managed" , & self . client_managed . keys ( ) )
23
- . finish ( )
21
+ f. debug_struct ( "StateRegistry" ) . finish ( )
24
22
}
25
23
}
26
24
@@ -40,13 +38,13 @@ impl StateRegistry {
40
38
#[ allow( clippy:: new_without_default) ]
41
39
pub fn new ( ) -> Self {
42
40
StateRegistry {
43
- client_managed : HashMap :: new ( ) ,
41
+ client_managed : RwLock :: new ( HashMap :: new ( ) ) ,
44
42
}
45
43
}
46
44
47
45
/// Registers a client-managed repository into the map, associating it with its type.
48
46
pub fn register_client_managed < T : RepositoryItem > (
49
- & mut self ,
47
+ & self ,
50
48
value : Arc < dyn Repository < T > > ,
51
49
) -> Result < ( ) , StateRegistryError > {
52
50
let mut possible_registrations = RepositoryItemRegistration :: iter ( ) ;
@@ -63,6 +61,8 @@ impl StateRegistry {
63
61
}
64
62
65
63
self . client_managed
64
+ . write ( )
65
+ . expect ( "RwLock should not be poisoned" )
66
66
. insert ( TypeId :: of :: < T > ( ) , Box :: new ( value) ) ;
67
67
68
68
Ok ( ( ) )
@@ -71,6 +71,8 @@ impl StateRegistry {
71
71
/// Retrieves a client-managed repository from the map given its type.
72
72
pub fn get_client_managed < T : RepositoryItem > ( & self ) -> Option < Arc < dyn Repository < T > > > {
73
73
self . client_managed
74
+ . read ( )
75
+ . expect ( "RwLock should not be poisoned" )
74
76
. get ( & TypeId :: of :: < T > ( ) )
75
77
. and_then ( |boxed| boxed. downcast_ref :: < Arc < dyn Repository < T > > > ( ) )
76
78
. map ( Arc :: clone)
@@ -82,8 +84,13 @@ impl StateRegistry {
82
84
let possible_registrations = RepositoryItemRegistration :: iter ( ) ;
83
85
let mut missing_repository = false ;
84
86
87
+ let client_managed = self
88
+ . client_managed
89
+ . read ( )
90
+ . expect ( "RwLock should not be poisoned" ) ;
91
+
85
92
for reg in possible_registrations {
86
- if reg. rtype . is_client_managed ( ) && !self . client_managed . contains_key ( & reg. type_id ( ) ) {
93
+ if reg. rtype . is_client_managed ( ) && !client_managed. contains_key ( & reg. type_id ( ) ) {
87
94
log:: error!(
88
95
"Repository for type {} is not registered in the client-managed state registry" ,
89
96
reg. name
@@ -151,7 +158,7 @@ mod tests {
151
158
let b = Arc :: new ( TestB ( "test" . to_string ( ) ) ) ;
152
159
let c = Arc :: new ( TestC ( vec ! [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ) ) ;
153
160
154
- let mut map = StateRegistry :: new ( ) ;
161
+ let map = StateRegistry :: new ( ) ;
155
162
156
163
async fn get < T : RepositoryItem > ( map : & StateRegistry ) -> Option < T > {
157
164
map. get_client_managed :: < T > ( )
0 commit comments