Skip to content

Commit 9c092a3

Browse files
authored
Merge pull request #380 from dtolnay/octalescape
Circumvent clippy::octal_escapes lint in generated literals
2 parents c4a3e19 + 6c21627 commit 9c092a3

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

src/fallback.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -958,12 +958,20 @@ impl Literal {
958958
pub fn string(t: &str) -> Literal {
959959
let mut repr = String::with_capacity(t.len() + 2);
960960
repr.push('"');
961-
for c in t.chars() {
962-
if c == '\'' {
961+
let mut chars = t.chars();
962+
while let Some(ch) = chars.next() {
963+
if ch == '\0'
964+
&& chars
965+
.as_str()
966+
.starts_with(|next| '0' <= next && next <= '7')
967+
{
968+
// circumvent clippy::octal_escapes lint
969+
repr.push_str("\\x00");
970+
} else if ch == '\'' {
963971
// escape_debug turns this into "\'" which is unnecessary.
964-
repr.push(c);
972+
repr.push(ch);
965973
} else {
966-
repr.extend(c.escape_debug());
974+
repr.extend(ch.escape_debug());
967975
}
968976
}
969977
repr.push('"');
@@ -985,16 +993,21 @@ impl Literal {
985993

986994
pub fn byte_string(bytes: &[u8]) -> Literal {
987995
let mut escaped = "b\"".to_string();
988-
for b in bytes {
996+
let mut bytes = bytes.iter();
997+
while let Some(&b) = bytes.next() {
989998
#[allow(clippy::match_overlapping_arm)]
990-
match *b {
991-
b'\0' => escaped.push_str(r"\0"),
999+
match b {
1000+
b'\0' => escaped.push_str(match bytes.as_slice().first() {
1001+
// circumvent clippy::octal_escapes lint
1002+
Some(b'0'..=b'7') => r"\x00",
1003+
_ => r"\0",
1004+
}),
9921005
b'\t' => escaped.push_str(r"\t"),
9931006
b'\n' => escaped.push_str(r"\n"),
9941007
b'\r' => escaped.push_str(r"\r"),
9951008
b'"' => escaped.push_str("\\\""),
9961009
b'\\' => escaped.push_str("\\\\"),
997-
b'\x20'..=b'\x7E' => escaped.push(*b as char),
1010+
b'\x20'..=b'\x7E' => escaped.push(b as char),
9981011
_ => {
9991012
let _ = write!(escaped, "\\x{:02X}", b);
10001013
}

tests/test.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#![allow(
22
clippy::assertions_on_result_states,
33
clippy::items_after_statements,
4-
clippy::non_ascii_literal
4+
clippy::non_ascii_literal,
5+
clippy::octal_escapes
56
)]
67

78
use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
@@ -114,6 +115,11 @@ fn literal_string() {
114115
assert_eq!(Literal::string("foo").to_string(), "\"foo\"");
115116
assert_eq!(Literal::string("\"").to_string(), "\"\\\"\"");
116117
assert_eq!(Literal::string("didn't").to_string(), "\"didn't\"");
118+
119+
let repr = Literal::string("a\00b\07c\08d\0e\0").to_string();
120+
if repr != "\"a\\x000b\\x007c\\u{0}8d\\u{0}e\\u{0}\"" {
121+
assert_eq!(repr, "\"a\\x000b\\x007c\\08d\\0e\\0\"");
122+
}
117123
}
118124

119125
#[test]
@@ -147,6 +153,10 @@ fn literal_byte_string() {
147153
Literal::byte_string(b"\0\t\n\r\"\\2\x10").to_string(),
148154
"b\"\\0\\t\\n\\r\\\"\\\\2\\x10\"",
149155
);
156+
assert_eq!(
157+
Literal::byte_string(b"a\00b\07c\08d\0e\0").to_string(),
158+
"b\"a\\x000b\\x007c\\08d\\0e\\0\"",
159+
);
150160
}
151161

152162
#[test]

0 commit comments

Comments
 (0)