33use std:: {
44 any:: Any ,
55 hash:: { Hash , Hasher } ,
6- marker:: PhantomData ,
76} ;
87
98pub trait DynEq : Any {
4847 }
4948}
5049
51- #[ doc( hidden) ]
52- /// A string slice, stuffed with a payload of data `16` bits long.
53- /// This means that the maximum length of the string is `2^(size-16)`,
54- /// where `size` is either 32 or 64 depending on your computer.
55- #[ derive( Clone , Copy ) ]
56- pub struct StuffedStr < ' a > {
57- ptr : * const u8 ,
58- marker : PhantomData < & ' a str > ,
59-
60- /// lower 16 bits stores the data,
61- /// upper 48 or 16 bits stores the length of the string.
62- /// This layout optimizes for calling `.data()`
63- meta : usize ,
64- }
65-
66- unsafe impl < ' a > Send for StuffedStr < ' a > { }
67- unsafe impl < ' a > Sync for StuffedStr < ' a > { }
68-
69- /// Truncates the passed string slice to be of length `len`, or shorter.
70- #[ cold]
71- #[ inline( never) ]
72- fn truncate ( str : & str , mut len : usize ) -> & str {
73- // Just keep lowering the expected length until we hit a unicode boundary.
74- // This is messy but if the string is long enough that we need to truncate it,
75- // it's too long for anyone to notice what the end looks like.
76- loop {
77- if let Some ( str) = str. get ( ..len) {
78- break str;
79- }
80- // In practice this won't be able to underflow, since `str.get(..0)` will always succeed.
81- len -= 1 ;
82- }
83- }
84-
85- impl < ' a > StuffedStr < ' a > {
86- const DATA_MASK : usize = !Self :: LEN_MASK ;
87- const LEN_MASK : usize = !0 << 16 ;
88-
89- pub fn new ( mut str : & ' a str , data : u16 ) -> Self {
90- // Make sure there's enough room to store the data.
91- if str. len ( ) . leading_zeros ( ) < 16 {
92- str = truncate ( str, Self :: LEN_MASK >> 16 ) ;
93- debug_assert ! ( str . len( ) . leading_zeros( ) < 16 ) ;
94- }
95- let ptr = str. as_ptr ( ) ;
96- let meta = data as usize | str. len ( ) << 16 ;
97- Self {
98- ptr,
99- marker : PhantomData ,
100- meta,
101- }
102- }
103-
104- #[ inline]
105- fn len ( & self ) -> usize {
106- self . meta >> 16
107- }
108- #[ inline]
109- pub fn data ( & self ) -> u16 {
110- let data = self . meta & Self :: DATA_MASK ;
111- data as u16
112- }
113- #[ inline]
114- pub fn as_str ( & self ) -> & ' a str {
115- // SAFETY: this instance was constructed from a string slice of length `len`, and lifetime `'a`.
116- // It is sound to convert it back to a slice.
117- unsafe {
118- let slice = std:: slice:: from_raw_parts ( self . ptr , self . len ( ) ) ;
119- std:: str:: from_utf8_unchecked ( slice)
120- }
121- }
122- }
123-
12450/// Macro to define a new label trait
12551///
12652/// # Example
@@ -145,11 +71,12 @@ macro_rules! define_label {
14571 ) => {
14672 $( #[ $id_attr] ) *
14773 #[ derive( Clone , Copy ) ]
148- pub struct $id_name( :: core :: any:: TypeId , $crate :: label :: StuffedStr < ' static > ) ;
74+ pub struct $id_name( :: std :: any:: TypeId , u64 , fn ( u64 , & mut :: std :: fmt :: Formatter ) -> :: std :: fmt :: Result ) ;
14975
150- impl :: core:: fmt:: Debug for $id_name {
151- fn fmt( & self , f: & mut :: core:: fmt:: Formatter ) -> :: core:: fmt:: Result {
152- write!( f, "{}" , self . as_str( ) )
76+ impl :: std:: fmt:: Debug for $id_name {
77+ fn fmt( & self , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
78+ let data = self . data( ) ;
79+ self . dbg( ) ( data, f)
15380 }
15481 }
15582
@@ -159,22 +86,17 @@ macro_rules! define_label {
15986 fn as_label( & self ) -> $id_name {
16087 let ty = self . type_id( ) ;
16188 let data = self . data( ) ;
162- let text = self . as_str( ) ;
163- let stuffed = $crate:: label:: StuffedStr :: new( text, data) ;
164- $id_name( ty, stuffed)
89+ let dbg = self . dbg( ) ;
90+ $id_name( ty, data, dbg)
16591 }
16692 /// Returns the [`TypeId`] used to differentiate labels.
16793 #[ inline]
168- fn type_id( & self ) -> :: core :: any:: TypeId {
169- :: core :: any:: TypeId :: of:: <Self >( )
94+ fn type_id( & self ) -> :: std :: any:: TypeId {
95+ :: std :: any:: TypeId :: of:: <Self >( )
17096 }
17197 /// Returns a number used to distinguish different labels of the same type.
172- fn data( & self ) -> u16 ;
173- /// Returns the representation of this label as a string literal.
174- ///
175- /// In cases where you absolutely need a label to be determined at runtime,
176- /// you can use [`Box::leak`] to get a `'static` reference.
177- fn as_str( & self ) -> & ' static str ;
98+ fn data( & self ) -> u64 ;
99+ fn dbg( & self ) -> fn ( u64 , & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result ;
178100 }
179101
180102 impl $label_name for $id_name {
@@ -183,15 +105,16 @@ macro_rules! define_label {
183105 * self
184106 }
185107 #[ inline]
186- fn type_id( & self ) -> :: core :: any:: TypeId {
108+ fn type_id( & self ) -> :: std :: any:: TypeId {
187109 self . 0
188110 }
189111 #[ inline]
190- fn data( & self ) -> u16 {
191- self . 1 . data ( )
112+ fn data( & self ) -> u64 {
113+ self . 1
192114 }
193- fn as_str( & self ) -> & ' static str {
194- self . 1 . as_str( )
115+ #[ inline]
116+ fn dbg( & self ) -> fn ( u64 , & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
117+ self . 2
195118 }
196119 }
197120
@@ -212,18 +135,3 @@ macro_rules! define_label {
212135 }
213136 } ;
214137}
215-
216- #[ cfg( test) ]
217- mod tests {
218- use super :: * ;
219-
220- #[ test]
221- fn test_truncate ( ) {
222- // Slice at byte '4'
223- assert_eq ! ( truncate( "Hello, World!" , 4 ) , "Hell" ) ;
224-
225- // Slicing off at byte '3' would be inside of the emoji,
226- // so instead the whole emoji gets sliced off.
227- assert_eq ! ( truncate( "x😂" , 3 ) , "x" ) ;
228- }
229- }
0 commit comments