diff --git a/library/proc_macro/src/escape.rs b/library/proc_macro/src/escape.rs index 2c7f80969669..e1046f839d6b 100644 --- a/library/proc_macro/src/escape.rs +++ b/library/proc_macro/src/escape.rs @@ -1,5 +1,5 @@ use std::fmt::Write as _; -use std::str::Utf8Chunks; +use std::str; #[derive(Copy, Clone)] pub(crate) struct EscapeOptions { @@ -58,3 +58,55 @@ fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) { write!(repr, "{}", ch.escape_debug()).unwrap(); } } + +// FIXME: delete this and use std::str::Utf8Chunks once that is stable. +// https://github.com/rust-lang/rust/issues/99543 +// Mentioning the feature name so this comes up in search during stabilization: +// #![feature(utf8_chunks)] +struct Utf8Chunks<'a> { + bytes: &'a [u8], +} + +impl<'a> Utf8Chunks<'a> { + fn new(bytes: &'a [u8]) -> Self { + Utf8Chunks { bytes } + } +} + +impl<'a> Iterator for Utf8Chunks<'a> { + type Item = Utf8Chunk<'a>; + + fn next(&mut self) -> Option> { + if self.bytes.is_empty() { + return None; + } + + let (valid, invalid) = match str::from_utf8(self.bytes) { + Ok(all_valid) => (all_valid, b"" as &[u8]), + Err(utf8_error) => { + let (valid, rest) = self.bytes.split_at(utf8_error.valid_up_to()); + let valid = str::from_utf8(valid).unwrap(); + let invalid = utf8_error.error_len().map_or(rest, |error_len| &rest[..error_len]); + (valid, invalid) + } + }; + + self.bytes = &self.bytes[valid.len() + invalid.len()..]; + Some(Utf8Chunk { valid, invalid }) + } +} + +struct Utf8Chunk<'a> { + valid: &'a str, + invalid: &'a [u8], +} + +impl<'a> Utf8Chunk<'a> { + fn valid(&self) -> &'a str { + self.valid + } + + fn invalid(&self) -> &'a [u8] { + self.invalid + } +} diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index e48a20fa57d0..b8e4724f5eb6 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -34,7 +34,6 @@ #![feature(rustc_attrs)] #![feature(min_specialization)] #![feature(strict_provenance)] -#![feature(utf8_chunks)] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)]