@@ -23,19 +23,19 @@ use std::ops;
23
23
use std:: ptr;
24
24
use std:: slice;
25
25
use std:: str;
26
+ use std:: hash:: Hash ;
27
+ use std:: marker:: PhantomData ;
26
28
use std:: sync:: Mutex ;
27
29
use std:: sync:: atomic:: AtomicIsize ;
28
30
use std:: sync:: atomic:: Ordering :: SeqCst ;
29
31
30
32
use shared:: { STATIC_TAG , INLINE_TAG , DYNAMIC_TAG , TAG_MASK , MAX_INLINE_LEN , STATIC_SHIFT_BITS ,
31
- ENTRY_ALIGNMENT , pack_static, StaticAtomSet } ;
33
+ ENTRY_ALIGNMENT , pack_static, dynamic_hash } ;
32
34
use self :: UnpackedAtom :: { Dynamic , Inline , Static } ;
33
35
34
36
#[ cfg( feature = "log-events" ) ]
35
37
use event:: Event ;
36
38
37
- include ! ( concat!( env!( "OUT_DIR" ) , "/static_atom_set.rs" ) ) ;
38
-
39
39
#[ cfg( not( feature = "log-events" ) ) ]
40
40
macro_rules! log ( ( $e: expr) => ( ( ) ) ) ;
41
41
@@ -160,29 +160,58 @@ impl StringCache {
160
160
}
161
161
}
162
162
163
+ pub trait Kind : Eq + Hash + Ord + PartialEq + PartialOrd {
164
+ #[ inline]
165
+ fn get_index_or_hash ( s : & str ) -> Result < u32 , u64 > ;
166
+
167
+ #[ inline]
168
+ fn index ( i : u32 ) -> Option < & ' static str > ;
169
+ }
170
+
171
+ // Although DefaultKind isn't used right now, it will be when ServoAtomKind is
172
+ // removed. Note it will only be used for dynamic atoms.
173
+ #[ derive( Eq , Hash , Ord , PartialEq , PartialOrd ) ]
174
+ pub enum DefaultKind { }
175
+ impl Kind for DefaultKind {
176
+ // There are no static atoms for DefaultKind so there's never an index
177
+ #[ inline]
178
+ fn get_index_or_hash ( s : & str ) -> Result < u32 , u64 > {
179
+ Err ( dynamic_hash ( s) )
180
+ }
181
+
182
+ #[ inline]
183
+ fn index ( _: u32 ) -> Option < & ' static str > {
184
+ None
185
+ }
186
+ }
187
+
188
+ pub type Atom = BaseAtom < super :: ServoAtomKind > ;
189
+
163
190
// NOTE: Deriving Eq here implies that a given string must always
164
- // be interned the same way.
191
+ // be interned the same way for the same kind .
165
192
#[ cfg_attr( feature = "unstable" , unsafe_no_drop_flag) ] // See tests::atom_drop_is_idempotent
166
193
#[ cfg_attr( feature = "heap_size" , derive( HeapSizeOf ) ) ]
167
194
#[ derive( Eq , Hash , PartialEq ) ]
168
- pub struct Atom {
195
+ // After RFC 213, rename `BaseAtom` to `Atom` and use `K=super::ServoAtomKind`.
196
+ pub struct BaseAtom < K > where K : Kind {
169
197
/// This field is public so that the `atom!()` macro can use it.
170
198
/// You should not otherwise access this field.
171
199
pub data : u64 ,
200
+ pub kind : PhantomData < K > ,
172
201
}
173
202
174
- impl Atom {
203
+ impl < K > BaseAtom < K > where K : Kind {
175
204
#[ inline( always) ]
176
205
unsafe fn unpack ( & self ) -> UnpackedAtom {
177
206
UnpackedAtom :: from_packed ( self . data )
178
207
}
179
208
}
180
209
181
- impl < ' a > From < Cow < ' a , str > > for Atom {
210
+ impl < ' a , K > From < Cow < ' a , str > > for BaseAtom < K > where K : Kind {
182
211
#[ inline]
183
- fn from ( string_to_add : Cow < ' a , str > ) -> Atom {
184
- let unpacked = match STATIC_ATOM_SET . get_index_or_hash ( & * string_to_add) {
185
- Ok ( id) => Static ( id as u32 ) ,
212
+ fn from ( string_to_add : Cow < ' a , str > ) -> BaseAtom < K > {
213
+ let unpacked = match K :: get_index_or_hash ( & * string_to_add) {
214
+ Ok ( id) => Static ( id) ,
186
215
Err ( hash) => {
187
216
let len = string_to_add. len ( ) ;
188
217
if len <= MAX_INLINE_LEN {
@@ -197,27 +226,27 @@ impl<'a> From<Cow<'a, str>> for Atom {
197
226
198
227
let data = unsafe { unpacked. pack ( ) } ;
199
228
log ! ( Event :: Intern ( data) ) ;
200
- Atom { data : data }
229
+ BaseAtom { data : data, kind : PhantomData }
201
230
}
202
231
}
203
232
204
- impl < ' a > From < & ' a str > for Atom {
233
+ impl < ' a , K > From < & ' a str > for BaseAtom < K > where K : Kind {
205
234
#[ inline]
206
- fn from ( string_to_add : & str ) -> Atom {
207
- Atom :: from ( Cow :: Borrowed ( string_to_add) )
235
+ fn from ( string_to_add : & str ) -> BaseAtom < K > {
236
+ BaseAtom :: from ( Cow :: Borrowed ( string_to_add) )
208
237
}
209
238
}
210
239
211
- impl From < String > for Atom {
240
+ impl < K > From < String > for BaseAtom < K > where K : Kind {
212
241
#[ inline]
213
- fn from ( string_to_add : String ) -> Atom {
214
- Atom :: from ( Cow :: Owned ( string_to_add) )
242
+ fn from ( string_to_add : String ) -> BaseAtom < K > {
243
+ BaseAtom :: from ( Cow :: Owned ( string_to_add) )
215
244
}
216
245
}
217
246
218
- impl Clone for Atom {
247
+ impl < K > Clone for BaseAtom < K > where K : Kind {
219
248
#[ inline( always) ]
220
- fn clone ( & self ) -> Atom {
249
+ fn clone ( & self ) -> BaseAtom < K > {
221
250
unsafe {
222
251
match from_packed_dynamic ( self . data ) {
223
252
Some ( entry) => {
@@ -227,17 +256,18 @@ impl Clone for Atom {
227
256
None => ( ) ,
228
257
}
229
258
}
230
- Atom {
231
- data : self . data
259
+ BaseAtom {
260
+ data : self . data ,
261
+ kind : PhantomData ,
232
262
}
233
263
}
234
264
}
235
265
236
- impl Drop for Atom {
266
+ impl < K > Drop for BaseAtom < K > where K : Kind {
237
267
#[ inline]
238
268
fn drop ( & mut self ) {
239
269
// Out of line to guide inlining.
240
- fn drop_slow ( this : & mut Atom ) {
270
+ fn drop_slow < K > ( this : & mut BaseAtom < K > ) where K : Kind {
241
271
STRING_CACHE . lock ( ) . unwrap ( ) . remove ( this. data ) ;
242
272
}
243
273
@@ -256,7 +286,7 @@ impl Drop for Atom {
256
286
}
257
287
258
288
259
- impl ops:: Deref for Atom {
289
+ impl < K > ops:: Deref for BaseAtom < K > where K : Kind {
260
290
type Target = str ;
261
291
262
292
#[ inline]
@@ -267,7 +297,7 @@ impl ops::Deref for Atom {
267
297
let buf = inline_orig_bytes ( & self . data ) ;
268
298
str:: from_utf8 ( buf) . unwrap ( )
269
299
} ,
270
- Static ( idx) => STATIC_ATOM_SET . index ( idx) . expect ( "bad static atom" ) ,
300
+ Static ( idx) => K :: index ( idx) . expect ( "bad static atom" ) ,
271
301
Dynamic ( entry) => {
272
302
let entry = entry as * mut StringCacheEntry ;
273
303
& ( * entry) . string
@@ -277,14 +307,14 @@ impl ops::Deref for Atom {
277
307
}
278
308
}
279
309
280
- impl fmt:: Display for Atom {
310
+ impl < K > fmt:: Display for BaseAtom < K > where K : Kind {
281
311
#[ inline]
282
312
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
283
313
<str as fmt:: Display >:: fmt ( self , f)
284
314
}
285
315
}
286
316
287
- impl fmt:: Debug for Atom {
317
+ impl < K > fmt:: Debug for BaseAtom < K > where K : Kind {
288
318
#[ inline]
289
319
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
290
320
let ty_str = unsafe {
@@ -299,63 +329,63 @@ impl fmt::Debug for Atom {
299
329
}
300
330
}
301
331
302
- impl PartialOrd for Atom {
332
+ impl < K > PartialOrd for BaseAtom < K > where K : Kind {
303
333
#[ inline]
304
- fn partial_cmp ( & self , other : & Atom ) -> Option < Ordering > {
334
+ fn partial_cmp ( & self , other : & BaseAtom < K > ) -> Option < Ordering > {
305
335
if self . data == other. data {
306
336
return Some ( Equal ) ;
307
337
}
308
338
self . as_ref ( ) . partial_cmp ( other. as_ref ( ) )
309
339
}
310
340
}
311
341
312
- impl Ord for Atom {
342
+ impl < K > Ord for BaseAtom < K > where K : Kind {
313
343
#[ inline]
314
- fn cmp ( & self , other : & Atom ) -> Ordering {
344
+ fn cmp ( & self , other : & BaseAtom < K > ) -> Ordering {
315
345
if self . data == other. data {
316
346
return Equal ;
317
347
}
318
348
self . as_ref ( ) . cmp ( other. as_ref ( ) )
319
349
}
320
350
}
321
351
322
- impl AsRef < str > for Atom {
352
+ impl < K > AsRef < str > for BaseAtom < K > where K : Kind {
323
353
fn as_ref ( & self ) -> & str {
324
354
& self
325
355
}
326
356
}
327
357
328
- impl Serialize for Atom {
358
+ impl < K > Serialize for BaseAtom < K > where K : Kind {
329
359
fn serialize < S > ( & self , serializer : & mut S ) -> Result < ( ) , S :: Error > where S : Serializer {
330
360
let string: & str = self . as_ref ( ) ;
331
361
string. serialize ( serializer)
332
362
}
333
363
}
334
364
335
- impl Deserialize for Atom {
336
- fn deserialize < D > ( deserializer : & mut D ) -> Result < Atom , D :: Error > where D : Deserializer {
365
+ impl < K > Deserialize for BaseAtom < K > where K : Kind {
366
+ fn deserialize < D > ( deserializer : & mut D ) -> Result < BaseAtom < K > , D :: Error > where D : Deserializer {
337
367
let string: String = try!( Deserialize :: deserialize ( deserializer) ) ;
338
- Ok ( Atom :: from ( & * string) )
368
+ Ok ( BaseAtom :: from ( & * string) )
339
369
}
340
370
}
341
371
342
372
// AsciiExt requires mutating methods, so we just implement the non-mutating ones.
343
373
// We don't need to implement is_ascii because there's no performance improvement
344
374
// over the one from &str.
345
- impl Atom {
346
- pub fn to_ascii_uppercase ( & self ) -> Atom {
375
+ impl < K > BaseAtom < K > where K : Kind {
376
+ pub fn to_ascii_uppercase ( & self ) -> BaseAtom < K > {
347
377
if self . chars ( ) . all ( char:: is_uppercase) {
348
378
self . clone ( )
349
379
} else {
350
- Atom :: from ( & * ( ( & * * self ) . to_ascii_uppercase ( ) ) )
380
+ BaseAtom :: from ( & * ( ( & * * self ) . to_ascii_uppercase ( ) ) )
351
381
}
352
382
}
353
383
354
- pub fn to_ascii_lowercase ( & self ) -> Atom {
384
+ pub fn to_ascii_lowercase ( & self ) -> BaseAtom < K > {
355
385
if self . chars ( ) . all ( char:: is_lowercase) {
356
386
self . clone ( )
357
387
} else {
358
- Atom :: from ( & * ( ( & * * self ) . to_ascii_lowercase ( ) ) )
388
+ BaseAtom :: from ( & * ( ( & * * self ) . to_ascii_lowercase ( ) ) )
359
389
}
360
390
}
361
391
@@ -486,7 +516,8 @@ mod bench;
486
516
mod tests {
487
517
use std:: mem;
488
518
use std:: thread;
489
- use super :: { Atom , StringCacheEntry , STATIC_ATOM_SET } ;
519
+ use super :: { Atom , StringCacheEntry } ;
520
+ use super :: super :: STATIC_ATOM_SET ;
490
521
use super :: UnpackedAtom :: { Dynamic , Inline , Static } ;
491
522
use shared:: ENTRY_ALIGNMENT ;
492
523
0 commit comments