@@ -3,7 +3,7 @@ use std::collections::HashMap;
3
3
use std:: fmt;
4
4
use std:: hash:: { BuildHasherDefault , Hasher } ;
5
5
6
- type AnyMap = HashMap < TypeId , Box < dyn Any + Send + Sync > , BuildHasherDefault < IdHasher > > ;
6
+ type AnyMap = HashMap < TypeId , Box < dyn AnyClone + Send + Sync > , BuildHasherDefault < IdHasher > > ;
7
7
8
8
// With TypeIds as keys, there's no need to hash them. They are already hashes
9
9
// themselves, coming from the compiler. The IdHasher just holds the u64 of
@@ -31,7 +31,7 @@ impl Hasher for IdHasher {
31
31
///
32
32
/// `Extensions` can be used by `Request` and `Response` to store
33
33
/// extra data derived from the underlying protocol.
34
- #[ derive( Default ) ]
34
+ #[ derive( Clone , Default ) ]
35
35
pub struct Extensions {
36
36
// If extensions are never used, no need to carry around an empty HashMap.
37
37
// That's 3 words. Instead, this is only 1 word.
@@ -59,12 +59,12 @@ impl Extensions {
59
59
/// assert!(ext.insert(4u8).is_none());
60
60
/// assert_eq!(ext.insert(9i32), Some(5i32));
61
61
/// ```
62
- pub fn insert < T : Send + Sync + ' static > ( & mut self , val : T ) -> Option < T > {
62
+ pub fn insert < T : Clone + Send + Sync + ' static > ( & mut self , val : T ) -> Option < T > {
63
63
self . map
64
64
. get_or_insert_with ( || Box :: new ( HashMap :: default ( ) ) )
65
65
. insert ( TypeId :: of :: < T > ( ) , Box :: new ( val) )
66
66
. and_then ( |boxed| {
67
- ( boxed as Box < dyn Any + ' static > )
67
+ boxed. into_any ( )
68
68
. downcast ( )
69
69
. ok ( )
70
70
. map ( |boxed| * boxed)
@@ -87,7 +87,7 @@ impl Extensions {
87
87
self . map
88
88
. as_ref ( )
89
89
. and_then ( |map| map. get ( & TypeId :: of :: < T > ( ) ) )
90
- . and_then ( |boxed| ( & * * boxed as & ( dyn Any + ' static ) ) . downcast_ref ( ) )
90
+ . and_then ( |boxed| ( & * * boxed) . as_any ( ) . downcast_ref ( ) )
91
91
}
92
92
93
93
/// Get a mutable reference to a type previously inserted on this `Extensions`.
@@ -106,7 +106,7 @@ impl Extensions {
106
106
self . map
107
107
. as_mut ( )
108
108
. and_then ( |map| map. get_mut ( & TypeId :: of :: < T > ( ) ) )
109
- . and_then ( |boxed| ( & mut * * boxed as & mut ( dyn Any + ' static ) ) . downcast_mut ( ) )
109
+ . and_then ( |boxed| ( & mut * * boxed) . as_any_mut ( ) . downcast_mut ( ) )
110
110
}
111
111
112
112
/// Remove a type from this `Extensions`.
@@ -127,7 +127,7 @@ impl Extensions {
127
127
. as_mut ( )
128
128
. and_then ( |map| map. remove ( & TypeId :: of :: < T > ( ) ) )
129
129
. and_then ( |boxed| {
130
- ( boxed as Box < dyn Any + ' static > )
130
+ boxed. into_any ( )
131
131
. downcast ( )
132
132
. ok ( )
133
133
. map ( |boxed| * boxed)
@@ -229,9 +229,42 @@ impl fmt::Debug for Extensions {
229
229
}
230
230
}
231
231
232
+ trait AnyClone : Any {
233
+ fn clone_box ( & self ) -> Box < dyn AnyClone + Send + Sync > ;
234
+ fn as_any ( & self ) -> & dyn Any ;
235
+ fn as_any_mut ( & mut self ) -> & mut dyn Any ;
236
+ fn into_any ( self : Box < Self > ) -> Box < dyn Any > ;
237
+ }
238
+
239
+ impl < T : Clone + Send + Sync + ' static > AnyClone for T {
240
+ fn clone_box ( & self ) -> Box < dyn AnyClone + Send + Sync > {
241
+ Box :: new ( self . clone ( ) )
242
+ }
243
+
244
+ fn as_any ( & self ) -> & dyn Any {
245
+ self
246
+ }
247
+
248
+ fn as_any_mut ( & mut self ) -> & mut dyn Any {
249
+ self
250
+ }
251
+
252
+ fn into_any ( self : Box < Self > ) -> Box < dyn Any > {
253
+ self
254
+ }
255
+ }
256
+
257
+ impl Clone for Box < dyn AnyClone + Send + Sync > {
258
+ fn clone ( & self ) -> Self {
259
+ ( * * self ) . clone_box ( )
260
+ }
261
+ }
262
+
263
+
264
+
232
265
#[ test]
233
266
fn test_extensions ( ) {
234
- #[ derive( Debug , PartialEq ) ]
267
+ #[ derive( Clone , Debug , PartialEq ) ]
235
268
struct MyType ( i32 ) ;
236
269
237
270
let mut extensions = Extensions :: new ( ) ;
@@ -242,9 +275,15 @@ fn test_extensions() {
242
275
assert_eq ! ( extensions. get( ) , Some ( & 5i32 ) ) ;
243
276
assert_eq ! ( extensions. get_mut( ) , Some ( & mut 5i32 ) ) ;
244
277
278
+ let ext2 = extensions. clone ( ) ;
279
+
245
280
assert_eq ! ( extensions. remove:: <i32 >( ) , Some ( 5i32 ) ) ;
246
281
assert ! ( extensions. get:: <i32 >( ) . is_none( ) ) ;
247
282
283
+ // clone still has it
284
+ assert_eq ! ( ext2. get( ) , Some ( & 5i32 ) ) ;
285
+ assert_eq ! ( ext2. get( ) , Some ( & MyType ( 10 ) ) ) ;
286
+
248
287
assert_eq ! ( extensions. get:: <bool >( ) , None ) ;
249
288
assert_eq ! ( extensions. get( ) , Some ( & MyType ( 10 ) ) ) ;
250
289
}
0 commit comments