diff options
author | Matthew Maurer <mmaurer@google.com> | 2021-08-23 20:01:13 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-08-23 20:01:13 +0000 |
commit | f1ccdfa2299300e0681651e4bc6512f3b003ff90 (patch) | |
tree | faa186535256536e9e910d1f323454bd411f0af3 | |
parent | 94cb65ac6e8714d75d61e5c14382ff85004fd93f (diff) | |
parent | 26b49c2fc94bc32b919b01a65834d4c58a0d2d5d (diff) | |
download | rustc-demangle-f1ccdfa2299300e0681651e4bc6512f3b003ff90.tar.gz |
Initial Import: rustc-demangle-0.1.20 am: 813ee2753a am: 26b49c2fc9
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/rustc-demangle/+/1798349
Change-Id: I7b164bdbfab928d9e8bb24cb45e40766387e45bf
-rw-r--r-- | .cargo_vcs_info.json | 5 | ||||
-rw-r--r-- | .github/dependabot.yml | 8 | ||||
-rw-r--r-- | .github/workflows/main.yml | 54 | ||||
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Cargo.toml | 35 | ||||
-rw-r--r-- | Cargo.toml.orig | 25 | ||||
l--------- | LICENSE | 1 | ||||
-rw-r--r-- | LICENSE-APACHE | 201 | ||||
-rw-r--r-- | LICENSE-MIT | 25 | ||||
-rw-r--r-- | METADATA | 20 | ||||
-rw-r--r-- | MODULE_LICENSE_APACHE2 | 0 | ||||
-rw-r--r-- | OWNERS | 1 | ||||
-rw-r--r-- | README.md | 48 | ||||
-rw-r--r-- | src/legacy.rs | 392 | ||||
-rw-r--r-- | src/lib.rs | 398 | ||||
-rw-r--r-- | src/v0.rs | 1811 |
16 files changed, 3026 insertions, 0 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json new file mode 100644 index 0000000..ceed88a --- /dev/null +++ b/.cargo_vcs_info.json @@ -0,0 +1,5 @@ +{ + "git": { + "sha1": "b1bbc0d5c180da20c633e7939bccf673daa736d9" + } +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..7377d37 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: cargo + directory: "/" + schedule: + interval: daily + time: "08:00" + open-pull-requests-limit: 10 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..6ae8d0c --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,54 @@ +name: CI +on: [push, pull_request] + +jobs: + test: + name: Test + runs-on: ubuntu-latest + strategy: + matrix: + rust: [stable, beta, nightly] + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} + - run: cargo build --all + - run: cargo test --all + + fuzz_targets: + name: Fuzz Targets + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # Note that building with fuzzers requires nightly since it uses unstable + # flags to rustc. + - run: rustup update nightly && rustup default nightly + - run: cargo install cargo-fuzz --vers "^0.10" + - run: cargo fuzz build --dev + + rustfmt: + name: Rustfmt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update stable && rustup default stable && rustup component add rustfmt + - run: cargo fmt -- --check + + publish_docs: + name: Publish Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Install Rust + run: rustup update stable && rustup default stable + - name: Build documentation + run: cargo doc --no-deps + - name: Publish documentation + run: | + cd target/doc + git init + git add . + git -c user.name='ci' -c user.email='ci' commit -m init + git push -f -q https://git:${{ secrets.github_token }}@github.com/${{ github.repository }} HEAD:gh-pages + if: github.event_name == 'push' && github.event.ref == 'refs/heads/main' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9d37c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c813375 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,35 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "rustc-demangle" +version = "0.1.20" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +description = "Rust compiler symbol demangling.\n" +homepage = "https://github.com/alexcrichton/rustc-demangle" +documentation = "https://docs.rs/rustc-demangle" +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/alexcrichton/rustc-demangle" +[profile.release] +lto = true +[dependencies.compiler_builtins] +version = "0.1.2" +optional = true + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" + +[features] +rustc-dep-of-std = ["core", "compiler_builtins"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig new file mode 100644 index 0000000..6c244a4 --- /dev/null +++ b/Cargo.toml.orig @@ -0,0 +1,25 @@ +[package] +name = "rustc-demangle" +version = "0.1.20" +authors = ["Alex Crichton <alex@alexcrichton.com>"] +license = "MIT/Apache-2.0" +readme = "README.md" +repository = "https://github.com/alexcrichton/rustc-demangle" +homepage = "https://github.com/alexcrichton/rustc-demangle" +documentation = "https://docs.rs/rustc-demangle" +description = """ +Rust compiler symbol demangling. +""" + +[workspace] +members = ["crates/capi", "fuzz"] + +[dependencies] +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +compiler_builtins = { version = '0.1.2', optional = true } + +[features] +rustc-dep-of-std = ['core', 'compiler_builtins'] + +[profile.release] +lto = true @@ -0,0 +1 @@ +LICENSE-APACHE
\ No newline at end of file diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..39e0ed6 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 Alex Crichton + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..f99d6ac --- /dev/null +++ b/METADATA @@ -0,0 +1,20 @@ +name: "rustc-demangle" +description: "Rust compiler symbol demangling." +third_party { + url { + type: HOMEPAGE + value: "https://crates.io/crates/rustc-demangle" + } + url { + type: ARCHIVE + value: "https://static.crates.io/crates/rustc-demangle/rustc-demangle-0.1.20.crate" + } + version: "0.1.20" + # Dual-licensed, using the least restrictive per go/thirdpartylicenses#same. + license_type: NOTICE + last_upgrade_date { + year: 2021 + month: 8 + day: 17 + } +} diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/MODULE_LICENSE_APACHE2 @@ -0,0 +1 @@ +include platform/prebuilts/rust:master:/OWNERS diff --git a/README.md b/README.md new file mode 100644 index 0000000..0833e1e --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# rustc-demangle + +Demangling for Rust symbols, written in Rust. + +[Documentation](https://docs.rs/rustc-demangle) + +## Usage + +You can add this as a dependency via your `Cargo.toml` + +```toml +[dependencies] +rustc-demangle = "0.1" +``` + +and then be sure to check out the [crate +documentation](https://docs.rs/rustc-demangle) for usage. + +## Usage from non-Rust languages + +You can also use this crate from other languages via the C API wrapper in the +`crates/capi` directory. This can be build with: + +```sh +$ cargo build -p rustc-demangle-capi --release +``` + +You'll then find `target/release/librustc_demangle.a` and +`target/release/librustc_demangle.so` (or a different name depending on your +platform). These objects implement the interface specified in +`crates/capi/include/rustc_demangle.h`. + +# License + +This project is licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in rustc-demangle you, as defined in the Apache-2.0 license, shall +be dual licensed as above, without any additional terms or conditions. diff --git a/src/legacy.rs b/src/legacy.rs new file mode 100644 index 0000000..d55f3a1 --- /dev/null +++ b/src/legacy.rs @@ -0,0 +1,392 @@ +use core::char; +use core::fmt; + +/// Representation of a demangled symbol name. +pub struct Demangle<'a> { + inner: &'a str, + /// The number of ::-separated elements in the original name. + elements: usize, +} + +/// De-mangles a Rust symbol into a more readable version +/// +/// All Rust symbols by default are mangled as they contain characters that +/// cannot be represented in all object files. The mangling mechanism is similar +/// to C++'s, but Rust has a few specifics to handle items like lifetimes in +/// symbols. +/// +/// This function will take a **mangled** symbol and return a value. When printed, +/// the de-mangled version will be written. If the symbol does not look like +/// a mangled symbol, the original value will be written instead. +/// +/// # Examples +/// +/// ``` +/// use rustc_demangle::demangle; +/// +/// assert_eq!(demangle("_ZN4testE").to_string(), "test"); +/// assert_eq!(demangle("_ZN3foo3barE").to_string(), "foo::bar"); +/// assert_eq!(demangle("foo").to_string(), "foo"); +/// ``` + +// All Rust symbols are in theory lists of "::"-separated identifiers. Some +// assemblers, however, can't handle these characters in symbol names. To get +// around this, we use C++-style mangling. The mangling method is: +// +// 1. Prefix the symbol with "_ZN" +// 2. For each element of the path, emit the length plus the element +// 3. End the path with "E" +// +// For example, "_ZN4testE" => "test" and "_ZN3foo3barE" => "foo::bar". +// +// We're the ones printing our backtraces, so we can't rely on anything else to +// demangle our symbols. It's *much* nicer to look at demangled symbols, so +// this function is implemented to give us nice pretty output. +// +// 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), ()> { + // 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") { + // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" + // form too. + &s[2..] + } else if s.starts_with("__ZN") { + // On OSX, symbols are prefixed with an extra _ + &s[4..] + } else { + return Err(()); + }; + + // only work with ascii text + if inner.bytes().any(|c| c & 0x80 != 0) { + return Err(()); + } + + let mut elements = 0; + let mut chars = inner.chars(); + let mut c = chars.next().ok_or(())?; + while c != 'E' { + // Decode an identifier element's length. + if !c.is_digit(10) { + return Err(()); + } + let mut len = 0usize; + while let Some(d) = c.to_digit(10) { + len = len + .checked_mul(10) + .and_then(|len| len.checked_add(d as usize)) + .ok_or(())?; + c = chars.next().ok_or(())?; + } + + // `c` already contains the first character of this identifier, skip it and + // all the other characters of this identifier, to reach the next element. + for _ in 0..len { + c = chars.next().ok_or(())?; + } + + elements += 1; + } + + Ok((Demangle { inner, elements }, chars.as_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)) +} + +impl<'a> fmt::Display for Demangle<'a> { + 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 { + let mut rest = inner; + while rest.chars().next().unwrap().is_digit(10) { + rest = &rest[1..]; + } + let i: usize = inner[..(inner.len() - rest.len())].parse().unwrap(); + inner = &rest[i..]; + rest = &rest[..i]; + // Skip printing the hash if alternate formatting + // was requested. + if f.alternate() && element + 1 == self.elements && is_rust_hash(&rest) { + break; + } + if element != 0 { + f.write_str("::")?; + } + if rest.starts_with("_$") { + rest = &rest[1..]; + } + loop { + if rest.starts_with('.') { + if let Some('.') = rest[1..].chars().next() { + f.write_str("::")?; + rest = &rest[2..]; + } else { + f.write_str(".")?; + rest = &rest[1..]; + } + } else if rest.starts_with('$') { + let (escape, after_escape) = if let Some(end) = rest[1..].find('$') { + (&rest[1..=end], &rest[end + 2..]) + } else { + break; + }; + + // see src/librustc_codegen_utils/symbol_names/legacy.rs for these mappings + let unescaped = match escape { + "SP" => "@", + "BP" => "*", + "RF" => "&", + "LT" => "<", + "GT" => ">", + "LP" => "(", + "RP" => ")", + "C" => ",", + + _ => { + if escape.starts_with('u') { + let digits = &escape[1..]; + let all_lower_hex = digits.chars().all(|c| match c { + '0'..='9' | 'a'..='f' => true, + _ => false, + }); + let c = u32::from_str_radix(digits, 16) + .ok() + .and_then(char::from_u32); + if let (true, Some(c)) = (all_lower_hex, c) { + // FIXME(eddyb) do we need to filter out control codepoints? + if !c.is_control() { + c.fmt(f)?; + rest = after_escape; + continue; + } + } + } + break; + } + }; + f.write_str(unescaped)?; + rest = after_escape; + } else if let Some(i) = rest.find(|c| c == '$' || c == '.') { + f.write_str(&rest[..i])?; + rest = &rest[i..]; + } else { + break; + } + } + f.write_str(rest)?; + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use std::prelude::v1::*; + + macro_rules! t { + ($a:expr, $b:expr) => { + assert!(ok($a, $b)) + }; + } + + macro_rules! t_err { + ($a:expr) => { + assert!(ok_err($a)) + }; + } + + macro_rules! t_nohash { + ($a:expr, $b:expr) => {{ + assert_eq!(format!("{:#}", ::demangle($a)), $b); + }}; + } + + fn ok(sym: &str, expected: &str) -> bool { + match ::try_demangle(sym) { + Ok(s) => { + if s.to_string() == expected { + true + } else { + println!("\n{}\n!=\n{}\n", s, expected); + false + } + } + Err(_) => { + println!("error demangling"); + false + } + } + } + + fn ok_err(sym: &str) -> bool { + match ::try_demangle(sym) { + Ok(_) => { + println!("succeeded in demangling"); + false + } + Err(_) => ::demangle(sym).to_string() == sym, + } + } + + #[test] + fn demangle() { + t_err!("test"); + t!("_ZN4testE", "test"); + t_err!("_ZN4test"); + t!("_ZN4test1a2bcE", "test::a::bc"); + } + + #[test] + fn demangle_dollars() { + t!("_ZN4$RP$E", ")"); + t!("_ZN8$RF$testE", "&test"); + t!("_ZN8$BP$test4foobE", "*test::foob"); + t!("_ZN9$u20$test4foobE", " test::foob"); + t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>"); + } + + #[test] + fn demangle_many_dollars() { + t!("_ZN13test$u20$test4foobE", "test test::foob"); + t!("_ZN12test$BP$test4foobE", "test*test::foob"); + } + + #[test] + fn demangle_osx() { + t!( + "__ZN5alloc9allocator6Layout9for_value17h02a996811f781011E", + "alloc::allocator::Layout::for_value::h02a996811f781011" + ); + t!("__ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap18_MSG_FILE_LINE_COL17haf7cb8d5824ee659E", "<core::option::Option<T>>::unwrap::_MSG_FILE_LINE_COL::haf7cb8d5824ee659"); + t!("__ZN4core5slice89_$LT$impl$u20$core..iter..traits..IntoIterator$u20$for$u20$$RF$$u27$a$u20$$u5b$T$u5d$$GT$9into_iter17h450e234d27262170E", "core::slice::<impl core::iter::traits::IntoIterator for &'a [T]>::into_iter::h450e234d27262170"); + } + + #[test] + fn demangle_windows() { + t!("ZN4testE", "test"); + t!("ZN13test$u20$test4foobE", "test test::foob"); + t!("ZN12test$RF$test4foobE", "test&test::foob"); + } + + #[test] + fn demangle_elements_beginning_with_underscore() { + t!("_ZN13_$LT$test$GT$E", "<test>"); + t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"); + t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR"); + } + + #[test] + fn demangle_trait_impls() { + t!( + "_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE", + "<Test + 'static as foo::Bar<Test>>::bar" + ); + } + + #[test] + fn demangle_without_hash() { + let s = "_ZN3foo17h05af221e174051e9E"; + t!(s, "foo::h05af221e174051e9"); + t_nohash!(s, "foo"); + } + + #[test] + fn demangle_without_hash_edgecases() { + // One element, no hash. + t_nohash!("_ZN3fooE", "foo"); + // Two elements, no hash. + t_nohash!("_ZN3foo3barE", "foo::bar"); + // Longer-than-normal hash. + t_nohash!("_ZN3foo20h05af221e174051e9abcE", "foo"); + // Shorter-than-normal hash. + t_nohash!("_ZN3foo5h05afE", "foo"); + // Valid hash, but not at the end. + t_nohash!("_ZN17h05af221e174051e93fooE", "h05af221e174051e9::foo"); + // Not a valid hash, missing the 'h'. + t_nohash!("_ZN3foo16ffaf221e174051e9E", "foo::ffaf221e174051e9"); + // Not a valid hash, has a non-hex-digit. + t_nohash!("_ZN3foo17hg5af221e174051e9E", "foo::hg5af221e174051e9"); + } + + #[test] + fn demangle_thinlto() { + // One element, no hash. + t!("_ZN3fooE.llvm.9D1C9369", "foo"); + t!("_ZN3fooE.llvm.9D1C9369@@16", "foo"); + t_nohash!( + "_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9", + "backtrace::foo" + ); + } + + #[test] + fn demangle_llvm_ir_branch_labels() { + t!("_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i", "core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut::haf9727c2edfbc47b.exit.i.i"); + t_nohash!("_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i", "core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i"); + } + + #[test] + fn demangle_ignores_suffix_that_doesnt_look_like_a_symbol() { + t_err!("_ZN3fooE.llvm moocow"); + } + + #[test] + fn dont_panic() { + ::demangle("_ZN2222222222222222222222EE").to_string(); + ::demangle("_ZN5*70527e27.ll34csaғE").to_string(); + ::demangle("_ZN5*70527a54.ll34_$b.1E").to_string(); + ::demangle( + "\ + _ZN5~saäb4e\n\ + 2734cOsbE\n\ + 5usage20h)3\0\0\0\0\0\0\07e2734cOsbE\ + ", + ) + .to_string(); + } + + #[test] + fn invalid_no_chop() { + t_err!("_ZNfooE"); + } + + #[test] + fn handle_assoc_types() { + t!("_ZN151_$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$9call_once17h69e8f44b3723e1caE", "<alloc::boxed::Box<alloc::boxed::FnBox<A, Output=R> + 'a> as core::ops::function::FnOnce<A>>::call_once::h69e8f44b3723e1ca"); + } + + #[test] + fn handle_bang() { + t!( + "_ZN88_$LT$core..result..Result$LT$$u21$$C$$u20$E$GT$$u20$as$u20$std..process..Termination$GT$6report17hfc41d0da4a40b3e8E", + "<core::result::Result<!, E> as std::process::Termination>::report::hfc41d0da4a40b3e8" + ); + } + + #[test] + fn demangle_utf8_idents() { + t_nohash!( + "_ZN11utf8_idents157_$u10e1$$u10d0$$u10ed$$u10db$$u10d4$$u10da$$u10d0$$u10d3$_$u10d2$$u10d4$$u10db$$u10e0$$u10d8$$u10d4$$u10da$$u10d8$_$u10e1$$u10d0$$u10d3$$u10d8$$u10da$$u10d8$17h21634fd5714000aaE", + "utf8_idents::საჭმელად_გემრიელი_სადილი" + ); + } + + #[test] + fn demangle_issue_60925() { + t_nohash!( + "_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h059a991a004536adE", + "issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo" + ); + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..7adc0c7 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,398 @@ +//! Demangle Rust compiler symbol names. +//! +//! This crate provides a `demangle` function which will return a `Demangle` +//! sentinel value that can be used to learn about the demangled version of a +//! symbol name. The demangled representation will be the same as the original +//! if it doesn't look like a mangled symbol name. +//! +//! `Demangle` can be formatted with the `Display` trait. The alternate +//! modifier (`#`) can be used to format the symbol name without the +//! trailing hash value. +//! +//! # Examples +//! +//! ``` +//! use rustc_demangle::demangle; +//! +//! assert_eq!(demangle("_ZN4testE").to_string(), "test"); +//! assert_eq!(demangle("_ZN3foo3barE").to_string(), "foo::bar"); +//! assert_eq!(demangle("foo").to_string(), "foo"); +//! // With hash +//! assert_eq!(format!("{}", demangle("_ZN3foo17h05af221e174051e9E")), "foo::h05af221e174051e9"); +//! // Without hash +//! assert_eq!(format!("{:#}", demangle("_ZN3foo17h05af221e174051e9E")), "foo"); +//! ``` + +#![no_std] +#![deny(missing_docs)] + +#[cfg(test)] +#[macro_use] +extern crate std; + +mod legacy; +mod v0; + +use core::fmt; + +/// Representation of a demangled symbol name. +pub struct Demangle<'a> { + style: Option<DemangleStyle<'a>>, + original: &'a str, + suffix: &'a str, +} + +enum DemangleStyle<'a> { + Legacy(legacy::Demangle<'a>), + V0(v0::Demangle<'a>), +} + +/// De-mangles a Rust symbol into a more readable version +/// +/// This function will take a **mangled** symbol and return a value. When printed, +/// the de-mangled version will be written. If the symbol does not look like +/// a mangled symbol, the original value will be written instead. +/// +/// # Examples +/// +/// ``` +/// use rustc_demangle::demangle; +/// +/// assert_eq!(demangle("_ZN4testE").to_string(), "test"); +/// assert_eq!(demangle("_ZN3foo3barE").to_string(), "foo::bar"); +/// assert_eq!(demangle("foo").to_string(), "foo"); +/// ``` +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. + 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, + _ => false, + }); + + if all_hex { + s = &s[..i]; + } + } + + let mut suffix = ""; + let mut style = match legacy::demangle(s) { + Ok((d, s)) => { + suffix = s; + Some(DemangleStyle::Legacy(d)) + } + Err(()) => match v0::demangle(s) { + Ok((d, s)) => { + suffix = s; + Some(DemangleStyle::V0(d)) + } + Err(v0::Invalid) => None, + }, + }; + + // Output like LLVM IR adds extra period-delimited words. See if + // we are in that case and save the trailing words if so. + if !suffix.is_empty() { + if suffix.starts_with('.') && is_symbol_like(suffix) { + // Keep the suffix. + } else { + // Reset the suffix and invalidate the demangling. + suffix = ""; + style = None; + } + } + + Demangle { + style, + original: s, + suffix, + } +} + +/// Error returned from the `try_demangle` function below when demangling fails. +#[derive(Debug, Clone)] +pub struct TryDemangleError { + _priv: (), +} + +/// The same as `demangle`, except return an `Err` if the string does not appear +/// to be a Rust symbol, rather than "demangling" the given string as a no-op. +/// +/// ``` +/// extern crate rustc_demangle; +/// +/// let not_a_rust_symbol = "la la la"; +/// +/// // The `try_demangle` function will reject strings which are not Rust symbols. +/// assert!(rustc_demangle::try_demangle(not_a_rust_symbol).is_err()); +/// +/// // 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<Demangle, TryDemangleError> { + let sym = demangle(s); + if sym.style.is_some() { + Ok(sym) + } else { + Err(TryDemangleError { _priv: () }) + } +} + +impl<'a> Demangle<'a> { + /// Returns the underlying string that's being demangled. + pub fn as_str(&self) -> &'a str { + self.original + } +} + +fn is_symbol_like(s: &str) -> bool { + s.chars().all(|c| { + // Once `char::is_ascii_punctuation` and `char::is_ascii_alphanumeric` + // have been stable for long enough, use those instead for clarity + is_ascii_alphanumeric(c) || is_ascii_punctuation(c) + }) +} + +// Copied from the documentation of `char::is_ascii_alphanumeric` +fn is_ascii_alphanumeric(c: char) -> bool { + match c { + '\u{0041}'..='\u{005A}' | '\u{0061}'..='\u{007A}' | '\u{0030}'..='\u{0039}' => true, + _ => false, + } +} + +// Copied from the documentation of `char::is_ascii_punctuation` +fn is_ascii_punctuation(c: char) -> bool { + match c { + '\u{0021}'..='\u{002F}' + | '\u{003A}'..='\u{0040}' + | '\u{005B}'..='\u{0060}' + | '\u{007B}'..='\u{007E}' => true, + _ => false, + } +} + +impl<'a> fmt::Display for Demangle<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.style { + None => f.write_str(self.original)?, + Some(DemangleStyle::Legacy(ref d)) => fmt::Display::fmt(d, f)?, + Some(DemangleStyle::V0(ref d)) => fmt::Display::fmt(d, f)?, + } + f.write_str(self.suffix) + } +} + +impl<'a> fmt::Debug for Demangle<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +#[cfg(test)] +mod tests { + use std::prelude::v1::*; + + macro_rules! t { + ($a:expr, $b:expr) => { + assert!(ok($a, $b)) + }; + } + + macro_rules! t_err { + ($a:expr) => { + assert!(ok_err($a)) + }; + } + + macro_rules! t_nohash { + ($a:expr, $b:expr) => {{ + assert_eq!(format!("{:#}", super::demangle($a)), $b); + }}; + } + + fn ok(sym: &str, expected: &str) -> bool { + match super::try_demangle(sym) { + Ok(s) => { + if s.to_string() == expected { + true + } else { + println!("\n{}\n!=\n{}\n", s, expected); + false + } + } + Err(_) => { + println!("error demangling"); + false + } + } + } + + fn ok_err(sym: &str) -> bool { + match super::try_demangle(sym) { + Ok(_) => { + println!("succeeded in demangling"); + false + } + Err(_) => super::demangle(sym).to_string() == sym, + } + } + + #[test] + fn demangle() { + t_err!("test"); + t!("_ZN4testE", "test"); + t_err!("_ZN4test"); + t!("_ZN4test1a2bcE", "test::a::bc"); + } + + #[test] + fn demangle_dollars() { + t!("_ZN4$RP$E", ")"); + t!("_ZN8$RF$testE", "&test"); + t!("_ZN8$BP$test4foobE", "*test::foob"); + t!("_ZN9$u20$test4foobE", " test::foob"); + t!("_ZN35Bar$LT$$u5b$u32$u3b$$u20$4$u5d$$GT$E", "Bar<[u32; 4]>"); + } + + #[test] + fn demangle_many_dollars() { + t!("_ZN13test$u20$test4foobE", "test test::foob"); + t!("_ZN12test$BP$test4foobE", "test*test::foob"); + } + + #[test] + fn demangle_osx() { + t!( + "__ZN5alloc9allocator6Layout9for_value17h02a996811f781011E", + "alloc::allocator::Layout::for_value::h02a996811f781011" + ); + t!("__ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap18_MSG_FILE_LINE_COL17haf7cb8d5824ee659E", "<core::option::Option<T>>::unwrap::_MSG_FILE_LINE_COL::haf7cb8d5824ee659"); + t!("__ZN4core5slice89_$LT$impl$u20$core..iter..traits..IntoIterator$u20$for$u20$$RF$$u27$a$u20$$u5b$T$u5d$$GT$9into_iter17h450e234d27262170E", "core::slice::<impl core::iter::traits::IntoIterator for &'a [T]>::into_iter::h450e234d27262170"); + } + + #[test] + fn demangle_windows() { + t!("ZN4testE", "test"); + t!("ZN13test$u20$test4foobE", "test test::foob"); + t!("ZN12test$RF$test4foobE", "test&test::foob"); + } + + #[test] + fn demangle_elements_beginning_with_underscore() { + t!("_ZN13_$LT$test$GT$E", "<test>"); + t!("_ZN28_$u7b$$u7b$closure$u7d$$u7d$E", "{{closure}}"); + t!("_ZN15__STATIC_FMTSTRE", "__STATIC_FMTSTR"); + } + + #[test] + fn demangle_trait_impls() { + t!( + "_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3barE", + "<Test + 'static as foo::Bar<Test>>::bar" + ); + } + + #[test] + fn demangle_without_hash() { + let s = "_ZN3foo17h05af221e174051e9E"; + t!(s, "foo::h05af221e174051e9"); + t_nohash!(s, "foo"); + } + + #[test] + fn demangle_without_hash_edgecases() { + // One element, no hash. + t_nohash!("_ZN3fooE", "foo"); + // Two elements, no hash. + t_nohash!("_ZN3foo3barE", "foo::bar"); + // Longer-than-normal hash. + t_nohash!("_ZN3foo20h05af221e174051e9abcE", "foo"); + // Shorter-than-normal hash. + t_nohash!("_ZN3foo5h05afE", "foo"); + // Valid hash, but not at the end. + t_nohash!("_ZN17h05af221e174051e93fooE", "h05af221e174051e9::foo"); + // Not a valid hash, missing the 'h'. + t_nohash!("_ZN3foo16ffaf221e174051e9E", "foo::ffaf221e174051e9"); + // Not a valid hash, has a non-hex-digit. + t_nohash!("_ZN3foo17hg5af221e174051e9E", "foo::hg5af221e174051e9"); + } + + #[test] + fn demangle_thinlto() { + // One element, no hash. + t!("_ZN3fooE.llvm.9D1C9369", "foo"); + t!("_ZN3fooE.llvm.9D1C9369@@16", "foo"); + t_nohash!( + "_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9", + "backtrace::foo" + ); + } + + #[test] + fn demangle_llvm_ir_branch_labels() { + t!("_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i", "core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut::haf9727c2edfbc47b.exit.i.i"); + t_nohash!("_ZN4core5slice77_$LT$impl$u20$core..ops..index..IndexMut$LT$I$GT$$u20$for$u20$$u5b$T$u5d$$GT$9index_mut17haf9727c2edfbc47bE.exit.i.i", "core::slice::<impl core::ops::index::IndexMut<I> for [T]>::index_mut.exit.i.i"); + } + + #[test] + fn demangle_ignores_suffix_that_doesnt_look_like_a_symbol() { + t_err!("_ZN3fooE.llvm moocow"); + } + + #[test] + fn dont_panic() { + super::demangle("_ZN2222222222222222222222EE").to_string(); + super::demangle("_ZN5*70527e27.ll34csaғE").to_string(); + super::demangle("_ZN5*70527a54.ll34_$b.1E").to_string(); + super::demangle( + "\ + _ZN5~saäb4e\n\ + 2734cOsbE\n\ + 5usage20h)3\0\0\0\0\0\0\07e2734cOsbE\ + ", + ) + .to_string(); + } + + #[test] + fn invalid_no_chop() { + t_err!("_ZNfooE"); + } + + #[test] + fn handle_assoc_types() { + t!("_ZN151_$LT$alloc..boxed..Box$LT$alloc..boxed..FnBox$LT$A$C$$u20$Output$u3d$R$GT$$u20$$u2b$$u20$$u27$a$GT$$u20$as$u20$core..ops..function..FnOnce$LT$A$GT$$GT$9call_once17h69e8f44b3723e1caE", "<alloc::boxed::Box<alloc::boxed::FnBox<A, Output=R> + 'a> as core::ops::function::FnOnce<A>>::call_once::h69e8f44b3723e1ca"); + } + + #[test] + fn handle_bang() { + t!( + "_ZN88_$LT$core..result..Result$LT$$u21$$C$$u20$E$GT$$u20$as$u20$std..process..Termination$GT$6report17hfc41d0da4a40b3e8E", + "<core::result::Result<!, E> as std::process::Termination>::report::hfc41d0da4a40b3e8" + ); + } + + #[test] + fn limit_recursion() { + use std::fmt::Write; + let mut s = String::new(); + assert!(write!(s, "{}", super::demangle("_RNvB_1a")).is_err()); + } + + #[test] + fn limit_output() { + use std::fmt::Write; + let mut s = String::new(); + assert!(write!( + s, + "{}", + super::demangle("RYFG_FGyyEvRYFF_EvRYFFEvERLB_B_B_ERLRjB_B_B_") + ) + .is_err()); + } +} diff --git a/src/v0.rs b/src/v0.rs new file mode 100644 index 0000000..163686b --- /dev/null +++ b/src/v0.rs @@ -0,0 +1,1811 @@ +use core::char; +use core::fmt; +use core::fmt::{Display, Write}; + +// Maximum recursion depth when parsing symbols before we just bail out saying +// "this symbol is invalid" +const MAX_DEPTH: u32 = 500; + +// Approximately the maximum size of the symbol that we'll print. This is +// approximate because it only limits calls writing to `LimitedFormatter`, but +// not all writes exclusively go through `LimitedFormatter`. Some writes go +// directly to the underlying formatter, but when that happens we always write +// at least a little to the `LimitedFormatter`. +const MAX_APPROX_SIZE: usize = 1_000_000; + +/// Representation of a demangled symbol name. +pub struct Demangle<'a> { + inner: &'a str, +} + +/// De-mangles a Rust symbol into a more readable version +/// +/// This function will take a **mangled** symbol and return a value. When printed, +/// the de-mangled version will be written. If the symbol does not look like +/// a mangled symbol, the original value will be written instead. +pub fn demangle(s: &str) -> Result<(Demangle, &str), Invalid> { + // 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') { + // On Windows, dbghelp strips leading underscores, so we accept "R..." + // form too. + inner = &s[1..]; + } else if s.len() > 3 && s.starts_with("__R") { + // On OSX, symbols are prefixed with an extra _ + inner = &s[3..]; + } else { + return Err(Invalid); + } + + // Paths always start with uppercase characters. + match inner.as_bytes()[0] { + b'A'..=b'Z' => {} + _ => return Err(Invalid), + } + + // only work with ascii text + if inner.bytes().any(|c| c & 0x80 != 0) { + return Err(Invalid); + } + + // Verify that the symbol is indeed a valid path. + let mut parser = Parser { + sym: inner, + next: 0, + depth: 0, + }; + parser.skip_path()?; + + // Instantiating crate (paths always start with uppercase characters). + if let Some(&(b'A'..=b'Z')) = parser.sym.as_bytes().get(parser.next) { + parser.skip_path()?; + } + + Ok((Demangle { inner }, &parser.sym[parser.next..])) +} + +impl<'s> Display for Demangle<'s> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut remaining = MAX_APPROX_SIZE; + let mut printer = Printer { + parser: Ok(Parser { + sym: self.inner, + next: 0, + depth: 0, + }), + out: LimitedFormatter { + remaining: &mut remaining, + inner: f, + }, + bound_lifetime_depth: 0, + }; + printer.print_path(true) + } +} + +#[derive(PartialEq, Eq)] +pub struct Invalid; + +struct Ident<'s> { + /// ASCII part of the identifier. + ascii: &'s str, + /// Punycode insertion codes for Unicode codepoints, if any. + punycode: &'s str, +} + +const SMALL_PUNYCODE_LEN: usize = 128; + +impl<'s> Ident<'s> { + /// Attempt to decode punycode on the stack (allocation-free), + /// and pass the char slice to the closure, if successful. + /// This supports up to `SMALL_PUNYCODE_LEN` characters. + fn try_small_punycode_decode<F: FnOnce(&[char]) -> R, R>(&self, f: F) -> Option<R> { + let mut out = ['\0'; SMALL_PUNYCODE_LEN]; + let mut out_len = 0; + let r = self.punycode_decode(|i, c| { + // Check there's space left for another character. + out.get(out_len).ok_or(())?; + + // Move the characters after the insert position. + let mut j = out_len; + out_len += 1; + + while j > i { + out[j] = out[j - 1]; + j -= 1; + } + + // Insert the new character. + out[i] = c; + + Ok(()) + }); + if r.is_ok() { + Some(f(&out[..out_len])) + } else { + None + } + } + + /// Decode punycode as insertion positions and characters + /// and pass them to the closure, which can return `Err(())` + /// to stop the decoding process. + fn punycode_decode<F: FnMut(usize, char) -> Result<(), ()>>( + &self, + mut insert: F, + ) -> Result<(), ()> { + let mut punycode_bytes = self.punycode.bytes().peekable(); + if punycode_bytes.peek().is_none() { + return Err(()); + } + + let mut len = 0; + + // Populate initial output from ASCII fragment. + for c in self.ascii.chars() { + insert(len, c)?; + len += 1; + } + + // Punycode parameters and initial state. + let base = 36; + let t_min = 1; + let t_max = 26; + let skew = 38; + let mut damp = 700; + let mut bias = 72; + let mut i: usize = 0; + let mut n: usize = 0x80; + + loop { + // Read one delta value. + let mut delta: usize = 0; + let mut w = 1; + let mut k: usize = 0; + loop { + use core::cmp::{max, min}; + + k += base; + let t = min(max(k.saturating_sub(bias), t_min), t_max); + + let d = match punycode_bytes.next() { + Some(d @ b'a'..=b'z') => d - b'a', + Some(d @ b'0'..=b'9') => 26 + (d - b'0'), + _ => return Err(()), + }; + let d = d as usize; + delta = delta.checked_add(d.checked_mul(w).ok_or(())?).ok_or(())?; + if d < t { + break; + } + w = w.checked_mul(base - t).ok_or(())?; + } + + // Compute the new insert position and character. + len += 1; + i = i.checked_add(delta).ok_or(())?; + n = n.checked_add(i / len).ok_or(())?; + i %= len; + + let n_u32 = n as u32; + let c = if n_u32 as usize == n { + char::from_u32(n_u32).ok_or(())? + } else { + return Err(()); + }; + + // Insert the new character and increment the insert position. + insert(i, c)?; + i += 1; + + // If there are no more deltas, decoding is complete. + if punycode_bytes.peek().is_none() { + return Ok(()); + } + + // Perform bias adaptation. + delta /= damp; + damp = 2; + + delta += delta / len; + let mut k = 0; + while delta > ((base - t_min) * t_max) / 2 { + delta /= base - t_min; + k += base; + } + bias = k + ((base - t_min + 1) * delta) / (delta + skew); + } + } +} + +impl<'s> Display for Ident<'s> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.try_small_punycode_decode(|chars| { + for &c in chars { + c.fmt(f)?; + } + Ok(()) + }) + .unwrap_or_else(|| { + if !self.punycode.is_empty() { + f.write_str("punycode{")?; + + // Reconstruct a standard Punycode encoding, + // by using `-` as the separator. + if !self.ascii.is_empty() { + f.write_str(self.ascii)?; + f.write_str("-")?; + } + f.write_str(self.punycode)?; + + f.write_str("}") + } else { + f.write_str(self.ascii) + } + }) + } +} + +fn basic_type(tag: u8) -> Option<&'static str> { + Some(match tag { + b'b' => "bool", + b'c' => "char", + b'e' => "str", + b'u' => "()", + b'a' => "i8", + b's' => "i16", + b'l' => "i32", + b'x' => "i64", + b'n' => "i128", + b'i' => "isize", + b'h' => "u8", + b't' => "u16", + b'm' => "u32", + b'y' => "u64", + b'o' => "u128", + b'j' => "usize", + b'f' => "f32", + b'd' => "f64", + b'z' => "!", + b'p' => "_", + b'v' => "...", + + _ => return None, + }) +} + +struct Parser<'s> { + sym: &'s str, + next: usize, + depth: u32, +} + +impl<'s> Parser<'s> { + fn push_depth(&mut self) -> Result<(), Invalid> { + self.depth += 1; + if self.depth > MAX_DEPTH { + Err(Invalid) + } else { + Ok(()) + } + } + + fn pop_depth(&mut self) { + self.depth -= 1; + } + + fn peek(&self) -> Option<u8> { + self.sym.as_bytes().get(self.next).cloned() + } + + fn eat(&mut self, b: u8) -> bool { + if self.peek() == Some(b) { + self.next += 1; + true + } else { + false + } + } + + fn next(&mut self) -> Result<u8, Invalid> { + let b = self.peek().ok_or(Invalid)?; + self.next += 1; + Ok(b) + } + + fn hex_nibbles(&mut self) -> Result<&'s str, Invalid> { + let start = self.next; + loop { + match self.next()? { + b'0'..=b'9' | b'a'..=b'f' => {} + b'_' => break, + _ => return Err(Invalid), + } + } + Ok(&self.sym[start..self.next - 1]) + } + + fn digit_10(&mut self) -> Result<u8, Invalid> { + let d = match self.peek() { + Some(d @ b'0'..=b'9') => d - b'0', + _ => return Err(Invalid), + }; + self.next += 1; + Ok(d) + } + + fn digit_62(&mut self) -> Result<u8, Invalid> { + let d = match self.peek() { + Some(d @ b'0'..=b'9') => d - b'0', + Some(d @ b'a'..=b'z') => 10 + (d - b'a'), + Some(d @ b'A'..=b'Z') => 10 + 26 + (d - b'A'), + _ => return Err(Invalid), + }; + self.next += 1; + Ok(d) + } + + fn integer_62(&mut self) -> Result<u64, Invalid> { + if self.eat(b'_') { + return Ok(0); + } + + let mut x: u64 = 0; + while !self.eat(b'_') { + let d = self.digit_62()? as u64; + x = x.checked_mul(62).ok_or(Invalid)?; + x = x.checked_add(d).ok_or(Invalid)?; + } + x.checked_add(1).ok_or(Invalid) + } + + fn opt_integer_62(&mut self, tag: u8) -> Result<u64, Invalid> { + if !self.eat(tag) { + return Ok(0); + } + self.integer_62()?.checked_add(1).ok_or(Invalid) + } + + fn disambiguator(&mut self) -> Result<u64, Invalid> { + self.opt_integer_62(b's') + } + + fn namespace(&mut self) -> Result<Option<char>, Invalid> { + match self.next()? { + // Special namespaces, like closures and shims. + ns @ b'A'..=b'Z' => Ok(Some(ns as char)), + + // Implementation-specific/unspecified namespaces. + b'a'..=b'z' => Ok(None), + + _ => Err(Invalid), + } + } + + fn backref(&mut self) -> Result<Parser<'s>, Invalid> { + let s_start = self.next - 1; + let i = self.integer_62()?; + if i >= s_start as u64 { + return Err(Invalid); + } + let mut new_parser = Parser { + sym: self.sym, + next: i as usize, + depth: self.depth, + }; + new_parser.push_depth()?; + Ok(new_parser) + } + + fn ident(&mut self) -> Result<Ident<'s>, Invalid> { + let is_punycode = self.eat(b'u'); + let mut len = self.digit_10()? as usize; + if len != 0 { + while let Ok(d) = self.digit_10() { + len = len.checked_mul(10).ok_or(Invalid)?; + len = len.checked_add(d as usize).ok_or(Invalid)?; + } + } + + // Skip past the optional `_` separator. + self.eat(b'_'); + + let start = self.next; + self.next = self.next.checked_add(len).ok_or(Invalid)?; + if self.next > self.sym.len() { + return Err(Invalid); + } + + let ident = &self.sym[start..self.next]; + + if is_punycode { + let ident = match ident.bytes().rposition(|b| b == b'_') { + Some(i) => Ident { + ascii: &ident[..i], + punycode: &ident[i + 1..], + }, + None => Ident { + ascii: "", + punycode: ident, + }, + }; + if ident.punycode.is_empty() { + return Err(Invalid); + } + Ok(ident) + } else { + Ok(Ident { + ascii: ident, + punycode: "", + }) + } + } + + fn skip_path(&mut self) -> Result<(), Invalid> { + self.push_depth()?; + + match self.next()? { + b'C' => { + self.disambiguator()?; + self.ident()?; + } + b'N' => { + self.namespace()?; + self.skip_path()?; + self.disambiguator()?; + self.ident()?; + } + b'M' => { + self.disambiguator()?; + self.skip_path()?; + self.skip_type()?; + } + b'X' => { + self.disambiguator()?; + self.skip_path()?; + self.skip_type()?; + self.skip_path()?; + } + b'Y' => { + self.skip_type()?; + self.skip_path()?; + } + b'I' => { + self.skip_path()?; + while !self.eat(b'E') { + self.skip_generic_arg()?; + } + } + b'B' => { + self.backref()?; + } + _ => return Err(Invalid), + } + Ok(()) + } + + fn skip_generic_arg(&mut self) -> Result<(), Invalid> { + self.push_depth()?; + + if self.eat(b'L') { + self.integer_62()?; + Ok(()) + } else if self.eat(b'K') { + self.skip_const() + } else { + self.skip_type() + } + } + + fn skip_type(&mut self) -> Result<(), Invalid> { + self.push_depth()?; + + match self.next()? { + tag if basic_type(tag).is_some() => {} + + b'R' | b'Q' => { + if self.eat(b'L') { + self.integer_62()?; + } + self.skip_type()?; + } + b'P' | b'O' | b'S' => self.skip_type()?, + b'A' => { + self.skip_type()?; + self.skip_const()?; + } + b'T' => { + while !self.eat(b'E') { + self.skip_type()?; + } + } + b'F' => { + let _binder = self.opt_integer_62(b'G')?; + let _is_unsafe = self.eat(b'U'); + if self.eat(b'K') { + let c_abi = self.eat(b'C'); + if !c_abi { + let abi = self.ident()?; + if abi.ascii.is_empty() || !abi.punycode.is_empty() { + return Err(Invalid); + } + } + } + while !self.eat(b'E') { + self.skip_type()?; + } + self.skip_type()?; + } + b'D' => { + let _binder = self.opt_integer_62(b'G')?; + while !self.eat(b'E') { + self.skip_path()?; + while self.eat(b'p') { + self.ident()?; + self.skip_type()?; + } + } + if !self.eat(b'L') { + return Err(Invalid); + } + self.integer_62()?; + } + b'B' => { + self.backref()?; + } + _ => { + // Go back to the tag, so `skip_path` also sees it. + self.next -= 1; + self.skip_path()?; + } + } + Ok(()) + } + + fn skip_const(&mut self) -> Result<(), Invalid> { + self.push_depth()?; + + if self.eat(b'B') { + self.backref()?; + return Ok(()); + } + + let ty_tag = self.next()?; + + if ty_tag == b'p' { + // We don't encode the type if the value is a placeholder. + return Ok(()); + } + + match ty_tag { + // Unsigned integer types. + b'h' | b't' | b'm' | b'y' | b'o' | b'j' | + // Bool. + b'b' | + // Char. + b'c' => {} + + // Signed integer types. + b'a' | b's' | b'l' | b'x' | b'n' | b'i' => { + // Negation on signed integers. + let _ = self.eat(b'n'); + } + + _ => return Err(Invalid), + } + + self.hex_nibbles()?; + Ok(()) + } +} + +struct Printer<'a, 'b: 'a, 's> { + parser: Result<Parser<'s>, Invalid>, + out: LimitedFormatter<'a, 'b>, + bound_lifetime_depth: u32, +} + +/// Mark the parser as errored, print `?` and return early. +/// This allows callers to keep printing the approximate +/// syntax of the path/type/const, despite having errors. +/// E.g. `Vec<[(A, ?); ?]>` instead of `Vec<[(A, ?`. +macro_rules! invalid { + ($printer:ident) => {{ + $printer.parser = Err(Invalid); + return $printer.out.write_str("?"); + }}; +} + +/// Call a parser method (if the parser hasn't errored yet), +/// and mark the parser as errored if it returns `Err(Invalid)`. +/// +/// If the parser errored, before or now, prints `?`, and +/// returns early the current function (see `invalid!` above). +macro_rules! parse { + ($printer:ident, $method:ident $(($($arg:expr),*))*) => { + match $printer.parser_mut().and_then(|p| p.$method($($($arg),*)*)) { + Ok(x) => x, + Err(Invalid) => invalid!($printer), + } + }; +} + +impl<'a, 'b, 's> Printer<'a, 'b, 's> { + fn parser_mut<'c>(&'c mut self) -> Result<&'c mut Parser<'s>, Invalid> { + self.parser.as_mut().map_err(|_| Invalid) + } + + /// Eat the given character from the parser, + /// returning `false` if the parser errored. + fn eat(&mut self, b: u8) -> bool { + self.parser_mut().map(|p| p.eat(b)) == Ok(true) + } + + /// Return a nested parser for a backref. + fn backref_printer<'c>(&'c mut self) -> Printer<'c, 'b, 's> { + Printer { + parser: self.parser_mut().and_then(|p| p.backref()), + out: LimitedFormatter { + remaining: self.out.remaining, + inner: self.out.inner, + }, + bound_lifetime_depth: self.bound_lifetime_depth, + } + } + + fn push_depth(&mut self) -> bool { + match self.parser { + Err(_) => false, + Ok(ref mut parser) => { + let _ = parser.push_depth(); + true + } + } + } + + fn pop_depth(&mut self) { + if let Ok(ref mut parser) = self.parser { + parser.pop_depth(); + } + } + + /// Print the lifetime according to the previously decoded index. + /// An index of `0` always refers to `'_`, but starting with `1`, + /// indices refer to late-bound lifetimes introduced by a binder. + fn print_lifetime_from_index(&mut self, lt: u64) -> fmt::Result { + self.out.write_str("'")?; + if lt == 0 { + return self.out.write_str("_"); + } + match (self.bound_lifetime_depth as u64).checked_sub(lt) { + Some(depth) => { + // Try to print lifetimes alphabetically first. + if depth < 26 { + let c = (b'a' + depth as u8) as char; + c.fmt(self.out.inner) + } else { + // Use `'_123` after running out of letters. + self.out.write_str("_")?; + depth.fmt(self.out.inner) + } + } + None => invalid!(self), + } + } + + /// Optionally enter a binder ('G') for late-bound lifetimes, + /// printing e.g. `for<'a, 'b> ` before calling the closure, + /// and make those lifetimes visible to it (via depth level). + fn in_binder<F>(&mut self, f: F) -> fmt::Result + where + F: FnOnce(&mut Self) -> fmt::Result, + { + let bound_lifetimes = parse!(self, opt_integer_62(b'G')); + if bound_lifetimes > 0 { + self.out.write_str("for<")?; + for i in 0..bound_lifetimes { + if i > 0 { + self.out.write_str(", ")?; + } + self.bound_lifetime_depth += 1; + self.print_lifetime_from_index(1)?; + } + self.out.write_str("> ")?; + } + + let r = f(self); + + // Restore `bound_lifetime_depth` to the previous value. + self.bound_lifetime_depth -= bound_lifetimes as u32; + + r + } + + /// Print list elements using the given closure and separator, + /// until the end of the list ('E') is found, or the parser errors. + /// Returns the number of elements printed. + fn print_sep_list<F>(&mut self, f: F, sep: &str) -> Result<usize, fmt::Error> + where + F: Fn(&mut Self) -> fmt::Result, + { + let mut i = 0; + while self.parser.is_ok() && !self.eat(b'E') { + if i > 0 { + self.out.write_str(sep)?; + } + f(self)?; + i += 1; + } + Ok(i) + } + + fn print_path(&mut self, in_value: bool) -> fmt::Result { + let tag = parse!(self, next); + match tag { + b'C' => { + let dis = parse!(self, disambiguator); + let name = parse!(self, ident); + + name.fmt(self.out.inner)?; + if !self.out.inner.alternate() { + self.out.write_str("[")?; + fmt::LowerHex::fmt(&dis, self.out.inner)?; + self.out.write_str("]")?; + } + } + b'N' => { + let ns = parse!(self, namespace); + + self.print_path(in_value)?; + + let dis = parse!(self, disambiguator); + let name = parse!(self, ident); + + match ns { + // Special namespaces, like closures and shims. + Some(ns) => { + self.out.write_str("::{")?; + match ns { + 'C' => self.out.write_str("closure")?, + 'S' => self.out.write_str("shim")?, + _ => ns.fmt(self.out.inner)?, + } + if !name.ascii.is_empty() || !name.punycode.is_empty() { + self.out.write_str(":")?; + name.fmt(self.out.inner)?; + } + self.out.write_str("#")?; + dis.fmt(self.out.inner)?; + self.out.write_str("}")?; + } + + // Implementation-specific/unspecified namespaces. + None => { + if !name.ascii.is_empty() || !name.punycode.is_empty() { + self.out.write_str("::")?; + name.fmt(self.out.inner)?; + } + } + } + } + b'M' | b'X' | b'Y' => { + if tag != b'Y' { + // Ignore the `impl`'s own path. + parse!(self, disambiguator); + parse!(self, skip_path); + } + + self.out.write_str("<")?; + self.print_type()?; + if tag != b'M' { + self.out.write_str(" as ")?; + self.print_path(false)?; + } + self.out.write_str(">")?; + } + b'I' => { + self.print_path(in_value)?; + if in_value { + self.out.write_str("::")?; + } + self.out.write_str("<")?; + self.print_sep_list(Self::print_generic_arg, ", ")?; + self.out.write_str(">")?; + } + b'B' => { + let mut backref_printer = self.backref_printer(); + backref_printer.print_path(in_value)?; + if backref_printer.parser.is_err() { + return Err(fmt::Error); + } + } + _ => invalid!(self), + } + Ok(()) + } + + fn print_generic_arg(&mut self) -> fmt::Result { + if self.eat(b'L') { + let lt = parse!(self, integer_62); + self.print_lifetime_from_index(lt) + } else if self.eat(b'K') { + self.print_const() + } else { + self.print_type() + } + } + + fn print_type(&mut self) -> fmt::Result { + let tag = parse!(self, next); + + if let Some(ty) = basic_type(tag) { + return self.out.write_str(ty); + } + + self.push_depth(); + + match tag { + b'R' | b'Q' => { + self.out.write_str("&")?; + if self.eat(b'L') { + let lt = parse!(self, integer_62); + if lt != 0 { + self.print_lifetime_from_index(lt)?; + self.out.write_str(" ")?; + } + } + if tag != b'R' { + self.out.write_str("mut ")?; + } + self.print_type()?; + } + + b'P' | b'O' => { + self.out.write_str("*")?; + if tag != b'P' { + self.out.write_str("mut ")?; + } else { + self.out.write_str("const ")?; + } + self.print_type()?; + } + + b'A' | b'S' => { + self.out.write_str("[")?; + self.print_type()?; + if tag == b'A' { + self.out.write_str("; ")?; + self.print_const()?; + } + self.out.write_str("]")?; + } + b'T' => { + self.out.write_str("(")?; + let count = self.print_sep_list(Self::print_type, ", ")?; + if count == 1 { + self.out.write_str(",")?; + } + self.out.write_str(")")?; + } + b'F' => self.in_binder(|this| { + let is_unsafe = this.eat(b'U'); + let abi = if this.eat(b'K') { + if this.eat(b'C') { + Some("C") + } else { + let abi = parse!(this, ident); + if abi.ascii.is_empty() || !abi.punycode.is_empty() { + invalid!(this); + } + Some(abi.ascii) + } + } else { + None + }; + + if is_unsafe { + this.out.write_str("unsafe ")?; + } + + if let Some(abi) = abi { + this.out.write_str("extern \"")?; + + // If the ABI had any `-`, they were replaced with `_`, + // so the parts between `_` have to be re-joined with `-`. + let mut parts = abi.split('_'); + this.out.write_str(parts.next().unwrap())?; + for part in parts { + this.out.write_str("-")?; + this.out.write_str(part)?; + } + + this.out.write_str("\" ")?; + } + + this.out.write_str("fn(")?; + this.print_sep_list(Self::print_type, ", ")?; + this.out.write_str(")")?; + + if this.eat(b'u') { + // Skip printing the return type if it's 'u', i.e. `()`. + } else { + this.out.write_str(" -> ")?; + this.print_type()?; + } + + Ok(()) + })?, + b'D' => { + self.out.write_str("dyn ")?; + self.in_binder(|this| { + this.print_sep_list(Self::print_dyn_trait, " + ")?; + Ok(()) + })?; + + if !self.eat(b'L') { + invalid!(self); + } + let lt = parse!(self, integer_62); + if lt != 0 { + self.out.write_str(" + ")?; + self.print_lifetime_from_index(lt)?; + } + } + b'B' => { + self.backref_printer().print_type()?; + } + _ => { + // Go back to the tag, so `print_path` also sees it. + let _ = self.parser_mut().map(|p| p.next -= 1); + self.print_path(false)?; + } + } + + self.pop_depth(); + Ok(()) + } + + /// A trait in a trait object may have some "existential projections" + /// (i.e. associated type bindings) after it, which should be printed + /// in the `<...>` of the trait, e.g. `dyn Trait<T, U, Assoc=X>`. + /// To this end, this method will keep the `<...>` of an 'I' path + /// open, by omitting the `>`, and return `Ok(true)` in that case. + fn print_path_maybe_open_generics(&mut self) -> Result<bool, fmt::Error> { + if self.eat(b'B') { + self.backref_printer().print_path_maybe_open_generics() + } else if self.eat(b'I') { + self.print_path(false)?; + self.out.write_str("<")?; + self.print_sep_list(Self::print_generic_arg, ", ")?; + Ok(true) + } else { + self.print_path(false)?; + Ok(false) + } + } + + fn print_dyn_trait(&mut self) -> fmt::Result { + let mut open = self.print_path_maybe_open_generics()?; + + while self.eat(b'p') { + if !open { + self.out.write_str("<")?; + open = true; + } else { + self.out.write_str(", ")?; + } + + let name = parse!(self, ident); + name.fmt(self.out.inner)?; + self.out.write_str(" = ")?; + self.print_type()?; + } + + if open { + self.out.write_str(">")?; + } + + Ok(()) + } + + fn print_const(&mut self) -> fmt::Result { + if self.eat(b'B') { + return self.backref_printer().print_const(); + } + + let ty_tag = parse!(self, next); + + if ty_tag == b'p' { + // We don't encode the type if the value is a placeholder. + self.out.write_str("_")?; + return Ok(()); + } + + match ty_tag { + // Unsigned integer types. + b'h' | b't' | b'm' | b'y' | b'o' | b'j' => self.print_const_uint()?, + // Signed integer types. + b'a' | b's' | b'l' | b'x' | b'n' | b'i' => self.print_const_int()?, + // Bool. + b'b' => self.print_const_bool()?, + // Char. + b'c' => self.print_const_char()?, + + // This branch ought to be unreachable. + _ => invalid!(self), + }; + + if !self.out.inner.alternate() { + self.out.write_str(": ")?; + let ty = basic_type(ty_tag).unwrap(); + self.out.write_str(ty)?; + } + + Ok(()) + } + + fn print_const_uint(&mut self) -> fmt::Result { + let hex = parse!(self, hex_nibbles); + + // Print anything that doesn't fit in `u64` verbatim. + if hex.len() > 16 { + self.out.write_str("0x")?; + return self.out.write_str(hex); + } + + let mut v = 0; + for c in hex.chars() { + v = (v << 4) | (c.to_digit(16).unwrap() as u64); + } + v.fmt(self.out.inner) + } + + fn print_const_int(&mut self) -> fmt::Result { + if self.eat(b'n') { + self.out.write_str("-")?; + } + + self.print_const_uint() + } + + fn print_const_bool(&mut self) -> fmt::Result { + match parse!(self, hex_nibbles).as_bytes() { + b"0" => self.out.write_str("false"), + b"1" => self.out.write_str("true"), + _ => invalid!(self), + } + } + + fn print_const_char(&mut self) -> fmt::Result { + let hex = parse!(self, hex_nibbles); + + // Valid `char`s fit in `u32`. + if hex.len() > 8 { + invalid!(self); + } + + let mut v = 0; + for c in hex.chars() { + v = (v << 4) | (c.to_digit(16).unwrap() as u32); + } + if let Some(c) = char::from_u32(v) { + write!(self.out, "{:?}", c) + } else { + invalid!(self) + } + } +} + +#[cfg(test)] +mod tests { + macro_rules! t_nohash { + ($a:expr, $b:expr) => {{ + assert_eq!(format!("{:#}", ::demangle($a)), $b); + }}; + } + macro_rules! t_nohash_type { + ($a:expr, $b:expr) => { + t_nohash!(concat!("_RMC0", $a), concat!("<", $b, ">")) + }; + } + + #[test] + fn demangle_crate_with_leading_digit() { + t_nohash!("_RNvC6_123foo3bar", "123foo::bar"); + } + + #[test] + fn demangle_utf8_idents() { + t_nohash!( + "_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y", + "utf8_idents::საჭმელად_გემრიელი_სადილი" + ); + } + + #[test] + fn demangle_closure() { + t_nohash!( + "_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_", + "cc::spawn::{closure#0}::{closure#0}" + ); + t_nohash!( + "_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_", + "<core::slice::Iter<u8> as core::iter::iterator::Iterator>::rposition::<core::slice::memchr::memrchr::{closure#1}>::{closure#0}" + ); + } + + #[test] + fn demangle_dyn_trait() { + t_nohash!( + "_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std", + "alloc::alloc::box_free::<dyn alloc::boxed::FnBox<(), Output = ()>>" + ); + } + + #[test] + fn demangle_const_generics() { + // NOTE(eddyb) this was hand-written, before rustc had working + // const generics support (but the mangling format did include them). + t_nohash_type!( + "INtC8arrayvec8ArrayVechKj7b_E", + "arrayvec::ArrayVec<u8, 123>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E", + "<const_generic::Unsigned<11>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E", + "<const_generic::Signed<152>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E", + "<const_generic::Signed<-11>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E", + "<const_generic::Bool<false>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E", + "<const_generic::Bool<true>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E", + "<const_generic::Char<'v'>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E", + "<const_generic::Char<'\\n'>>" + ); + t_nohash!( + "_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E", + "<const_generic::Char<'∂'>>" + ); + t_nohash!( + "_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO", + "<const_generic::Foo<_>>::foo::FOO" + ); + } + + #[test] + fn demangle_exponential_explosion() { + // NOTE(eddyb) because of the prefix added by `t_nohash_type!` is + // 3 bytes long, `B2_` refers to the start of the type, not `B_`. + // 6 backrefs (`B8_E` through `B3_E`) result in 2^6 = 64 copies of `_`. + // Also, because the `p` (`_`) type is after all of the starts of the + // backrefs, it can be replaced with any other type, independently. + t_nohash_type!( + concat!("TTTTTT", "p", "B8_E", "B7_E", "B6_E", "B5_E", "B4_E", "B3_E"), + "((((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \ + ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))), \ + (((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _)))), \ + ((((_, _), (_, _)), ((_, _), (_, _))), (((_, _), (_, _)), ((_, _), (_, _))))))" + ); + } + + #[test] + fn demangle_thinlto() { + t_nohash!("_RC3foo.llvm.9D1C9369", "foo"); + t_nohash!("_RC3foo.llvm.9D1C9369@@16", "foo"); + t_nohash!("_RNvC9backtrace3foo.llvm.A5310EB9", "backtrace::foo"); + } + + #[test] + fn demangle_extra_suffix() { + // From alexcrichton/rustc-demangle#27: + t_nohash!( + "_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0", + "rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0" + ); + } + + #[test] + fn demangling_limits() { + // Stress tests found via fuzzing. + + format!( + "{:?}", + ::demangle( + "RICu4$TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOSOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTO\ +OOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTOOOOOOOOOOOOOOOOOOOO\ +OTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOO\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOO\ +OOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOO\ +OOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTT\ +TTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxx\ +xxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOO\ +OOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOO\ +OOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOTTTTTTTTTTOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTYTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOO\ +OOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTO\ +OOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOO\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\ +OOOOOOOOOOOOOOOTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTT\ +TTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTT\ +TTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\ +\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +TTTTTxxxxxRICu4\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOO\ +OOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTT\ +TTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxR\ +ICu5\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOO\ +OOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu3\u{0005}\u{002c}\u{002d}xOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTO\ +OOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOxxxRICu4\u{002c}\u{002d}xxxxffff\u{0001}\u{0012}ffffffffffffffffffffffffffffffffffffffffffffff\ +ffffffffffxxxxxxxxxxxxxxxxxxxRaRBRaR\u{003e}R\u{003e}xxxu2IC\u{002c}\u{002d}xxxxxxRIC4xxxOOOOOOOOO\ +OOTTTOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO\ +OOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTxxxxxRICu4\ +\u{0005}\u{002c}\u{002d}xOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTTTOOOOOOOOOOOOOOOOOTTTTTTTT\ +TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOOOO\ +OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOxxxRICu4\u{002c}\u{002d}xxxxffff\u{0001}\u{0012}fffffffffffffff\ +fffffffffffffffffffffffffffffffffffffffffxxxxxxxxxxxxxxxxxxxRaRBRaR\u{003e}R\u{003e}xxxu2IC\ +\u{002c}\u{002d}xxxxxxRIC4xxx\u{0001}\u{0000}K\u{0000}\u{0000}xRBRaR\u{003e}RICu6$\u{002d}RBKIQARI\ +Cu6$\u{002d}RBKIQAA\u{0001}\u{0000}\u{0000}\u{0000}\u{0000}\u{0000}\u{0000}\u{0004}TvvKKKKKKKKKxxx\ +xxxxxxxxxxxxBKIQARICu6$\u{002d}RBKIQAA\u{0001}\u{0000}\u{0000}\u{0000}_\u{0000}xxx" + ) + ); + + format!( + "{:?}", + ::demangle( + "RIYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYY\ +YYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyY\ +YYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYFhhhhYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_R\ +XB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYY\ +YYXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYFhhhhYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYyYYYYYYMYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_R\ +XB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYyYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +MYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYMYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRYYYYYYYYYXB_RXB_lYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYXYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYMYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRXB_RXYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYIBRIIRIIBRCIByEEj_ByEEj_EEj" + ) + ); + + format!( + "{:?}", + ::demangle( + "RYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYY\ +YYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYY\ +YYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYY\ +YYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYR\ +YYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYY\ +YYYYYYYRYYYYYYYYYYYYYYYYYYSSSYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYSSSSRRRRRRRRRRRRRRRRRYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YY\ +YYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYY\ +YYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYY\ +YYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYY\ +YYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmY\ +YYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu\ +3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRR\ +RRRRRRRRRRRRRRRSSSSSSSRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYY\ +YYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSS\ +SSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYY\ +YYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYY\ +YYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYY\ +YYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSS\ +SSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYY\ +YYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYY\ +YYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +PYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYY\ +YYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRR\ +RRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYR\ +YYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYb\ +YYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYY\ +YYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYY\ +YYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYY\ +YYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRSSSSSSSRRRRRRRRRRRRRRRRRYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3\ +YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYY\ +YYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYY\ +YYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYY\ +YYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYY\ +mYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYY\ +YYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYY\ +YYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSS\ +SSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYY\ +YYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYY\ +YYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYY\ +YYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRY\ +YYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSS\ +SSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYY\ +YYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYY\ +YYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYY\ +YYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYY\ +YYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYY\ +mYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYY\ +YYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSSSSSSSSSS\ +SSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyY\ +YYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYY\ +YYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYY\ +YRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSYYYYYYYYYYYRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRSSSSSSSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSSSSSSSSSS\ +SSSSSSSSSSSYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYY\ +YYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSS\ +SSRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYYYYPYYyYYYbYYYYYYYYYYYYYYRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRYYYYYYYYYYYYYmYYYYYYYYYYYYYYYYYYYYYRCu3YYYYYYYYY\ +YYPYYYYYYbYYYYYYYYYRYYYYYYYYYYYYYYYYYYSSSSSSSSSSSS" + ) + ); + + format!( + "{:?}", + ::demangle( + "RYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYyYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY\ +R\u{003b}" + ) + ); + + format!( + "{:?}", + ::demangle( + "RIC20tRYIMYNRYFG05_EB5_B_B6_RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR\ +RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRB_E" + ) + ); + } +} + +struct LimitedFormatter<'a, 'b> { + remaining: &'a mut usize, + inner: &'a mut fmt::Formatter<'b>, +} + +impl Write for LimitedFormatter<'_, '_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.remaining.checked_sub(s.len()) { + Some(amt) => { + *self.remaining = amt; + self.inner.write_str(s) + } + None => Err(fmt::Error), + } + } +} |