From b24126aa70788e81898d4ee0146741f11c495544 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 17:01:53 +0300 Subject: [PATCH 01/11] fix lifetimes as requested by rustc build --- src/legacy.rs | 4 ++-- src/lib.rs | 8 ++++---- src/v0.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index d55f3a1..802d14b 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -46,7 +46,7 @@ pub struct Demangle<'a> { // Note that this demangler isn't quite as fancy as it could be. We have lots // of other information in our symbols like hashes, version, type information, // etc. Additionally, this doesn't handle glue symbols at all. -pub fn demangle(s: &str) -> Result<(Demangle, &str), ()> { +pub fn demangle(s: &str) -> Result<(Demangle<'_>, &str), ()> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-Rust // symbols because we could have any function in the backtrace. @@ -103,7 +103,7 @@ fn is_rust_hash(s: &str) -> bool { } impl<'a> fmt::Display for Demangle<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Alright, let's do this. let mut inner = self.inner; for element in 0..self.elements { diff --git a/src/lib.rs b/src/lib.rs index 1ecb13f..049c627 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,7 +88,7 @@ enum DemangleStyle<'a> { /// assert_eq!(demangle("_ZN3foo3barE").to_string(), "foo::bar"); /// assert_eq!(demangle("foo").to_string(), "foo"); /// ``` -pub fn demangle(mut s: &str) -> Demangle { +pub fn demangle(mut s: &str) -> Demangle<'_> { // During ThinLTO LLVM may import and rename internal symbols, so strip out // those endings first as they're one of the last manglings applied to symbol // names. @@ -164,7 +164,7 @@ pub struct TryDemangleError { /// // While `demangle` will just pass the non-symbol through as a no-op. /// assert_eq!(rustc_demangle::demangle(not_a_rust_symbol).as_str(), not_a_rust_symbol); /// ``` -pub fn try_demangle(s: &str) -> Result { +pub fn try_demangle(s: &str) -> Result, TryDemangleError> { let sym = demangle(s); if sym.style.is_some() { Ok(sym) @@ -241,7 +241,7 @@ impl fmt::Write for SizeLimitedFmtAdapter { } impl<'a> fmt::Display for Demangle<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.style { None => f.write_str(self.original)?, Some(ref d) => { @@ -276,7 +276,7 @@ impl<'a> fmt::Display for Demangle<'a> { } impl<'a> fmt::Debug for Demangle<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } diff --git a/src/v0.rs b/src/v0.rs index 3e88fa6..733e1d1 100644 --- a/src/v0.rs +++ b/src/v0.rs @@ -53,8 +53,8 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), ParseError> { } // Paths always start with uppercase characters. - match inner.as_bytes()[0] { - b'A'..=b'Z' => {} + match inner.bytes().next() { + Some(b'A'..=b'Z') => {} _ => return Err(ParseError::Invalid), } From 011d5bbb9c925915145ef828bfdf5f7b8bc95387 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 17:03:28 +0300 Subject: [PATCH 02/11] iterate over bytes, as we expect only portion of ascii range --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 049c627..18b1bec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,8 +95,8 @@ pub fn demangle(mut s: &str) -> Demangle<'_> { let llvm = ".llvm."; if let Some(i) = s.find(llvm) { let candidate = &s[i + llvm.len()..]; - let all_hex = candidate.chars().all(|c| match c { - 'A'..='F' | '0'..='9' | '@' => true, + let all_hex = candidate.bytes().all(|c| match c { + b'A'..=b'F' | b'0'..=b'9' | b'@' => true, _ => false, }); From 20f6396b833a39d4de1aea7aaf1226c6d9835abc Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 19:05:24 +0300 Subject: [PATCH 03/11] legacy: strip prefix via strip_prefix to avoid additional bound check --- src/legacy.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index 802d14b..70fb0f6 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -50,15 +50,15 @@ pub fn demangle(s: &str) -> Result<(Demangle<'_>, &str), ()> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-Rust // symbols because we could have any function in the backtrace. - let inner = if s.starts_with("_ZN") { - &s[3..] - } else if s.starts_with("ZN") { + let inner = if let Some(s) = s.strip_prefix("_ZN") { + s + } else if let Some(s) = s.strip_prefix("ZN") { // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" // form too. - &s[2..] - } else if s.starts_with("__ZN") { + s + } else if let Some(s) = s.strip_prefix("__ZN") { // On OSX, symbols are prefixed with an extra _ - &s[4..] + s } else { return Err(()); }; From 5b648274314df757dc4533b85d8fb912bc9ea315 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 21:09:35 +0300 Subject: [PATCH 04/11] legacy: iterate over bytes, not chars, as mangled string ascii only; fix clippy --- src/legacy.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index 70fb0f6..b9f2c6d 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -99,7 +99,7 @@ pub fn demangle(s: &str) -> Result<(Demangle<'_>, &str), ()> { // Rust hashes are hex digits with an `h` prepended. fn is_rust_hash(s: &str) -> bool { - s.starts_with('h') && s[1..].chars().all(|c| c.is_digit(16)) + s.starts_with('h') && s[1..].bytes().all(|c| (c as char).is_digit(16)) } impl<'a> fmt::Display for Demangle<'a> { @@ -116,7 +116,7 @@ impl<'a> fmt::Display for Demangle<'a> { rest = &rest[..i]; // Skip printing the hash if alternate formatting // was requested. - if f.alternate() && element + 1 == self.elements && is_rust_hash(&rest) { + if f.alternate() && element + 1 == self.elements && is_rust_hash(rest) { break; } if element != 0 { From 61850e0365441008e6df09f46c142d8e81d322e9 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 21:43:07 +0300 Subject: [PATCH 05/11] legacy: iterate over bytes, not chars --- src/legacy.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index b9f2c6d..8e59ed0 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -155,8 +155,8 @@ impl<'a> fmt::Display for Demangle<'a> { _ => { if escape.starts_with('u') { let digits = &escape[1..]; - let all_lower_hex = digits.chars().all(|c| match c { - '0'..='9' | 'a'..='f' => true, + let all_lower_hex = digits.bytes().all(|c| match c { + b'0'..=b'9' | b'a'..=b'f' => true, _ => false, }); let c = u32::from_str_radix(digits, 16) From 3fdbfdd23d313cf8218237bcc141aec9a890cab1 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 22:07:31 +0300 Subject: [PATCH 06/11] legacy::demangle iterate over bytes --- src/legacy.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index 8e59ed0..e346e69 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -69,15 +69,16 @@ pub fn demangle(s: &str) -> Result<(Demangle<'_>, &str), ()> { } let mut elements = 0; - let mut chars = inner.chars(); + // we checked, that string is in ascii range + let mut chars = inner.bytes(); let mut c = chars.next().ok_or(())?; - while c != 'E' { + while c != b'E' { // Decode an identifier element's length. - if !c.is_digit(10) { + if !(c as char).is_digit(10) { return Err(()); } let mut len = 0usize; - while let Some(d) = c.to_digit(10) { + while let Some(d) = (c as char).to_digit(10) { len = len .checked_mul(10) .and_then(|len| len.checked_add(d as usize)) @@ -94,7 +95,11 @@ pub fn demangle(s: &str) -> Result<(Demangle<'_>, &str), ()> { elements += 1; } - Ok((Demangle { inner, elements }, chars.as_str())) + let chars_left = chars.count(); + Ok(( + Demangle { inner, elements }, + &inner[inner.len() - chars_left..], + )) } // Rust hashes are hex digits with an `h` prepended. From cc1023a3b93690338d85f23dfae6fbdf6bcadad0 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 22:51:39 +0300 Subject: [PATCH 07/11] legacy: get switch all chars iterators to bytes --- src/legacy.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index e346e69..7f0c852 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -113,7 +113,12 @@ impl<'a> fmt::Display for Demangle<'a> { let mut inner = self.inner; for element in 0..self.elements { let mut rest = inner; - while rest.chars().next().unwrap().is_digit(10) { + while rest + .bytes() + .next() + .map(|c| (c as char).is_digit(10)) + .unwrap_or(false) + { rest = &rest[1..]; } let i: usize = inner[..(inner.len() - rest.len())].parse().unwrap(); @@ -132,7 +137,7 @@ impl<'a> fmt::Display for Demangle<'a> { } loop { if rest.starts_with('.') { - if let Some('.') = rest[1..].chars().next() { + if let Some(b'.') = rest[1..].bytes().next() { f.write_str("::")?; rest = &rest[2..]; } else { From 44e64baafe8ed2b5235726795e1c22c8c8484312 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 12 Jul 2021 23:08:50 +0300 Subject: [PATCH 08/11] v0: use strip_prefix instead of manual work --- src/v0.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/v0.rs b/src/v0.rs index 733e1d1..526a9ec 100644 --- a/src/v0.rs +++ b/src/v0.rs @@ -38,16 +38,15 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), ParseError> { // First validate the symbol. If it doesn't look like anything we're // expecting, we just print it literally. Note that we must handle non-Rust // symbols because we could have any function in the backtrace. - let inner; - if s.len() > 2 && s.starts_with("_R") { - inner = &s[2..]; - } else if s.len() > 1 && s.starts_with('R') { + let inner = if let Some(s) = s.strip_prefix("_R") { + s + } else if let Some(s) = s.strip_prefix('R') { // On Windows, dbghelp strips leading underscores, so we accept "R..." // form too. - inner = &s[1..]; - } else if s.len() > 3 && s.starts_with("__R") { + s + } else if let Some(s) = s.strip_prefix("__R") { // On OSX, symbols are prefixed with an extra _ - inner = &s[3..]; + s } else { return Err(ParseError::Invalid); } From c9bcb69140f83d70c0846147688a243aa54652fa Mon Sep 17 00:00:00 2001 From: klensy Date: Tue, 13 Jul 2021 01:29:20 +0300 Subject: [PATCH 09/11] v0: one more iterate over bytes, intead of chars --- src/v0.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v0.rs b/src/v0.rs index 526a9ec..64abaeb 100644 --- a/src/v0.rs +++ b/src/v0.rs @@ -160,8 +160,8 @@ impl<'s> Ident<'s> { let mut len = 0; // Populate initial output from ASCII fragment. - for c in self.ascii.chars() { - insert(len, c)?; + for c in self.ascii.bytes() { + insert(len, c as char)?; len += 1; } From bb0cec5b772ec1c5d11f76e814de173d157eacd8 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 3 Sep 2021 19:41:03 +0300 Subject: [PATCH 10/11] fixup rebase --- src/v0.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v0.rs b/src/v0.rs index 64abaeb..b06d49a 100644 --- a/src/v0.rs +++ b/src/v0.rs @@ -49,7 +49,7 @@ pub fn demangle(s: &str) -> Result<(Demangle, &str), ParseError> { s } else { return Err(ParseError::Invalid); - } + }; // Paths always start with uppercase characters. match inner.bytes().next() { From 5ea1cb30d40c2d3f8b8c28a393367fd9fb3c5eb6 Mon Sep 17 00:00:00 2001 From: klensy Date: Fri, 3 Sep 2021 19:46:21 +0300 Subject: [PATCH 11/11] use strip_prefix --- src/legacy.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/legacy.rs b/src/legacy.rs index 7f0c852..3648cee 100644 --- a/src/legacy.rs +++ b/src/legacy.rs @@ -163,8 +163,7 @@ impl<'a> fmt::Display for Demangle<'a> { "C" => ",", _ => { - if escape.starts_with('u') { - let digits = &escape[1..]; + if let Some(digits) = escape.strip_prefix('u') { let all_lower_hex = digits.bytes().all(|c| match c { b'0'..=b'9' | b'a'..=b'f' => true, _ => false,