1
+ use std:: borrow:: Cow ;
1
2
use std:: fmt;
3
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
4
+ use std:: marker:: PhantomData ;
2
5
use std:: os:: raw:: c_void;
3
6
use std:: path:: Path ;
4
7
use std:: str;
@@ -108,26 +111,83 @@ impl fmt::Debug for Symbol {
108
111
}
109
112
}
110
113
114
+ // Maybe a parsed C++ symbol, if parsing the mangled symbol as Rust failed.
115
+ #[ cfg( feature = "cpp_demangle" ) ]
116
+ struct OptionCppSymbol < ' a > ( Option < :: cpp_demangle:: BorrowedSymbol < ' a > > ) ;
117
+
118
+ #[ cfg( feature = "cpp_demangle" ) ]
119
+ impl < ' a > OptionCppSymbol < ' a > {
120
+ fn parse ( input : & ' a [ u8 ] ) -> OptionCppSymbol < ' a > {
121
+ OptionCppSymbol ( :: cpp_demangle:: BorrowedSymbol :: with_tail ( input)
122
+ . ok ( )
123
+ . map ( |( sym, _tail) | sym) )
124
+ }
125
+
126
+ fn none ( ) -> OptionCppSymbol < ' a > {
127
+ OptionCppSymbol ( None )
128
+ }
129
+
130
+ fn as_str ( & self ) -> Option < Cow < ' a , str > > {
131
+ self . 0 . as_ref ( ) . map ( |cpp| Cow :: from ( format ! ( "{}" , cpp) ) )
132
+ }
133
+ }
134
+
135
+ // Make sure to keep this zero-sized, so that the `cpp_demangle` feature has no
136
+ // cost when disabled.
137
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
138
+ struct OptionCppSymbol < ' a > ( PhantomData < & ' a ( ) > ) ;
139
+
140
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
141
+ impl < ' a > OptionCppSymbol < ' a > {
142
+ fn parse ( input : & ' a [ u8 ] ) -> OptionCppSymbol < ' a > {
143
+ OptionCppSymbol ( PhantomData )
144
+ }
145
+
146
+ fn none ( ) -> OptionCppSymbol < ' a > {
147
+ OptionCppSymbol ( PhantomData )
148
+ }
149
+
150
+ fn as_str ( & self ) -> Option < Cow < ' a , str > > {
151
+ None
152
+ }
153
+ }
154
+
111
155
/// A wrapper around a symbol name to provide ergonomic accessors to the
112
156
/// demangled name, the raw bytes, the raw string, etc.
157
+ #[ cfg( feature = "cpp_demangle" ) ]
113
158
pub struct SymbolName < ' a > {
114
159
bytes : & ' a [ u8 ] ,
115
160
demangled : Option < Demangle < ' a > > ,
161
+ cpp_demangled : OptionCppSymbol < ' a > ,
116
162
}
117
163
118
164
impl < ' a > SymbolName < ' a > {
119
165
/// Creates a new symbol name from the raw underlying bytes.
120
166
pub fn new ( bytes : & ' a [ u8 ] ) -> SymbolName < ' a > {
121
167
let demangled = str:: from_utf8 ( bytes) . ok ( ) . map ( demangle) ;
168
+
169
+ // Only try and parse a C++ symbol if we didn't parse a Rust symbol.
170
+ let cpp = if demangled. is_none ( ) {
171
+ OptionCppSymbol :: parse ( bytes)
172
+ } else {
173
+ OptionCppSymbol :: none ( )
174
+ } ;
175
+
122
176
SymbolName {
123
177
bytes : bytes,
124
178
demangled : demangled,
179
+ cpp_demangled : cpp,
125
180
}
126
181
}
127
182
128
- /// Returns the raw symbol name as `&str` if the symbols is valid utf-8.
129
- pub fn as_str ( & self ) -> Option < & ' a str > {
130
- self . demangled . as_ref ( ) . map ( |s| s. as_str ( ) )
183
+ /// Returns the raw symbol name as a `str` if the symbols is valid utf-8.
184
+ pub fn as_str ( & self ) -> Option < Cow < ' a , str > > {
185
+ self . demangled
186
+ . as_ref ( )
187
+ . map ( |s| Cow :: from ( s. as_str ( ) ) )
188
+ . or_else ( || {
189
+ self . cpp_demangled . as_str ( )
190
+ } )
131
191
}
132
192
133
193
/// Returns the raw symbol name as a list of bytes
@@ -137,6 +197,18 @@ impl<'a> SymbolName<'a> {
137
197
}
138
198
139
199
impl < ' a > fmt:: Display for SymbolName < ' a > {
200
+ #[ cfg( feature = "cpp_demangle" ) ]
201
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
202
+ if let Some ( ref s) = self . demangled {
203
+ s. fmt ( f)
204
+ } else if let Some ( ref cpp) = self . cpp_demangled . 0 {
205
+ cpp. fmt ( f)
206
+ } else {
207
+ String :: from_utf8_lossy ( self . bytes ) . fmt ( f)
208
+ }
209
+ }
210
+
211
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
140
212
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
141
213
if let Some ( ref s) = self . demangled {
142
214
s. fmt ( f)
@@ -147,6 +219,18 @@ impl<'a> fmt::Display for SymbolName<'a> {
147
219
}
148
220
149
221
impl < ' a > fmt:: Debug for SymbolName < ' a > {
222
+ #[ cfg( feature = "cpp_demangle" ) ]
223
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
224
+ if let Some ( ref s) = self . demangled {
225
+ s. fmt ( f)
226
+ } else if let Some ( ref cpp) = self . cpp_demangled . 0 {
227
+ cpp. fmt ( f)
228
+ } else {
229
+ String :: from_utf8_lossy ( self . bytes ) . fmt ( f)
230
+ }
231
+ }
232
+
233
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
150
234
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
151
235
if let Some ( ref s) = self . demangled {
152
236
s. fmt ( f)
@@ -185,4 +269,3 @@ cfg_if! {
185
269
use self :: noop:: Symbol as SymbolImp ;
186
270
}
187
271
}
188
-
0 commit comments