@@ -46,64 +46,57 @@ pub struct Demangle<'a> {
46
46
// Note that this demangler isn't quite as fancy as it could be. We have lots
47
47
// of other information in our symbols like hashes, version, type information,
48
48
// 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 ) , ( ) > {
50
50
// First validate the symbol. If it doesn't look like anything we're
51
51
// expecting, we just print it literally. Note that we must handle non-Rust
52
52
// 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" ) {
57
56
// On Windows, dbghelp strips leading underscores, so we accept "ZN...E"
58
57
// 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" ) {
61
60
// On OSX, symbols are prefixed with an extra _
62
- inner = & s[ 4 ..s . len ( ) - 1 ] ;
61
+ & s[ 4 ..]
63
62
} else {
64
63
return Err ( ( ) ) ;
65
- }
64
+ } ;
66
65
67
66
// only work with ascii text
68
67
if inner. bytes ( ) . any ( |c| c & 0x80 != 0 ) {
69
68
return Err ( ( ) ) ;
70
69
}
71
70
72
71
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 ( ( ) ) ) ;
89
85
}
90
86
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 ( ( ) ) ) ;
100
91
}
92
+
93
+ elements += 1 ;
101
94
}
102
95
103
- Ok ( Demangle {
96
+ Ok ( ( Demangle {
104
97
inner : inner,
105
98
elements : elements,
106
- } )
99
+ } , chars . as_str ( ) ) )
107
100
}
108
101
109
102
// Rust hashes are hex digits with an `h` prepended.
0 commit comments