@@ -46,64 +46,57 @@ pub struct Demangle<'a> {
4646// Note that this demangler isn't quite as fancy as it could be. We have lots
4747// of other information in our symbols like hashes, version, type information,
4848// etc. Additionally, this doesn't handle glue symbols at all.
49- pub fn demangle ( s : & str ) -> Result < Demangle , ( ) > {
49+ pub fn demangle ( s : & str ) -> Result < ( Demangle , & str ) , ( ) > {
5050 // First validate the symbol. If it doesn't look like anything we're
5151 // expecting, we just print it literally. Note that we must handle non-Rust
5252 // symbols because we could have any function in the backtrace.
53- let inner;
54- if s. len ( ) > 4 && s. starts_with ( "_ZN" ) && s. ends_with ( 'E' ) {
55- inner = & s[ 3 ..s. len ( ) - 1 ] ;
56- } else if s. len ( ) > 3 && s. starts_with ( "ZN" ) && s. ends_with ( 'E' ) {
53+ let inner = if s. starts_with ( "_ZN" ) {
54+ & s[ 3 ..]
55+ } else if s. starts_with ( "ZN" ) {
5756 // On Windows, dbghelp strips leading underscores, so we accept "ZN...E"
5857 // form too.
59- inner = & s[ 2 ..s . len ( ) - 1 ] ;
60- } else if s. len ( ) > 5 && s . starts_with ( "__ZN" ) && s . ends_with ( 'E' ) {
58+ & s[ 2 ..]
59+ } else if s. starts_with ( "__ZN" ) {
6160 // On OSX, symbols are prefixed with an extra _
62- inner = & s[ 4 ..s . len ( ) - 1 ] ;
61+ & s[ 4 ..]
6362 } else {
6463 return Err ( ( ) ) ;
65- }
64+ } ;
6665
6766 // only work with ascii text
6867 if inner. bytes ( ) . any ( |c| c & 0x80 != 0 ) {
6968 return Err ( ( ) ) ;
7069 }
7170
7271 let mut elements = 0 ;
73- let mut chars = inner. chars ( ) . peekable ( ) ;
74- loop {
75- let mut i = 0usize ;
76- while let Some ( & c) = chars. peek ( ) {
77- if !c. is_digit ( 10 ) {
78- break
79- }
80- chars. next ( ) ;
81- let next = i. checked_mul ( 10 )
82- . and_then ( |i| i. checked_add ( c as usize - '0' as usize ) ) ;
83- i = match next {
84- Some ( i) => i,
85- None => {
86- return Err ( ( ) ) ;
87- }
88- } ;
72+ let mut chars = inner. chars ( ) ;
73+ let mut c = try!( chars. next ( ) . ok_or ( ( ) ) ) ;
74+ while c != 'E' {
75+ // Decode an identifier element's length.
76+ if !c. is_digit ( 10 ) {
77+ return Err ( ( ) ) ;
78+ }
79+ let mut len = 0usize ;
80+ while let Some ( d) = c. to_digit ( 10 ) {
81+ len = try!( len. checked_mul ( 10 )
82+ . and_then ( |len| len. checked_add ( d as usize ) )
83+ . ok_or ( ( ) ) ) ;
84+ c = try!( chars. next ( ) . ok_or ( ( ) ) ) ;
8985 }
9086
91- if i == 0 {
92- if !chars. next ( ) . is_none ( ) {
93- return Err ( ( ) ) ;
94- }
95- break ;
96- } else if chars. by_ref ( ) . take ( i) . count ( ) != i {
97- return Err ( ( ) ) ;
98- } else {
99- elements += 1 ;
87+ // `c` already contains the first character of this identifier, skip it and
88+ // all the other characters of this identifier, to reach the next element.
89+ for _ in 0 ..len {
90+ c = try!( chars. next ( ) . ok_or ( ( ) ) ) ;
10091 }
92+
93+ elements += 1 ;
10194 }
10295
103- Ok ( Demangle {
96+ Ok ( ( Demangle {
10497 inner : inner,
10598 elements : elements,
106- } )
99+ } , chars . as_str ( ) ) )
107100}
108101
109102// Rust hashes are hex digits with an `h` prepended.
0 commit comments