Skip to content

Commit dee7dbd

Browse files
committed
Remove Display impl because it violates the trait's contract.
Fixes #233
1 parent 1e679dd commit dee7dbd

File tree

10 files changed

+73
-80
lines changed

10 files changed

+73
-80
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
This crate can parse a C++ “mangled” linker symbol name into a Rust value
66
describing what the name refers to: a variable, a function, a virtual table,
7-
etc. The description type implements `Display`, producing human-readable text
8-
describing the mangled name. Debuggers and profilers can use this crate to
9-
provide more meaningful output.
7+
etc. The description type implements functions such as `demangle()`,
8+
producing human-readable text describing the mangled name. Debuggers and
9+
profilers can use this crate to provide more meaningful output.
1010

1111
C++ requires the compiler to choose names for linker symbols consistently across
1212
compilation units, so that two compilation units that have seen the same
@@ -24,9 +24,9 @@ For example, suppose a C++ compilation unit has the definition:
2424

2525
The Itanium C++ ABI specifies that the linker symbol for that function must be
2626
named `_ZN5space3fooEii`. This crate can parse that name into a Rust value
27-
representing its structure. Formatting the value with the `format!` macro or the
28-
`std::string::ToString::to_string` trait method yields the string
29-
`space::foo(int, int)`, which is more meaningful to the C++ developer.
27+
representing its structure. That Rust value can be `demangle()`d to the
28+
string `space::foo(int, int)`, which is more meaningful to the C++
29+
developer.
3030

3131
## Usage
3232

@@ -49,7 +49,7 @@ let mangled = b"_ZN5space3fooEibc";
4949
let sym = Symbol::new(&mangled[..])
5050
.expect("Could not parse mangled symbol!");
5151

52-
let demangled = sym.to_string();
52+
let demangled = sym.demangle().unwrap();
5353
assert_eq!(demangled, "space::foo(int, bool, char)");
5454
```
5555

build.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ fn generate_compatibility_tests_from_libiberty() -> io::Result<()> {
126126
"
127127
extern crate cpp_demangle;
128128
extern crate diff;
129-
use std::fmt::Write;
130129
"
131130
)?;
132131

@@ -245,12 +244,14 @@ fn test_libiberty_demangle_{}_() {{
245244
Err(e) => panic!("Should parse mangled symbol {{}}", e),
246245
}};
247246
248-
let mut actual = String::new();
249-
if let Err(e) = write!(&mut actual, "{{}}", sym) {{
250-
panic!("Error while demangling '{{}}': {{}}",
251-
mangled_str,
252-
e);
253-
}}
247+
let actual = match sym.demangle() {{
248+
Ok(a) => a,
249+
Err(e) => {{
250+
panic!("Error while demangling '{{}}': {{}}",
251+
mangled_str,
252+
e);
253+
}}
254+
}};
254255
255256
println!(" Expect demangled symbol: {{}}", expected);
256257
println!("Actually demangled symbol as: {{}}", actual);
@@ -282,7 +283,7 @@ fn test_libiberty_demangle_{}_() {{
282283
println!("");
283284
}}
284285
285-
assert_eq!(expected, actual);
286+
assert_eq!(*expected, actual);
286287
}}
287288
"###,
288289
cfg,

c_api/src/c_api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub unsafe extern "C" fn demangle(
1515
let buffer = ffi::CStr::from_ptr(buffer);
1616

1717
if let Ok((symbol, _)) = cpp_demangle::BorrowedSymbol::with_tail_and_options(&buffer.to_bytes_with_nul(), &parse_options) {
18-
return ffi::CString::new(symbol.demangle(&demangle_options).unwrap()).unwrap().into_raw();
18+
return ffi::CString::new(symbol.demangle_with_options(&demangle_options).unwrap()).unwrap().into_raw();
1919
}
2020

2121
buffer.to_owned().into_raw()

examples/cppfilt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ where
5151

5252
if let Ok((sym, tail)) = BorrowedSymbol::with_tail(&line[idx..]) {
5353
let demangled = sym
54-
.demangle(&options)
54+
.demangle_with_options(&options)
5555
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
5656
write!(out, "{}", demangled)?;
5757
line = tail;

examples/simple.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
44
let mangled = b"_ZN5space3fooEibc";
55

66
let sym = Symbol::new(&mangled[..])?;
7-
let demangled = sym.to_string();
7+
let demangled = sym.demangle()?;
88

99
println!("{}", demangled);
1010

fuzz/fuzzers/cppfilt_differential.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fuzz_target!(|data: &[u8]| {
5252
}
5353

5454
let sym = ignore_err!(cpp_demangle::Symbol::new(data));
55-
let demangled = sym.to_string();
55+
let demangled = sym.demangle().unwrap();
5656
assert_eq!(demangled.trim(), cppfilt_output.trim(),
5757
"Should demangle the input the same as `c++filt` does");
5858
});

fuzz/fuzzers/parse_and_stringify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ extern crate cpp_demangle;
44

55
fuzz_target!(|data: &[u8]| {
66
if let Ok(sym) = cpp_demangle::Symbol::new(data) {
7-
let _ = sym.to_string();
7+
let _ = sym.demangle().unwrap();
88
}
99
});

src/lib.rs

Lines changed: 31 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
//! This crate can parse a C++ “mangled” linker symbol name into a Rust value
22
//! describing what the name refers to: a variable, a function, a virtual table,
3-
//! etc. The description type implements `Display`, producing human-readable
4-
//! text describing the mangled name. Debuggers and profilers can use this crate
5-
//! to provide more meaningful output.
3+
//! etc. The description type implements functions such as `demangle()`,
4+
//! producing human-readable text describing the mangled name. Debuggers and
5+
//! profilers can use this crate to provide more meaningful output.
66
//!
77
//! C++ requires the compiler to choose names for linker symbols consistently
88
//! across compilation units, so that two compilation units that have seen the
@@ -22,8 +22,7 @@
2222
//!
2323
//! The Itanium C++ ABI specifies that the linker symbol for that function must
2424
//! be named `_ZN5space3fooEii`. This crate can parse that name into a Rust
25-
//! value representing its structure. Formatting the value with the `format!`
26-
//! macro or the `std::string::ToString::to_string` trait method yields the
25+
//! value representing its structure. That Rust value can be `demangle()`d to the
2726
//! string `space::foo(int, int)`, which is more meaningful to the C++
2827
//! developer.
2928
@@ -151,7 +150,6 @@ where
151150
///
152151
/// ```
153152
/// use cpp_demangle::Symbol;
154-
/// use std::string::ToString;
155153
///
156154
/// // First, something easy :)
157155
///
@@ -160,7 +158,7 @@ where
160158
/// let sym = Symbol::new(&mangled[..])
161159
/// .expect("Could not parse mangled symbol!");
162160
///
163-
/// let demangled = sym.to_string();
161+
/// let demangled = sym.demangle().unwrap();
164162
/// assert_eq!(demangled, "space::foo(int, bool, char)");
165163
///
166164
/// // Now let's try something a little more complicated!
@@ -171,7 +169,7 @@ where
171169
/// let sym = Symbol::new(&mangled[..])
172170
/// .expect("Could not parse mangled symbol!");
173171
///
174-
/// let demangled = sym.to_string();
172+
/// let demangled = sym.demangle().unwrap();
175173
/// assert_eq!(
176174
/// demangled,
177175
/// "JS_GetPropertyDescriptorById(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::PropertyDescriptor>)"
@@ -186,7 +184,6 @@ where
186184
///
187185
/// ```
188186
/// use cpp_demangle::{ParseOptions, Symbol};
189-
/// use std::string::ToString;
190187
///
191188
/// // First, something easy :)
192189
///
@@ -198,7 +195,7 @@ where
198195
/// let sym = Symbol::new_with_options(&mangled[..], &parse_options)
199196
/// .expect("Could not parse mangled symbol!");
200197
///
201-
/// let demangled = sym.to_string();
198+
/// let demangled = sym.demangle().unwrap();
202199
/// assert_eq!(demangled, "space::foo(int, bool, char)");
203200
///
204201
/// // Now let's try something a little more complicated!
@@ -209,7 +206,7 @@ where
209206
/// let sym = Symbol::new(&mangled[..])
210207
/// .expect("Could not parse mangled symbol!");
211208
///
212-
/// let demangled = sym.to_string();
209+
/// let demangled = sym.demangle().unwrap();
213210
/// assert_eq!(
214211
/// demangled,
215212
/// "JS_GetPropertyDescriptorById(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::PropertyDescriptor>)"
@@ -252,27 +249,40 @@ substitutions = {:#?}",
252249
Ok(symbol)
253250
}
254251

255-
/// Demangle the symbol and return it as a String.
252+
/// Demangle the symbol and return it as a String, with the default options.
253+
///
254+
/// ```
255+
/// use cpp_demangle::{DemangleOptions, Symbol};
256256
///
257-
/// Unlike the `ToString` implementation, this function allows options to
258-
/// be specified.
257+
/// let mangled = b"_ZN5space3fooEibc";
258+
///
259+
/// let sym = Symbol::new(&mangled[..])
260+
/// .expect("Could not parse mangled symbol!");
261+
///
262+
/// let demangled = sym.demangle().unwrap();
263+
/// assert_eq!(demangled, "space::foo(int, bool, char)");
264+
/// ```
265+
#[inline]
266+
pub fn demangle(&self) -> ::core::result::Result<String, fmt::Error> {
267+
self.demangle_with_options(&Default::default())
268+
}
269+
270+
/// Demangle the symbol and return it as a String.
259271
///
260272
/// ```
261273
/// use cpp_demangle::{DemangleOptions, Symbol};
262-
/// use std::string::ToString;
263274
///
264275
/// let mangled = b"_ZN5space3fooEibc";
265276
///
266277
/// let sym = Symbol::new(&mangled[..])
267278
/// .expect("Could not parse mangled symbol!");
268279
///
269-
/// let demangled = sym.to_string();
270280
/// let options = DemangleOptions::default();
271-
/// let demangled_again = sym.demangle(&options).unwrap();
272-
/// assert_eq!(demangled_again, demangled);
281+
/// let demangled = sym.demangle_with_options(&options).unwrap();
282+
/// assert_eq!(demangled, "space::foo(int, bool, char)");
273283
/// ```
274284
#[allow(clippy::trivially_copy_pass_by_ref)]
275-
pub fn demangle(
285+
pub fn demangle_with_options(
276286
&self,
277287
options: &DemangleOptions,
278288
) -> ::core::result::Result<String, fmt::Error> {
@@ -361,7 +371,6 @@ where
361371
///
362372
/// ```
363373
/// use cpp_demangle::BorrowedSymbol;
364-
/// use std::string::ToString;
365374
///
366375
/// let mangled = b"_ZN5space3fooEibc and some trailing junk";
367376
///
@@ -370,7 +379,7 @@ where
370379
///
371380
/// assert_eq!(tail, b" and some trailing junk");
372381
///
373-
/// let demangled = sym.to_string();
382+
/// let demangled = sym.demangle().unwrap();
374383
/// assert_eq!(demangled, "space::foo(int, bool, char)");
375384
/// ```
376385
#[inline]
@@ -387,7 +396,6 @@ where
387396
///
388397
/// ```
389398
/// use cpp_demangle::{BorrowedSymbol, ParseOptions};
390-
/// use std::string::ToString;
391399
///
392400
/// let mangled = b"_ZN5space3fooEibc and some trailing junk";
393401
///
@@ -399,7 +407,7 @@ where
399407
///
400408
/// assert_eq!(tail, b" and some trailing junk");
401409
///
402-
/// let demangled = sym.to_string();
410+
/// let demangled = sym.demangle().unwrap();
403411
/// assert_eq!(demangled, "space::foo(int, bool, char)");
404412
/// ```
405413
pub fn with_tail_and_options(
@@ -433,26 +441,3 @@ substitutions = {:#?}",
433441
Ok((symbol, tail.into()))
434442
}
435443
}
436-
437-
impl<T> fmt::Display for Symbol<T>
438-
where
439-
T: AsRef<[u8]>,
440-
{
441-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
442-
let mut out = String::new();
443-
{
444-
let options = DemangleOptions::default();
445-
let mut ctx = ast::DemangleContext::new(
446-
&self.substitutions,
447-
self.raw.as_ref(),
448-
options,
449-
&mut out,
450-
);
451-
self.parsed.demangle(&mut ctx, None).map_err(|err| {
452-
log!("Demangling error: {:#?}", err);
453-
fmt::Error
454-
})?;
455-
}
456-
write!(f, "{}", &out)
457-
}
458-
}

tests/libxul.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ fn libxul_symbols_demangle() {
4545
let mut log_file = BufWriter::new(log_file);
4646

4747
let mut line = Vec::new();
48-
let mut demangled = Vec::new();
4948
let mut libiberty_sym = Vec::new();
5049

5150
let which_cppfilt = get_cppfilt();
@@ -86,8 +85,7 @@ fn libxul_symbols_demangle() {
8685
num_parsed += 1;
8786

8887
// Demangle the symbol.
89-
demangled.clear();
90-
if write!(&mut demangled, "{}", sym).is_ok() {
88+
if let Ok(demangled) = sym.demangle() {
9189
num_demangled += 1;
9290

9391
// Finally, we are going to have `c++filt` demangle the
@@ -107,6 +105,7 @@ fn libxul_symbols_demangle() {
107105
.expect("should read line from c++filt");
108106
// Drop the "\n".
109107
libiberty_sym.pop();
108+
let libiberty_sym = String::from_utf8_lossy(&libiberty_sym);
110109

111110
// Compare our demangling to libiberty's.
112111
if libiberty_sym == demangled {
@@ -121,13 +120,13 @@ fn libxul_symbols_demangle() {
121120
writeln!(
122121
&mut log_file,
123122
" ...we demangled to: {}",
124-
String::from_utf8_lossy(&demangled)
123+
demangled
125124
)
126125
.unwrap();
127126
writeln!(
128127
&mut log_file,
129128
" ...libiberty demangled to: {}",
130-
String::from_utf8_lossy(&libiberty_sym)
129+
libiberty_sym
131130
)
132131
.unwrap();
133132
}

0 commit comments

Comments
 (0)