1- use crate :: hasher:: { blake2b_512 , blake2s_256 , sha2_256, sha2_512 , sha3_256 , sha3_512 } ;
2- use crate :: Error :: PoisonedLock ;
3- use crate :: Result ;
1+ use crate :: hasher:: sha2_256;
2+ use crate :: Error :: { PoisonedLock , UnsupportedHasher } ;
3+ use crate :: { Result , THESEUS_POSTGRESQL_BINARIES_URL } ;
44use lazy_static:: lazy_static;
5- use std:: collections:: HashMap ;
65use std:: sync:: { Arc , Mutex , RwLock } ;
76
87lazy_static ! {
98 static ref REGISTRY : Arc <Mutex <HasherRegistry >> =
109 Arc :: new( Mutex :: new( HasherRegistry :: default ( ) ) ) ;
1110}
1211
12+ pub type SupportsFn = fn ( & str , & str ) -> Result < bool > ;
1313pub type HasherFn = fn ( & Vec < u8 > ) -> Result < String > ;
1414
1515/// Singleton struct to store hashers
16+ #[ allow( clippy:: type_complexity) ]
1617struct HasherRegistry {
17- hashers : HashMap < String , Arc < RwLock < HasherFn > > > ,
18+ hashers : Vec < ( Arc < RwLock < SupportsFn > > , Arc < RwLock < HasherFn > > ) > ,
1819}
1920
2021impl HasherRegistry {
2122 /// Creates a new hasher registry.
2223 fn new ( ) -> Self {
2324 Self {
24- hashers : HashMap :: new ( ) ,
25+ hashers : Vec :: new ( ) ,
2526 }
2627 }
2728
28- /// Registers a hasher for an extension. Newly registered hashers with the same extension will
29- /// override existing ones.
30- fn register < S : AsRef < str > > ( & mut self , extension : S , hasher_fn : HasherFn ) {
31- let extension = extension. as_ref ( ) . to_string ( ) ;
32- self . hashers
33- . insert ( extension, Arc :: new ( RwLock :: new ( hasher_fn) ) ) ;
29+ /// Registers a hasher for a supports function. Newly registered hashers will take precedence
30+ /// over existing ones.
31+ fn register ( & mut self , supports_fn : SupportsFn , hasher_fn : HasherFn ) {
32+ self . hashers . insert (
33+ 0 ,
34+ (
35+ Arc :: new ( RwLock :: new ( supports_fn) ) ,
36+ Arc :: new ( RwLock :: new ( hasher_fn) ) ,
37+ ) ,
38+ ) ;
3439 }
3540
36- /// Get a hasher for the specified extension.
41+ /// Get a hasher for the specified url and extension.
3742 ///
3843 /// # Errors
3944 /// * If the registry is poisoned.
40- fn get < S : AsRef < str > > ( & self , extension : S ) -> Result < Option < HasherFn > > {
41- let extension = extension. as_ref ( ) . to_string ( ) ;
42- if let Some ( hasher) = self . hashers . get ( & extension) {
43- let hasher = * hasher
45+ fn get < S : AsRef < str > > ( & self , url : S , extension : S ) -> Result < HasherFn > {
46+ let url = url. as_ref ( ) ;
47+ let extension = extension. as_ref ( ) ;
48+ for ( supports_fn, hasher_fn) in & self . hashers {
49+ let supports_function = supports_fn
4450 . read ( )
4551 . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?;
46- return Ok ( Some ( hasher) ) ;
52+ if supports_function ( url, extension) ? {
53+ let hasher_function = hasher_fn
54+ . read ( )
55+ . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?;
56+ return Ok ( * hasher_function) ;
57+ }
4758 }
4859
49- Ok ( None )
50- }
51-
52- /// Get the number of hashers in the registry.
53- fn len ( & self ) -> usize {
54- self . hashers . len ( )
55- }
56-
57- /// Check if the registry is empty.
58- fn is_empty ( & self ) -> bool {
59- self . hashers . is_empty ( )
60+ Err ( UnsupportedHasher ( url. to_string ( ) ) )
6061 }
6162}
6263
6364impl Default for HasherRegistry {
6465 /// Creates a new hasher registry with the default hashers registered.
6566 fn default ( ) -> Self {
6667 let mut registry = Self :: new ( ) ;
67- registry. register ( "blake2s" , blake2s_256 :: hash ) ;
68- registry . register ( "blake2b" , blake2b_512 :: hash ) ;
69- registry . register ( "sha256" , sha2_256 :: hash ) ;
70- registry . register ( "sha512" , sha2_512 :: hash ) ;
71- registry . register ( "sha3-256" , sha3_256 :: hash) ;
72- registry . register ( "sha3-512" , sha3_512 :: hash ) ;
68+ registry. register (
69+ |url , extension| {
70+ Ok ( url . starts_with ( THESEUS_POSTGRESQL_BINARIES_URL ) && extension == "sha256" )
71+ } ,
72+ sha2_256 :: hash,
73+ ) ;
7374 registry
7475 }
7576}
7677
77- /// Registers a hasher for an extension . Newly registered hashers with the same extension will
78- /// override existing ones.
78+ /// Registers a hasher for a supports function . Newly registered hashers will take precedence
79+ /// over existing ones.
7980///
8081/// # Errors
8182/// * If the registry is poisoned.
8283#[ allow( dead_code) ]
83- pub fn register < S : AsRef < str > > ( extension : S , hasher_fn : HasherFn ) -> Result < ( ) > {
84+ pub fn register ( supports_fn : SupportsFn , hasher_fn : HasherFn ) -> Result < ( ) > {
8485 let mut registry = REGISTRY
8586 . lock ( )
8687 . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?;
87- registry. register ( extension , hasher_fn) ;
88+ registry. register ( supports_fn , hasher_fn) ;
8889 Ok ( ( ) )
8990}
9091
91- /// Get a hasher for the specified extension.
92+ /// Get a hasher for the specified url and extension.
9293///
9394/// # Errors
9495/// * If the registry is poisoned.
95- pub fn get < S : AsRef < str > > ( extension : S ) -> Result < Option < HasherFn > > {
96+ pub fn get < S : AsRef < str > > ( url : S , extension : S ) -> Result < HasherFn > {
9697 let registry = REGISTRY
9798 . lock ( )
9899 . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?;
99- registry. get ( extension)
100- }
101-
102- /// Get the number of matchers in the registry.
103- ///
104- /// # Errors
105- /// * If the registry is poisoned.
106- pub fn len ( ) -> Result < usize > {
107- let registry = REGISTRY
108- . lock ( )
109- . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?;
110- Ok ( registry. len ( ) )
111- }
112-
113- /// Check if the registry is empty.
114- ///
115- /// # Errors
116- /// * If the registry is poisoned.
117- pub fn is_empty ( ) -> Result < bool > {
118- let registry = REGISTRY
119- . lock ( )
120- . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?;
121- Ok ( registry. is_empty ( ) )
100+ registry. get ( url, extension)
122101}
123102
124103#[ cfg( test) ]
125104mod tests {
126105 use super :: * ;
127106
128107 fn test_hasher ( extension : & str , expected : & str ) -> Result < ( ) > {
129- let hasher = get ( extension) ?. unwrap ( ) ;
108+ let hasher = get ( "https://foo.com" , extension) ?;
130109 let data = vec ! [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 ] ;
131110 let hash = hasher ( & data) ?;
132111 assert_eq ! ( expected, hash) ;
@@ -135,69 +114,33 @@ mod tests {
135114
136115 #[ test]
137116 fn test_register ( ) -> Result < ( ) > {
138- let extension = "sha256" ;
139- let hashers = len ( ) ?;
140- assert ! ( !is_empty( ) ?) ;
141- REGISTRY
142- . lock ( )
143- . map_err ( |error| PoisonedLock ( error. to_string ( ) ) ) ?
144- . hashers
145- . remove ( extension) ;
146- assert_ne ! ( hashers, len( ) ?) ;
147- register ( extension, sha2_256:: hash) ?;
148- assert_eq ! ( hashers, len( ) ?) ;
149-
150- test_hasher (
151- extension,
152- "9a89c68c4c5e28b8c4a5567673d462fff515db46116f9900624d09c474f593fb" ,
153- )
154- }
155-
156- #[ test]
157- fn test_sha2_256 ( ) -> Result < ( ) > {
158- test_hasher (
159- "sha256" ,
160- "9a89c68c4c5e28b8c4a5567673d462fff515db46116f9900624d09c474f593fb" ,
161- )
162- }
163-
164- #[ test]
165- fn test_sha2_512 ( ) -> Result < ( ) > {
166- test_hasher (
167- "sha512" ,
168- "3ad3f36979450d4f53366244ecf1010f4f9121d6888285ff14104fd5aded85d48aa171bf1e33a112602f92b7a7088b298789012fb87b9056321241a19fb74e0b" ,
169- )
170- }
171-
172- #[ test]
173- fn test_sha3_256 ( ) -> Result < ( ) > {
174- test_hasher (
175- "sha3-256" ,
176- "c0188232190e0427fc9cc78597221c76c799528660889bd6ce1f3563148ff84d" ,
177- )
117+ register (
118+ |_, extension| Ok ( extension == "test" ) ,
119+ |_| Ok ( "42" . to_string ( ) ) ,
120+ ) ?;
121+ test_hasher ( "test" , "42" )
178122 }
179123
180124 #[ test]
181- fn test_sha3_512 ( ) -> Result < ( ) > {
182- test_hasher (
183- "sha3-512" ,
184- "9429fc1f9772cc1d8039fe75cc1b033cd60f0ec4face0f8a514d25b0649ba8a5954b6c7a41cc3697a56db3ff321475be1fa14b70c7eb78fec6ce62dbfc54c9d3" ,
185- )
125+ fn test_get_invalid_url_error ( ) {
126+ let error = get ( "https://foo.com" , "foo" ) . unwrap_err ( ) ;
127+ assert_eq ! (
128+ "unsupported hasher for 'https://foo.com'" ,
129+ error. to_string( )
130+ ) ;
186131 }
187132
188133 #[ test]
189- fn test_blake2s_256 ( ) -> Result < ( ) > {
190- test_hasher (
191- "blake2s" ,
192- "7125921e06071710350390fe902856dbea366a5d6f5ee26c18e741143ac80061" ,
193- )
134+ fn test_get_invalid_extension_error ( ) {
135+ let error = get ( THESEUS_POSTGRESQL_BINARIES_URL , "foo" ) . unwrap_err ( ) ;
136+ assert_eq ! (
137+ format!( "unsupported hasher for '{THESEUS_POSTGRESQL_BINARIES_URL}'" ) ,
138+ error. to_string( )
139+ ) ;
194140 }
195141
196142 #[ test]
197- fn test_blake2b_512 ( ) -> Result < ( ) > {
198- test_hasher (
199- "blake2b" ,
200- "67767f1cab415502dcceec9f099fb84539b1c73c5ebdcfe1bb8ca7411e3b6cb33e304f49222edac9bdaa74129e9e13f11f215b8560f9081f0e8f1f869162bf46" ,
201- )
143+ fn test_get_theseus_postgresql_binaries ( ) {
144+ assert ! ( get( THESEUS_POSTGRESQL_BINARIES_URL , "sha256" ) . is_ok( ) ) ;
202145 }
203146}
0 commit comments