Skip to content

Commit

Permalink
Implement proc macro literal escaping without unstable Utf8Chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Apr 11, 2024
1 parent ccf4cc5 commit dd461af
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
54 changes: 53 additions & 1 deletion library/proc_macro/src/escape.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::fmt::Write as _;
use std::str::Utf8Chunks;
use std::str;

#[derive(Copy, Clone)]
pub(crate) struct EscapeOptions {
Expand Down Expand Up @@ -58,3 +58,55 @@ fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) {
write!(repr, "{}", ch.escape_debug()).unwrap();
}
}

// TODO: delete this and use std::str::Utf8Chunks once that is stable.

Check failure on line 62 in library/proc_macro/src/escape.rs

View workflow job for this annotation

GitHub Actions / PR - mingw-check-tidy

TODO is used for tasks that should be done before merging a PR; If you want to leave a message in the codebase use FIXME
// 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<Utf8Chunk<'a>> {
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
}
}
1 change: 0 additions & 1 deletion library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

0 comments on commit dd461af

Please sign in to comment.