1
+ use bumpalo:: Bump ;
1
2
use hashbrown:: HashSet ;
2
3
use std:: sync:: Mutex ;
3
4
@@ -16,8 +17,25 @@ macro_rules! intern {
16
17
where
17
18
D : serde:: de:: Deserializer <' de>,
18
19
{
19
- let s: & ' de str = <& ' de str >:: deserialize( deserializer) ?;
20
- Ok ( $crate:: intern:: intern:: <$for_ty>( s) )
20
+ use serde:: de:: Visitor ;
21
+ use std:: fmt;
22
+ struct InternVisitor ;
23
+ impl <' de> Visitor <' de> for InternVisitor {
24
+ type Value = $for_ty;
25
+
26
+ fn expecting( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
27
+ f. write_str( concat!( "a string (" , stringify!( $for_ty) , ")" ) )
28
+ }
29
+
30
+ fn visit_str<E >( self , s: & str ) -> Result <$for_ty, E > {
31
+ Ok ( $crate:: intern:: intern:: <$for_ty>( s) )
32
+ }
33
+
34
+ fn visit_borrowed_str<E >( self , s: & ' de str ) -> Result <$for_ty, E > {
35
+ Ok ( $crate:: intern:: intern:: <$for_ty>( s) )
36
+ }
37
+ }
38
+ deserializer. deserialize_str( InternVisitor )
21
39
}
22
40
}
23
41
@@ -48,18 +66,15 @@ macro_rules! intern {
48
66
}
49
67
50
68
lazy_static:: lazy_static! {
51
- static ref INTERNED : Mutex <HashSet <& ' static str >>
52
- = Mutex :: new( HashSet :: new( ) ) ;
69
+ static ref INTERNED : Mutex <( HashSet <& ' static str >, Bump ) >
70
+ = Mutex :: new( ( HashSet :: new( ) , Bump :: new ( ) ) ) ;
53
71
}
54
72
55
73
pub fn intern < T : InternString > ( value : & str ) -> T {
56
- let mut set = INTERNED . lock ( ) . unwrap ( ) ;
74
+ let mut guard = INTERNED . lock ( ) . unwrap ( ) ;
57
75
58
- if let Some ( interned) = set. get ( value) {
59
- T :: to_interned ( interned)
60
- } else {
61
- let v: & ' static str = Box :: leak ( value. to_owned ( ) . into_boxed_str ( ) ) ;
62
- set. insert ( v) ;
63
- T :: to_interned ( v)
64
- }
76
+ let ( ref mut set, ref arena) = & mut * guard;
77
+ T :: to_interned ( set. get_or_insert_with ( value, |_| -> & ' static str {
78
+ unsafe { std:: mem:: transmute :: < & str , & ' static str > ( arena. alloc_str ( value) ) }
79
+ } ) )
65
80
}
0 commit comments