@@ -56,6 +56,12 @@ pub trait LabelDowncast<Id> {
56
56
fn downcast_from ( data : u64 ) -> Option < Self :: Output > ;
57
57
}
58
58
59
+ #[ doc( hidden) ]
60
+ pub struct VTable {
61
+ pub ty : fn ( ) -> :: std:: any:: TypeId ,
62
+ pub fmt : fn ( u64 , & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result ,
63
+ }
64
+
59
65
/// Macro to define a new label trait
60
66
///
61
67
/// # Example
@@ -81,25 +87,30 @@ macro_rules! define_label {
81
87
$( #[ $id_attr] ) *
82
88
#[ derive( Clone , Copy ) ]
83
89
pub struct $id_name {
84
- ty: :: std:: any:: TypeId ,
85
90
data: u64 ,
86
- f : fn ( u64 , & mut :: std :: fmt :: Formatter ) -> :: std :: fmt :: Result ,
91
+ vtable : & ' static $crate :: label :: VTable ,
87
92
}
88
93
89
94
impl :: std:: fmt:: Debug for $id_name {
90
95
fn fmt( & self , f: & mut :: std:: fmt:: Formatter ) -> :: std:: fmt:: Result {
91
96
let data = self . data( ) ;
92
- ( self . f ) ( data, f)
97
+ ( self . vtable . fmt ) ( data, f)
93
98
}
94
99
}
95
100
96
101
$( #[ $label_attr] ) *
97
102
pub trait $label_name: ' static {
103
+ /// Essentially acts like a dynamic dispatch virtual table,
104
+ /// but specialized for labels.
105
+ const VTABLE : $crate:: label:: VTable = $crate:: label:: VTable {
106
+ ty: || :: std:: any:: TypeId :: of:: <Self >( ) ,
107
+ fmt: Self :: fmt,
108
+ } ;
98
109
/// Converts this type into an opaque, strongly-typed label.
99
110
#[ inline]
100
111
fn as_label( & self ) -> $id_name {
101
112
let data = self . data( ) ;
102
- $id_name { data, ty : :: std :: any :: TypeId :: of :: < Self > ( ) , f : Self :: fmt }
113
+ $id_name { data, vtable : & Self :: VTABLE }
103
114
}
104
115
/// Returns a number used to distinguish different labels of the same type.
105
116
fn data( & self ) -> u64 ;
@@ -129,23 +140,30 @@ macro_rules! define_label {
129
140
impl PartialEq for $id_name {
130
141
#[ inline]
131
142
fn eq( & self , rhs: & Self ) -> bool {
132
- self . ty == rhs. ty && self . data ( ) == rhs. data ( )
143
+ self . data ( ) == rhs. data ( ) && self . type_id ( ) == rhs. type_id ( )
133
144
}
134
145
}
135
146
impl Eq for $id_name { }
136
147
137
148
138
149
impl std:: hash:: Hash for $id_name {
139
150
fn hash<H : std:: hash:: Hasher >( & self , state: & mut H ) {
140
- self . ty . hash( state) ;
151
+ self . type_id ( ) . hash( state) ;
141
152
self . data( ) . hash( state) ;
142
153
}
143
154
}
144
155
145
156
impl $id_name {
157
+ /// Returns the [`TypeId`] of the label from which this ID was constructed.
158
+ ///
159
+ /// [`TypeId`]: ::std::any::TypeId
160
+ #[ inline]
161
+ pub fn type_id( self ) -> :: std:: any:: TypeId {
162
+ ( self . vtable. ty) ( )
163
+ }
146
164
/// Returns true if this label was constructed from an instance of type `L`.
147
165
pub fn is<L : $label_name>( self ) -> bool {
148
- self . ty == :: std:: any:: TypeId :: of:: <L >( )
166
+ self . type_id ( ) == :: std:: any:: TypeId :: of:: <L >( )
149
167
}
150
168
/// Attempts to downcast this label to type `L`.
151
169
///
0 commit comments