|
34 | 34 | #![feature(rustc_attrs)]
|
35 | 35 | #![feature(min_specialization)]
|
36 | 36 | #![feature(strict_provenance)]
|
| 37 | +#![feature(utf8_chunks)] |
37 | 38 | #![recursion_limit = "256"]
|
38 | 39 | #![allow(internal_features)]
|
39 | 40 | #![deny(ffi_unwind_calls)]
|
|
43 | 44 | pub mod bridge;
|
44 | 45 |
|
45 | 46 | mod diagnostic;
|
| 47 | +mod escape; |
46 | 48 |
|
47 | 49 | #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
|
48 | 50 | pub use diagnostic::{Diagnostic, Level, MultiSpan};
|
49 | 51 |
|
| 52 | +use crate::escape::{escape_bytes, EscapeOptions}; |
50 | 53 | use std::ffi::CStr;
|
51 | 54 | use std::ops::{Range, RangeBounds};
|
52 | 55 | use std::path::PathBuf;
|
@@ -1344,40 +1347,61 @@ impl Literal {
|
1344 | 1347 | /// String literal.
|
1345 | 1348 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
|
1346 | 1349 | pub fn string(string: &str) -> Literal {
|
1347 |
| - let quoted = format!("{:?}", string); |
1348 |
| - assert!(quoted.starts_with('"') && quoted.ends_with('"')); |
1349 |
| - let symbol = "ed[1..quoted.len() - 1]; |
1350 |
| - Literal::new(bridge::LitKind::Str, symbol, None) |
| 1350 | + let escape = EscapeOptions { |
| 1351 | + escape_single_quote: false, |
| 1352 | + escape_double_quote: true, |
| 1353 | + escape_nonascii: false, |
| 1354 | + }; |
| 1355 | + let repr = escape_bytes(string.as_bytes(), escape); |
| 1356 | + Literal::new(bridge::LitKind::Str, &repr, None) |
1351 | 1357 | }
|
1352 | 1358 |
|
1353 | 1359 | /// Character literal.
|
1354 | 1360 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
|
1355 | 1361 | pub fn character(ch: char) -> Literal {
|
1356 |
| - let quoted = format!("{:?}", ch); |
1357 |
| - assert!(quoted.starts_with('\'') && quoted.ends_with('\'')); |
1358 |
| - let symbol = "ed[1..quoted.len() - 1]; |
1359 |
| - Literal::new(bridge::LitKind::Char, symbol, None) |
| 1362 | + let escape = EscapeOptions { |
| 1363 | + escape_single_quote: true, |
| 1364 | + escape_double_quote: false, |
| 1365 | + escape_nonascii: false, |
| 1366 | + }; |
| 1367 | + let repr = escape_bytes(ch.encode_utf8(&mut [0u8; 4]).as_bytes(), escape); |
| 1368 | + Literal::new(bridge::LitKind::Char, &repr, None) |
1360 | 1369 | }
|
1361 | 1370 |
|
1362 | 1371 | /// Byte character literal.
|
1363 | 1372 | #[stable(feature = "proc_macro_byte_character", since = "CURRENT_RUSTC_VERSION")]
|
1364 | 1373 | pub fn byte_character(byte: u8) -> Literal {
|
1365 |
| - let string = [byte].escape_ascii().to_string(); |
1366 |
| - Literal::new(bridge::LitKind::Byte, &string, None) |
| 1374 | + let escape = EscapeOptions { |
| 1375 | + escape_single_quote: true, |
| 1376 | + escape_double_quote: false, |
| 1377 | + escape_nonascii: true, |
| 1378 | + }; |
| 1379 | + let repr = escape_bytes(&[byte], escape); |
| 1380 | + Literal::new(bridge::LitKind::Byte, &repr, None) |
1367 | 1381 | }
|
1368 | 1382 |
|
1369 | 1383 | /// Byte string literal.
|
1370 | 1384 | #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
|
1371 | 1385 | pub fn byte_string(bytes: &[u8]) -> Literal {
|
1372 |
| - let string = bytes.escape_ascii().to_string(); |
1373 |
| - Literal::new(bridge::LitKind::ByteStr, &string, None) |
| 1386 | + let escape = EscapeOptions { |
| 1387 | + escape_single_quote: false, |
| 1388 | + escape_double_quote: true, |
| 1389 | + escape_nonascii: true, |
| 1390 | + }; |
| 1391 | + let repr = escape_bytes(bytes, escape); |
| 1392 | + Literal::new(bridge::LitKind::ByteStr, &repr, None) |
1374 | 1393 | }
|
1375 | 1394 |
|
1376 | 1395 | /// C string literal.
|
1377 | 1396 | #[stable(feature = "proc_macro_c_str_literals", since = "CURRENT_RUSTC_VERSION")]
|
1378 | 1397 | pub fn c_string(string: &CStr) -> Literal {
|
1379 |
| - let string = string.to_bytes().escape_ascii().to_string(); |
1380 |
| - Literal::new(bridge::LitKind::CStr, &string, None) |
| 1398 | + let escape = EscapeOptions { |
| 1399 | + escape_single_quote: false, |
| 1400 | + escape_double_quote: true, |
| 1401 | + escape_nonascii: false, |
| 1402 | + }; |
| 1403 | + let repr = escape_bytes(string.to_bytes(), escape); |
| 1404 | + Literal::new(bridge::LitKind::CStr, &repr, None) |
1381 | 1405 | }
|
1382 | 1406 |
|
1383 | 1407 | /// Returns the span encompassing this literal.
|
|
0 commit comments