about summary refs log tree commit diff
path: root/library/alloc/src/string.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-09-21 22:09:47 +0000
committerbors <bors@rust-lang.org>2024-09-21 22:09:47 +0000
commit764e6aec81517cde60214ccd00a709a34eb0c07d (patch)
tree098f6fe0dcc9a44cb5280b813bda474854d0a1e5 /library/alloc/src/string.rs
parent1d68e6dd1deef26c5aeb91aee554edbee8b6d5e2 (diff)
parent52f146d363504d25b5e2fe468cadc2f50315da91 (diff)
downloadrust-764e6aec81517cde60214ccd00a709a34eb0c07d.tar.gz
rust-764e6aec81517cde60214ccd00a709a34eb0c07d.zip
Auto merge of #130674 - compiler-errors:rollup-yu105fl, r=compiler-errors
Rollup of 8 pull requests

Successful merges:

 - #127766 (add `extern "C-cmse-nonsecure-entry" fn` )
 - #129629 (Implement Return Type Notation (RTN)'s path form in where clauses)
 - #130408 (Avoid re-validating UTF-8 in `FromUtf8Error::into_utf8_lossy`)
 - #130651 (Add --enable-profiler to armhf dist)
 - #130653 (ABI compatibility: mention Result guarantee)
 - #130666 (Assert that `explicit_super_predicates_of` and `explicit_item_super_predicates` truly only contains bounds for the type itself)
 - #130667 (compiler: Accept "improper" ctypes in extern "rust-cold" fn)
 - #130673 (Parser: recover from `:::` to `::`)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library/alloc/src/string.rs')
-rw-r--r--library/alloc/src/string.rs26
1 files changed, 25 insertions, 1 deletions
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index d58a016b502..83977350832 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2087,7 +2087,31 @@ impl FromUtf8Error {
     #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")]
     pub fn into_utf8_lossy(self) -> String {
-        String::from_utf8_lossy_owned(self.bytes)
+        const REPLACEMENT: &str = "\u{FFFD}";
+
+        let mut res = {
+            let mut v = Vec::with_capacity(self.bytes.len());
+
+            // `Utf8Error::valid_up_to` returns the maximum index of validated
+            // UTF-8 bytes. Copy the valid bytes into the output buffer.
+            v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]);
+
+            // SAFETY: This is safe because the only bytes present in the buffer
+            // were validated as UTF-8 by the call to `String::from_utf8` which
+            // produced this `FromUtf8Error`.
+            unsafe { String::from_utf8_unchecked(v) }
+        };
+
+        let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks();
+
+        for chunk in iter {
+            res.push_str(chunk.valid());
+            if !chunk.invalid().is_empty() {
+                res.push_str(REPLACEMENT);
+            }
+        }
+
+        res
     }
 
     /// Returns the bytes that were attempted to convert to a `String`.