Skip to content

Commit f4b269d

Browse files
Create non-exhaustive proc_macro::EscapeError enum mirrorring rustc-literal-escaper's
1 parent b3f7e32 commit f4b269d

1 file changed

Lines changed: 137 additions & 11 deletions

File tree

library/proc_macro/src/lib.rs

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ mod diagnostic;
4444
mod escape;
4545
mod to_tokens;
4646

47+
use core::convert::From;
4748
use core::ops::BitOr;
4849
use std::ffi::CStr;
4950
use std::ops::{Range, RangeBounds};
@@ -53,8 +54,6 @@ use std::{error, fmt};
5354

5455
#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
5556
pub use diagnostic::{Diagnostic, Level, MultiSpan};
56-
#[unstable(feature = "proc_macro_value", issue = "136652")]
57-
pub use rustc_literal_escaper::EscapeError;
5857
use rustc_literal_escaper::{
5958
MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str,
6059
};
@@ -64,6 +63,135 @@ pub use to_tokens::ToTokens;
6463
use crate::bridge::client::Methods as BridgeMethods;
6564
use crate::escape::{EscapeOptions, escape_bytes};
6665

66+
/// Mostly relating to malformed escape sequences, but also a few other problems.
67+
#[unstable(feature = "proc_macro_value", issue = "136652")]
68+
#[derive(Debug, PartialEq, Eq)]
69+
#[non_exhaustive]
70+
pub enum EscapeError {
71+
/// Expected 1 char, but 0 were found.
72+
ZeroChars,
73+
/// Expected 1 char, but more than 1 were found.
74+
MoreThanOneChar,
75+
76+
/// Escaped '\' character without continuation.
77+
LoneSlash,
78+
/// Invalid escape character (e.g. '\z').
79+
InvalidEscape,
80+
/// Raw '\r' encountered.
81+
BareCarriageReturn,
82+
/// Raw '\r' encountered in raw string.
83+
BareCarriageReturnInRawString,
84+
/// Unescaped character that was expected to be escaped (e.g. raw '\t').
85+
EscapeOnlyChar,
86+
87+
/// Numeric character escape is too short (e.g. '\x1').
88+
TooShortHexEscape,
89+
/// Invalid character in numeric escape (e.g. '\xz')
90+
InvalidCharInHexEscape,
91+
/// Character code in numeric escape is non-ascii (e.g. '\xFF').
92+
OutOfRangeHexEscape,
93+
94+
/// '\u' not followed by '{'.
95+
NoBraceInUnicodeEscape,
96+
/// Non-hexadecimal value in '\u{..}'.
97+
InvalidCharInUnicodeEscape,
98+
/// '\u{}'
99+
EmptyUnicodeEscape,
100+
/// No closing brace in '\u{..}', e.g. '\u{12'.
101+
UnclosedUnicodeEscape,
102+
/// '\u{_12}'
103+
LeadingUnderscoreUnicodeEscape,
104+
/// More than 6 characters in '\u{..}', e.g. '\u{10FFFF_FF}'
105+
OverlongUnicodeEscape,
106+
/// Invalid in-bound unicode character code, e.g. '\u{DFFF}'.
107+
LoneSurrogateUnicodeEscape,
108+
/// Out of bounds unicode character code, e.g. '\u{FFFFFF}'.
109+
OutOfRangeUnicodeEscape,
110+
111+
/// Unicode escape code in byte literal.
112+
UnicodeEscapeInByte,
113+
/// Non-ascii character in byte literal, byte string literal, or raw byte string literal.
114+
NonAsciiCharInByte,
115+
116+
/// `\0` in a C string literal.
117+
NulInCStr,
118+
119+
/// After a line ending with '\', the next line contains whitespace
120+
/// characters that are not skipped.
121+
UnskippedWhitespaceWarning,
122+
123+
/// After a line ending with '\', multiple lines are skipped.
124+
MultipleSkippedLinesWarning,
125+
}
126+
127+
#[unstable(feature = "proc_macro_value", issue = "136652")]
128+
#[doc(hidden)]
129+
impl From<rustc_literal_escaper::EscapeError> for EscapeError {
130+
fn from(value: rustc_literal_escaper::EscapeError) -> Self {
131+
use rustc_literal_escaper::EscapeError as EE;
132+
133+
match value {
134+
EE::ZeroChars => Self::ZeroChars,
135+
EE::MoreThanOneChar => Self::MoreThanOneChar,
136+
EE::LoneSlash => Self::LoneSlash,
137+
EE::InvalidEscape => Self::InvalidEscape,
138+
EE::BareCarriageReturn => Self::BareCarriageReturn,
139+
EE::BareCarriageReturnInRawString => Self::BareCarriageReturnInRawString,
140+
EE::EscapeOnlyChar => Self::EscapeOnlyChar,
141+
EE::TooShortHexEscape => Self::TooShortHexEscape,
142+
EE::InvalidCharInHexEscape => Self::InvalidCharInHexEscape,
143+
EE::OutOfRangeHexEscape => Self::OutOfRangeHexEscape,
144+
EE::NoBraceInUnicodeEscape => Self::NoBraceInUnicodeEscape,
145+
EE::InvalidCharInUnicodeEscape => Self::InvalidCharInUnicodeEscape,
146+
EE::EmptyUnicodeEscape => Self::EmptyUnicodeEscape,
147+
EE::UnclosedUnicodeEscape => Self::UnclosedUnicodeEscape,
148+
EE::LeadingUnderscoreUnicodeEscape => Self::LeadingUnderscoreUnicodeEscape,
149+
EE::OverlongUnicodeEscape => Self::OverlongUnicodeEscape,
150+
EE::LoneSurrogateUnicodeEscape => Self::LoneSurrogateUnicodeEscape,
151+
EE::OutOfRangeUnicodeEscape => Self::OutOfRangeUnicodeEscape,
152+
EE::UnicodeEscapeInByte => Self::UnicodeEscapeInByte,
153+
EE::NonAsciiCharInByte => Self::NonAsciiCharInByte,
154+
EE::NulInCStr => Self::NulInCStr,
155+
EE::UnskippedWhitespaceWarning => Self::UnskippedWhitespaceWarning,
156+
EE::MultipleSkippedLinesWarning => Self::MultipleSkippedLinesWarning,
157+
}
158+
}
159+
}
160+
161+
#[unstable(feature = "proc_macro_value", issue = "136652")]
162+
impl error::Error for EscapeError {}
163+
164+
#[unstable(feature = "proc_macro_value", issue = "136652")]
165+
impl fmt::Display for EscapeError {
166+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167+
f.write_str(match self {
168+
Self::ZeroChars => "zero chars",
169+
Self::MoreThanOneChar => "more than one char",
170+
Self::LoneSlash => "lone slash",
171+
Self::InvalidEscape => "invalid escape",
172+
Self::BareCarriageReturn => "bare carriage return",
173+
Self::BareCarriageReturnInRawString => "bare carriage return in raw string",
174+
Self::EscapeOnlyChar => "escape only char",
175+
Self::TooShortHexEscape => "too short hex escape",
176+
Self::InvalidCharInHexEscape => "invalid char in hex escape",
177+
Self::OutOfRangeHexEscape => "out of range hex escape",
178+
Self::NoBraceInUnicodeEscape => "no brace in unicode escape",
179+
Self::InvalidCharInUnicodeEscape => "invalid char in unicode escape",
180+
Self::EmptyUnicodeEscape => "empty unicode escape",
181+
Self::UnclosedUnicodeEscape => "unclosed unicode escape",
182+
Self::LeadingUnderscoreUnicodeEscape => "leading underscore unicode escape",
183+
Self::OverlongUnicodeEscape => "overlong unicode escape",
184+
Self::LoneSurrogateUnicodeEscape => "lone surrogate unicode escape",
185+
Self::OutOfRangeUnicodeEscape => "out of range unicode escape",
186+
Self::UnicodeEscapeInByte => "unicode escape in byte",
187+
Self::NonAsciiCharInByte => "non ascii char in byte",
188+
Self::NulInCStr => "nul in CStr",
189+
Self::UnskippedWhitespaceWarning => "unskipped whitespace warning",
190+
Self::MultipleSkippedLinesWarning => "multiple skipped lines warning",
191+
})
192+
}
193+
}
194+
67195
/// Errors returned when trying to retrieve a literal unescaped value.
68196
#[unstable(feature = "proc_macro_value", issue = "136652")]
69197
#[derive(Debug, PartialEq, Eq)]
@@ -1461,9 +1589,8 @@ impl Literal {
14611589
#[unstable(feature = "proc_macro_value", issue = "136652")]
14621590
pub fn byte_character_value(&self) -> Result<u8, ConversionErrorKind> {
14631591
self.0.symbol.with(|symbol| match self.0.kind {
1464-
bridge::LitKind::Char => {
1465-
unescape_byte(symbol).map_err(ConversionErrorKind::FailedToUnescape)
1466-
}
1592+
bridge::LitKind::Char => unescape_byte(symbol)
1593+
.map_err(|err| ConversionErrorKind::FailedToUnescape(err.into())),
14671594
_ => Err(ConversionErrorKind::InvalidLiteralKind),
14681595
})
14691596
}
@@ -1472,9 +1599,8 @@ impl Literal {
14721599
#[unstable(feature = "proc_macro_value", issue = "136652")]
14731600
pub fn character_value(&self) -> Result<char, ConversionErrorKind> {
14741601
self.0.symbol.with(|symbol| match self.0.kind {
1475-
bridge::LitKind::Char => {
1476-
unescape_char(symbol).map_err(ConversionErrorKind::FailedToUnescape)
1477-
}
1602+
bridge::LitKind::Char => unescape_char(symbol)
1603+
.map_err(|err| ConversionErrorKind::FailedToUnescape(err.into())),
14781604
_ => Err(ConversionErrorKind::InvalidLiteralKind),
14791605
})
14801606
}
@@ -1497,7 +1623,7 @@ impl Literal {
14971623
Ok(c) => buf.push(c),
14981624
Err(err) => {
14991625
if err.is_fatal() {
1500-
error = Some(ConversionErrorKind::FailedToUnescape(err));
1626+
error = Some(ConversionErrorKind::FailedToUnescape(err.into()));
15011627
}
15021628
}
15031629
},
@@ -1528,7 +1654,7 @@ impl Literal {
15281654
Ok(MixedUnit::HighByte(b)) => buf.push(b.get()),
15291655
Err(err) => {
15301656
if err.is_fatal() {
1531-
error = Some(ConversionErrorKind::FailedToUnescape(err));
1657+
error = Some(ConversionErrorKind::FailedToUnescape(err.into()));
15321658
}
15331659
}
15341660
});
@@ -1564,7 +1690,7 @@ impl Literal {
15641690
Ok(b) => buf.push(b),
15651691
Err(err) => {
15661692
if err.is_fatal() {
1567-
error = Some(ConversionErrorKind::FailedToUnescape(err));
1693+
error = Some(ConversionErrorKind::FailedToUnescape(err.into()));
15681694
}
15691695
}
15701696
});

0 commit comments

Comments
 (0)