@@ -81,7 +81,7 @@ unsafe impl Sync for RcStr {}
81
81
82
82
// Marks a payload that is stored in an Arc
83
83
const DYNAMIC_TAG : u8 = 0b_00 ;
84
- const DYNAMIC_LOCATION : u8 = 0b_0 ;
84
+ const PREHASHED_STRING_LOCATION : u8 = 0b_0 ;
85
85
// Marks a payload that has been leaked since it has a static lifetime
86
86
const STATIC_TAG : u8 = 0b_10 ;
87
87
// The payload is stored inline
@@ -107,21 +107,22 @@ impl RcStr {
107
107
#[ inline( never) ]
108
108
pub fn as_str ( & self ) -> & str {
109
109
match self . location ( ) {
110
- DYNAMIC_LOCATION => self . dynamic_as_str ( ) ,
110
+ PREHASHED_STRING_LOCATION => self . prehashed_string_as_str ( ) ,
111
111
INLINE_LOCATION => self . inline_as_str ( ) ,
112
112
_ => unsafe { debug_unreachable ! ( ) } ,
113
113
}
114
114
}
115
115
116
116
fn inline_as_str ( & self ) -> & str {
117
+ debug_assert ! ( self . location( ) == INLINE_LOCATION ) ;
117
118
let len = ( self . unsafe_data . tag_byte ( ) & LEN_MASK ) >> LEN_OFFSET ;
118
119
let src = self . unsafe_data . data ( ) ;
119
120
unsafe { std:: str:: from_utf8_unchecked ( & src[ ..( len as usize ) ] ) }
120
121
}
121
122
122
- // Extract the str reference from a string stored in a dynamic location
123
- fn dynamic_as_str ( & self ) -> & str {
124
- debug_assert ! ( self . location( ) == DYNAMIC_LOCATION ) ;
123
+ // Extract the str reference from a string stored in a PrehashedString
124
+ fn prehashed_string_as_str ( & self ) -> & str {
125
+ debug_assert ! ( self . location( ) == PREHASHED_STRING_LOCATION ) ;
125
126
unsafe { dynamic:: deref_from ( self . unsafe_data ) . value . as_str ( ) }
126
127
}
127
128
@@ -143,7 +144,7 @@ impl RcStr {
143
144
}
144
145
}
145
146
INLINE_TAG => self . inline_as_str ( ) . to_string ( ) ,
146
- STATIC_TAG => self . dynamic_as_str ( ) . to_string ( ) ,
147
+ STATIC_TAG => self . prehashed_string_as_str ( ) . to_string ( ) ,
147
148
_ => unsafe { debug_unreachable ! ( ) } ,
148
149
}
149
150
}
@@ -278,6 +279,8 @@ impl Clone for RcStr {
278
279
#[ inline( always) ]
279
280
fn clone ( & self ) -> Self {
280
281
let alias = self . unsafe_data ;
282
+ // We only need to increment the ref count for DYNAMIC_TAG values
283
+ // For STATIC_TAG and INLINE_TAG we can just copy the value.
281
284
if alias. tag_byte ( ) & TAG_MASK == DYNAMIC_TAG {
282
285
unsafe {
283
286
let arc = dynamic:: restore_arc ( alias) ;
@@ -305,7 +308,7 @@ impl PartialEq for RcStr {
305
308
}
306
309
// They can still be equal if they are both stored on the heap
307
310
match ( self . location ( ) , other. location ( ) ) {
308
- ( DYNAMIC_LOCATION , DYNAMIC_LOCATION ) => {
311
+ ( PREHASHED_STRING_LOCATION , PREHASHED_STRING_LOCATION ) => {
309
312
let l = unsafe { deref_from ( self . unsafe_data ) } ;
310
313
let r = unsafe { deref_from ( other. unsafe_data ) } ;
311
314
l. hash == r. hash && l. value == r. value
@@ -334,7 +337,7 @@ impl Ord for RcStr {
334
337
impl Hash for RcStr {
335
338
fn hash < H : Hasher > ( & self , state : & mut H ) {
336
339
match self . location ( ) {
337
- DYNAMIC_LOCATION => {
340
+ PREHASHED_STRING_LOCATION => {
338
341
let l = unsafe { deref_from ( self . unsafe_data ) } ;
339
342
state. write_u64 ( l. hash ) ;
340
343
state. write_u8 ( 0xff ) ;
@@ -362,8 +365,15 @@ impl<'de> Deserialize<'de> for RcStr {
362
365
363
366
impl Drop for RcStr {
364
367
fn drop ( & mut self ) {
365
- if self . tag ( ) == DYNAMIC_TAG {
366
- unsafe { drop ( dynamic:: restore_arc ( self . unsafe_data ) ) }
368
+ match self . tag ( ) {
369
+ DYNAMIC_TAG => unsafe { drop ( dynamic:: restore_arc ( self . unsafe_data ) ) } ,
370
+ STATIC_TAG => {
371
+ // do nothing, these are never deallocated
372
+ }
373
+ INLINE_TAG => {
374
+ // do nothing, these payloads need no drop logic
375
+ }
376
+ _ => unsafe { debug_unreachable ! ( ) } ,
367
377
}
368
378
}
369
379
}
0 commit comments