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,82 @@ 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 ( _: & ' 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.
113
157
pub struct SymbolName < ' a > {
114
158
bytes : & ' a [ u8 ] ,
115
159
demangled : Option < Demangle < ' a > > ,
160
+ cpp_demangled : OptionCppSymbol < ' a > ,
116
161
}
117
162
118
163
impl < ' a > SymbolName < ' a > {
119
164
/// Creates a new symbol name from the raw underlying bytes.
120
165
pub fn new ( bytes : & ' a [ u8 ] ) -> SymbolName < ' a > {
121
166
let demangled = str:: from_utf8 ( bytes) . ok ( ) . map ( demangle) ;
167
+
168
+ // Only try and parse a C++ symbol if we didn't parse a Rust symbol.
169
+ let cpp = if demangled. is_none ( ) {
170
+ OptionCppSymbol :: parse ( bytes)
171
+ } else {
172
+ OptionCppSymbol :: none ( )
173
+ } ;
174
+
122
175
SymbolName {
123
176
bytes : bytes,
124
177
demangled : demangled,
178
+ cpp_demangled : cpp,
125
179
}
126
180
}
127
181
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 ( ) )
182
+ /// Returns the raw symbol name as a `str` if the symbols is valid utf-8.
183
+ pub fn as_str ( & self ) -> Option < Cow < ' a , str > > {
184
+ self . demangled
185
+ . as_ref ( )
186
+ . map ( |s| Cow :: from ( s. as_str ( ) ) )
187
+ . or_else ( || {
188
+ self . cpp_demangled . as_str ( )
189
+ } )
131
190
}
132
191
133
192
/// Returns the raw symbol name as a list of bytes
@@ -137,6 +196,18 @@ impl<'a> SymbolName<'a> {
137
196
}
138
197
139
198
impl < ' a > fmt:: Display for SymbolName < ' a > {
199
+ #[ cfg( feature = "cpp_demangle" ) ]
200
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
201
+ if let Some ( ref s) = self . demangled {
202
+ s. fmt ( f)
203
+ } else if let Some ( ref cpp) = self . cpp_demangled . 0 {
204
+ cpp. fmt ( f)
205
+ } else {
206
+ String :: from_utf8_lossy ( self . bytes ) . fmt ( f)
207
+ }
208
+ }
209
+
210
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
140
211
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
141
212
if let Some ( ref s) = self . demangled {
142
213
s. fmt ( f)
@@ -147,6 +218,18 @@ impl<'a> fmt::Display for SymbolName<'a> {
147
218
}
148
219
149
220
impl < ' a > fmt:: Debug for SymbolName < ' a > {
221
+ #[ cfg( feature = "cpp_demangle" ) ]
222
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
223
+ if let Some ( ref s) = self . demangled {
224
+ s. fmt ( f)
225
+ } else if let Some ( ref cpp) = self . cpp_demangled . 0 {
226
+ cpp. fmt ( f)
227
+ } else {
228
+ String :: from_utf8_lossy ( self . bytes ) . fmt ( f)
229
+ }
230
+ }
231
+
232
+ #[ cfg( not( feature = "cpp_demangle" ) ) ]
150
233
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
151
234
if let Some ( ref s) = self . demangled {
152
235
s. fmt ( f)
@@ -185,4 +268,3 @@ cfg_if! {
185
268
use self :: noop:: Symbol as SymbolImp ;
186
269
}
187
270
}
188
-
0 commit comments