Upgrade rustc-demangle to 0.1.23 am: 0ef60a4179

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/rustc-demangle/+/2955568

Change-Id: Ib20bcb6ca10c7e37266a570484447d6150a85b7b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 3b16060..ef99536 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "69fb82bd9c2da8b8977809e4d5d0c03109519831"
+    "sha1": "af38dc6b06b5665c79a4778268e4faf5decd19df"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index af83e04..dbece2f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@
     host_supported: true,
     crate_name: "rustc_demangle",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.22",
+    cargo_pkg_version: "0.1.23",
     srcs: ["src/lib.rs"],
     edition: "2015",
     apex_available: [
@@ -67,7 +67,7 @@
     host_supported: true,
     crate_name: "rustc_demangle",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.1.22",
+    cargo_pkg_version: "0.1.23",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
diff --git a/Cargo.toml b/Cargo.toml
index 60ef533..61238e3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,7 +11,7 @@
 
 [package]
 name = "rustc-demangle"
-version = "0.1.22"
+version = "0.1.23"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 description = """
 Rust compiler symbol demangling.
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 1deb42f..6534c7b 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "rustc-demangle"
-version = "0.1.22"
+version = "0.1.23"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
 license = "MIT/Apache-2.0"
 readme = "README.md"
diff --git a/METADATA b/METADATA
index bc073d8..a03a568 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update rust/crates/rustc-demangle
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/rust/crates/rustc-demangle
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 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.22.crate"
-  }
-  version: "0.1.22"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2023
-    month: 4
-    day: 3
+    year: 2024
+    month: 2
+    day: 8
+  }
+  homepage: "https://crates.io/crates/rustc-demangle"
+  identifier {
+    type: "Archive"
+    value: "https://static.crates.io/crates/rustc-demangle/rustc-demangle-0.1.23.crate"
+    version: "0.1.23"
   }
 }
diff --git a/src/lib.rs b/src/lib.rs
index 7eb1c42..cafec2f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -146,19 +146,24 @@
 }
 
 #[cfg(feature = "std")]
-fn demangle_line(line: &str, include_hash: bool) -> std::borrow::Cow<str> {
-    let mut line = std::borrow::Cow::Borrowed(line);
+fn demangle_line(
+    line: &str,
+    output: &mut impl std::io::Write,
+    include_hash: bool,
+) -> std::io::Result<()> {
     let mut head = 0;
-    loop {
+    while head < line.len() {
         // Move to the next potential match
-        head = match (line[head..].find("_ZN"), line[head..].find("_R")) {
+        let next_head = match (line[head..].find("_ZN"), line[head..].find("_R")) {
             (Some(idx), None) | (None, Some(idx)) => head + idx,
             (Some(idx1), Some(idx2)) => head + idx1.min(idx2),
             (None, None) => {
-                // No more matches, we can return our line.
-                return line;
+                // No more matches...
+                line.len()
             }
         };
+        output.write_all(line[head..next_head].as_bytes())?;
+        head = next_head;
         // Find the non-matching character.
         //
         // If we do not find a character, then until the end of the line is the
@@ -169,29 +174,26 @@
             .unwrap_or(line.len());
 
         let mangled = &line[head..match_end];
+        head = head + mangled.len();
         if let Ok(demangled) = try_demangle(mangled) {
-            let demangled = if include_hash {
-                format!("{}", demangled)
+            if include_hash {
+                write!(output, "{}", demangled)?;
             } else {
-                format!("{:#}", demangled)
-            };
-            line.to_mut().replace_range(head..match_end, &demangled);
-            // Start again after the replacement.
-            head = head + demangled.len();
+                write!(output, "{:#}", demangled)?;
+            }
         } else {
-            // Skip over the full symbol. We don't try to find a partial Rust symbol in the wider
-            // matched text today.
-            head = head + mangled.len();
+            output.write_all(mangled.as_bytes())?;
         }
     }
+    Ok(())
 }
 
 /// Process a stream of data from `input` into the provided `output`, demangling any symbols found
 /// within.
 ///
-/// This currently is implemented by buffering each line of input in memory, but that may be
-/// changed in the future. Symbols never cross line boundaries so this is just an implementation
-/// detail.
+/// Note that the underlying implementation will perform many relatively small writes to the
+/// output. If the output is expensive to write to (e.g., requires syscalls), consider using
+/// `std::io::BufWriter`.
 #[cfg(feature = "std")]
 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
 pub fn demangle_stream<R: std::io::BufRead, W: std::io::Write>(
@@ -206,8 +208,7 @@
     // trailing data during demangling. In the future we might directly stream to the output but at
     // least right now that seems to be less efficient.
     while input.read_line(&mut buf)? > 0 {
-        let demangled_line = demangle_line(&buf, include_hash);
-        output.write_all(demangled_line.as_bytes())?;
+        demangle_line(&buf, output, include_hash)?;
         buf.clear();
     }
     Ok(())
@@ -560,11 +561,18 @@
         );
     }
 
+    #[cfg(feature = "std")]
+    fn demangle_str(input: &str) -> String {
+        let mut output = Vec::new();
+        super::demangle_line(input, &mut output, false);
+        String::from_utf8(output).unwrap()
+    }
+
     #[test]
     #[cfg(feature = "std")]
     fn find_multiple() {
         assert_eq!(
-            super::demangle_line("_ZN3fooE.llvm moocow _ZN3fooE.llvm", false),
+            demangle_str("_ZN3fooE.llvm moocow _ZN3fooE.llvm"),
             "foo.llvm moocow foo.llvm"
         );
     }
@@ -573,7 +581,7 @@
     #[cfg(feature = "std")]
     fn interleaved_new_legacy() {
         assert_eq!(
-            super::demangle_line("_ZN3fooE.llvm moocow _RNvMNtNtNtNtCs8a2262Dv4r_3mio3sys4unix8selector5epollNtB2_8Selector6select _ZN3fooE.llvm", false),
+            demangle_str("_ZN3fooE.llvm moocow _RNvMNtNtNtNtCs8a2262Dv4r_3mio3sys4unix8selector5epollNtB2_8Selector6select _ZN3fooE.llvm"),
             "foo.llvm moocow <mio::sys::unix::selector::epoll::Selector>::select foo.llvm"
         );
     }