@@ -14,7 +14,8 @@ use triomphe::ThinArc;
14
14
15
15
use crate :: {
16
16
tagged_value:: { TaggedValue , MAX_INLINE_LEN } ,
17
- Atom , INLINE_TAG , INLINE_TAG_INIT , LEN_OFFSET , TAG_MASK ,
17
+ wtf8:: Wtf8 ,
18
+ Atom , Wtf8Atom , INLINE_TAG , INLINE_TAG_INIT , LEN_OFFSET , TAG_MASK ,
18
19
} ;
19
20
20
21
#[ derive( PartialEq , Eq ) ]
@@ -73,6 +74,11 @@ impl AtomStore {
73
74
atom_in ( self , & text. into ( ) )
74
75
}
75
76
77
+ #[ inline( always) ]
78
+ pub fn wtf8_atom < ' a > ( & mut self , text : impl Into < Cow < ' a , Wtf8 > > ) -> Wtf8Atom {
79
+ wtf8_atom_in ( self , text. into ( ) . as_bytes ( ) )
80
+ }
81
+
76
82
fn gc ( & mut self ) {
77
83
self . data . retain ( |item, _| {
78
84
let count = ThinArc :: strong_count ( & item. 0 ) ;
@@ -94,6 +100,14 @@ pub fn global_atom_store_gc() {
94
100
} ) ;
95
101
}
96
102
103
+ pub ( crate ) fn global_wtf8_atom ( text : & [ u8 ] ) -> Wtf8Atom {
104
+ GLOBAL_DATA . with ( |global| {
105
+ let mut store = global. borrow_mut ( ) ;
106
+
107
+ wtf8_atom_in ( & mut * store, text)
108
+ } )
109
+ }
110
+
97
111
pub ( crate ) fn global_atom ( text : & str ) -> Atom {
98
112
GLOBAL_DATA . with ( |global| {
99
113
let mut store = global. borrow_mut ( ) ;
@@ -102,9 +116,7 @@ pub(crate) fn global_atom(text: &str) -> Atom {
102
116
} )
103
117
}
104
118
105
- /// This can create any kind of [Atom], although this lives in the `dynamic`
106
- /// module.
107
- fn atom_in < S > ( storage : S , text : & str ) -> Atom
119
+ fn wtf8_atom_in < S > ( storage : S , text : & [ u8 ] ) -> Wtf8Atom
108
120
where
109
121
S : Storage ,
110
122
{
@@ -115,9 +127,9 @@ where
115
127
let tag = INLINE_TAG_INIT | ( ( len as u8 ) << LEN_OFFSET ) ;
116
128
let mut unsafe_data = TaggedValue :: new_tag ( tag) ;
117
129
unsafe {
118
- unsafe_data. data_mut ( ) [ ..len] . copy_from_slice ( text. as_bytes ( ) ) ;
130
+ unsafe_data. data_mut ( ) [ ..len] . copy_from_slice ( text) ;
119
131
}
120
- return Atom { unsafe_data } ;
132
+ return Wtf8Atom { unsafe_data } ;
121
133
}
122
134
123
135
let hash = calc_hash ( text) ;
@@ -129,12 +141,22 @@ where
129
141
NonNull :: new_unchecked ( entry)
130
142
} ;
131
143
debug_assert ! ( 0 == ptr. as_ptr( ) as u8 & TAG_MASK ) ;
132
- Atom {
144
+ Wtf8Atom {
133
145
unsafe_data : TaggedValue :: new_ptr ( ptr) ,
134
146
}
135
147
}
136
148
137
- /// Attempts to construct an Atom but only if it can be constructed inline.
149
+ /// This can create any kind of [Atom], although this lives in the `dynamic`
150
+ /// module.
151
+ fn atom_in < S > ( storage : S , text : & str ) -> Atom
152
+ where
153
+ S : Storage ,
154
+ {
155
+ // SAFETY: `text` is valid UTF-8
156
+ unsafe { Atom :: from_wtf8_unchecked ( wtf8_atom_in ( storage, text. as_bytes ( ) ) ) }
157
+ }
158
+
159
+ /// Attempts to construct an [Atom] but only if it can be constructed inline.
138
160
/// This is primarily useful in constant contexts.
139
161
pub ( crate ) const fn inline_atom ( text : & str ) -> Option < Atom > {
140
162
let len = text. len ( ) ;
@@ -159,31 +181,25 @@ pub(crate) const fn inline_atom(text: &str) -> Option<Atom> {
159
181
}
160
182
161
183
trait Storage {
162
- fn insert_entry ( self , text : & str , hash : u64 ) -> Item ;
184
+ fn insert_entry ( self , text : & [ u8 ] , hash : u64 ) -> Item ;
163
185
}
164
186
165
187
impl Storage for & ' _ mut AtomStore {
166
- fn insert_entry ( self , text : & str , hash : u64 ) -> Item {
188
+ fn insert_entry ( self , text : & [ u8 ] , hash : u64 ) -> Item {
167
189
// If the text is too long, interning is not worth it.
168
190
if text. len ( ) > 512 {
169
- return Item ( ThinArc :: from_header_and_slice (
170
- Metadata { hash } ,
171
- text. as_bytes ( ) ,
172
- ) ) ;
191
+ return Item ( ThinArc :: from_header_and_slice ( Metadata { hash } , text) ) ;
173
192
}
174
193
175
194
let ( entry, _) = self
176
195
. data
177
196
. raw_entry_mut ( )
178
197
. from_hash ( hash, |key| {
179
- key. header . header . hash == hash && key. slice . eq ( text. as_bytes ( ) )
198
+ key. header . header . hash == hash && key. slice . eq ( text)
180
199
} )
181
200
. or_insert_with ( move || {
182
201
(
183
- Item ( ThinArc :: from_header_and_slice (
184
- Metadata { hash } ,
185
- text. as_bytes ( ) ,
186
- ) ) ,
202
+ Item ( ThinArc :: from_header_and_slice ( Metadata { hash } , text) ) ,
187
203
( ) ,
188
204
)
189
205
} ) ;
@@ -192,7 +208,7 @@ impl Storage for &'_ mut AtomStore {
192
208
}
193
209
194
210
#[ inline( always) ]
195
- fn calc_hash ( text : & str ) -> u64 {
211
+ fn calc_hash ( text : & [ u8 ] ) -> u64 {
196
212
let mut hasher = FxHasher :: default ( ) ;
197
213
text. hash ( & mut hasher) ;
198
214
hasher. finish ( )
0 commit comments