summaryrefslogtreecommitdiffstats
path: root/src/fallback.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 05:38:30 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 05:38:30 +0000
commit7a5d77da248199cc79019b3e264d2b8f5186f883 (patch)
treea8b0ee19e56b828c857f2ce0d6865298ee62bccf /src/fallback.rs
parentAdding debian version 1.0.76-1. (diff)
downloadrust-proc-macro2-7a5d77da248199cc79019b3e264d2b8f5186f883.tar.xz
rust-proc-macro2-7a5d77da248199cc79019b3e264d2b8f5186f883.zip
Merging upstream version 1.0.81.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/fallback.rs')
-rw-r--r--src/fallback.rs207
1 files changed, 145 insertions, 62 deletions
diff --git a/src/fallback.rs b/src/fallback.rs
index 7b40427..b42537b 100644
--- a/src/fallback.rs
+++ b/src/fallback.rs
@@ -11,9 +11,13 @@ use core::cell::RefCell;
use core::cmp;
use core::fmt::{self, Debug, Display, Write};
use core::mem::ManuallyDrop;
+#[cfg(span_locations)]
+use core::ops::Range;
use core::ops::RangeBounds;
use core::ptr;
-use core::str::FromStr;
+use core::str::{self, FromStr};
+use std::ffi::CStr;
+#[cfg(procmacro2_semver_exempt)]
use std::path::PathBuf;
/// Force use of proc-macro2's fallback implementation of the API for now, even
@@ -151,9 +155,9 @@ fn get_cursor(src: &str) -> Cursor {
// Create a dummy file & add it to the source map
#[cfg(not(fuzzing))]
- SOURCE_MAP.with(|cm| {
- let mut cm = cm.borrow_mut();
- let span = cm.add_file(src);
+ SOURCE_MAP.with(|sm| {
+ let mut sm = sm.borrow_mut();
+ let span = sm.add_file(src);
Cursor {
rest: src,
off: span.lo,
@@ -295,11 +299,13 @@ impl IntoIterator for TokenStream {
}
}
+#[cfg(procmacro2_semver_exempt)]
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct SourceFile {
path: PathBuf,
}
+#[cfg(procmacro2_semver_exempt)]
impl SourceFile {
/// Get the path to this source file as a string.
pub fn path(&self) -> PathBuf {
@@ -311,6 +317,7 @@ impl SourceFile {
}
}
+#[cfg(procmacro2_semver_exempt)]
impl Debug for SourceFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("SourceFile")
@@ -334,6 +341,12 @@ thread_local! {
});
}
+#[cfg(span_locations)]
+pub(crate) fn invalidate_current_thread_spans() {
+ #[cfg(not(fuzzing))]
+ SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1));
+}
+
#[cfg(all(span_locations, not(fuzzing)))]
struct FileInfo {
source_text: String,
@@ -366,7 +379,7 @@ impl FileInfo {
span.lo >= self.span.lo && span.hi <= self.span.hi
}
- fn source_text(&mut self, span: Span) -> String {
+ fn byte_range(&mut self, span: Span) -> Range<usize> {
let lo_char = (span.lo - self.span.lo) as usize;
// Look up offset of the largest already-computed char index that is
@@ -395,11 +408,15 @@ impl FileInfo {
let trunc_lo = &self.source_text[lo_byte..];
let char_len = (span.hi - span.lo) as usize;
- let source_text = match trunc_lo.char_indices().nth(char_len) {
- Some((offset, _ch)) => &trunc_lo[..offset],
- None => trunc_lo,
- };
- source_text.to_owned()
+ lo_byte..match trunc_lo.char_indices().nth(char_len) {
+ Some((offset, _ch)) => lo_byte + offset,
+ None => self.source_text.len(),
+ }
+ }
+
+ fn source_text(&mut self, span: Span) -> String {
+ let byte_range = self.byte_range(span);
+ self.source_text[byte_range].to_owned()
}
}
@@ -534,22 +551,37 @@ impl Span {
};
#[cfg(not(fuzzing))]
- SOURCE_MAP.with(|cm| {
- let cm = cm.borrow();
- let path = cm.filepath(*self);
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ let path = sm.filepath(*self);
SourceFile { path }
})
}
#[cfg(span_locations)]
+ pub fn byte_range(&self) -> Range<usize> {
+ #[cfg(fuzzing)]
+ return 0..0;
+
+ #[cfg(not(fuzzing))]
+ {
+ if self.is_call_site() {
+ 0..0
+ } else {
+ SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self))
+ }
+ }
+ }
+
+ #[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
#[cfg(fuzzing)]
return LineColumn { line: 0, column: 0 };
#[cfg(not(fuzzing))]
- SOURCE_MAP.with(|cm| {
- let cm = cm.borrow();
- let fi = cm.fileinfo(*self);
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ let fi = sm.fileinfo(*self);
fi.offset_line_column(self.lo as usize)
})
}
@@ -560,9 +592,9 @@ impl Span {
return LineColumn { line: 0, column: 0 };
#[cfg(not(fuzzing))]
- SOURCE_MAP.with(|cm| {
- let cm = cm.borrow();
- let fi = cm.fileinfo(*self);
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
+ let fi = sm.fileinfo(*self);
fi.offset_line_column(self.hi as usize)
})
}
@@ -581,10 +613,10 @@ impl Span {
};
#[cfg(not(fuzzing))]
- SOURCE_MAP.with(|cm| {
- let cm = cm.borrow();
+ SOURCE_MAP.with(|sm| {
+ let sm = sm.borrow();
// If `other` is not within the same FileInfo as us, return None.
- if !cm.fileinfo(*self).span_within(other) {
+ if !sm.fileinfo(*self).span_within(other) {
return None;
}
Some(Span {
@@ -609,7 +641,7 @@ impl Span {
if self.is_call_site() {
None
} else {
- Some(SOURCE_MAP.with(|cm| cm.borrow_mut().fileinfo_mut(*self).source_text(*self)))
+ Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self)))
}
}
}
@@ -895,7 +927,7 @@ impl Debug for Ident {
#[derive(Clone)]
pub(crate) struct Literal {
- repr: String,
+ pub(crate) repr: String,
span: Span,
}
@@ -976,71 +1008,98 @@ impl Literal {
Literal::_new(s)
}
- pub fn string(t: &str) -> Literal {
- let mut repr = String::with_capacity(t.len() + 2);
+ pub fn string(string: &str) -> Literal {
+ let mut repr = String::with_capacity(string.len() + 2);
repr.push('"');
- let mut chars = t.chars();
- while let Some(ch) = chars.next() {
- if ch == '\0' {
- repr.push_str(
- if chars
- .as_str()
- .starts_with(|next| '0' <= next && next <= '7')
- {
- // circumvent clippy::octal_escapes lint
- "\\x00"
- } else {
- "\\0"
- },
- );
- } else if ch == '\'' {
- // escape_debug turns this into "\'" which is unnecessary.
- repr.push(ch);
- } else {
- repr.extend(ch.escape_debug());
- }
- }
+ escape_utf8(string, &mut repr);
repr.push('"');
Literal::_new(repr)
}
- pub fn character(t: char) -> Literal {
+ pub fn character(ch: char) -> Literal {
let mut repr = String::new();
repr.push('\'');
- if t == '"' {
+ if ch == '"' {
// escape_debug turns this into '\"' which is unnecessary.
- repr.push(t);
+ repr.push(ch);
} else {
- repr.extend(t.escape_debug());
+ repr.extend(ch.escape_debug());
+ }
+ repr.push('\'');
+ Literal::_new(repr)
+ }
+
+ pub fn byte_character(byte: u8) -> Literal {
+ let mut repr = "b'".to_string();
+ #[allow(clippy::match_overlapping_arm)]
+ match byte {
+ b'\0' => repr.push_str(r"\0"),
+ b'\t' => repr.push_str(r"\t"),
+ b'\n' => repr.push_str(r"\n"),
+ b'\r' => repr.push_str(r"\r"),
+ b'\'' => repr.push_str(r"\'"),
+ b'\\' => repr.push_str(r"\\"),
+ b'\x20'..=b'\x7E' => repr.push(byte as char),
+ _ => {
+ let _ = write!(repr, r"\x{:02X}", byte);
+ }
}
repr.push('\'');
Literal::_new(repr)
}
pub fn byte_string(bytes: &[u8]) -> Literal {
- let mut escaped = "b\"".to_string();
+ let mut repr = "b\"".to_string();
let mut bytes = bytes.iter();
while let Some(&b) = bytes.next() {
#[allow(clippy::match_overlapping_arm)]
match b {
- b'\0' => escaped.push_str(match bytes.as_slice().first() {
+ b'\0' => repr.push_str(match bytes.as_slice().first() {
// circumvent clippy::octal_escapes lint
Some(b'0'..=b'7') => r"\x00",
_ => r"\0",
}),
- b'\t' => escaped.push_str(r"\t"),
- b'\n' => escaped.push_str(r"\n"),
- b'\r' => escaped.push_str(r"\r"),
- b'"' => escaped.push_str("\\\""),
- b'\\' => escaped.push_str("\\\\"),
- b'\x20'..=b'\x7E' => escaped.push(b as char),
+ b'\t' => repr.push_str(r"\t"),
+ b'\n' => repr.push_str(r"\n"),
+ b'\r' => repr.push_str(r"\r"),
+ b'"' => repr.push_str("\\\""),
+ b'\\' => repr.push_str(r"\\"),
+ b'\x20'..=b'\x7E' => repr.push(b as char),
_ => {
- let _ = write!(escaped, "\\x{:02X}", b);
+ let _ = write!(repr, r"\x{:02X}", b);
+ }
+ }
+ }
+ repr.push('"');
+ Literal::_new(repr)
+ }
+
+ pub fn c_string(string: &CStr) -> Literal {
+ let mut repr = "c\"".to_string();
+ let mut bytes = string.to_bytes();
+ while !bytes.is_empty() {
+ let (valid, invalid) = match str::from_utf8(bytes) {
+ Ok(all_valid) => {
+ bytes = b"";
+ (all_valid, bytes)
+ }
+ Err(utf8_error) => {
+ let (valid, rest) = 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]);
+ bytes = &bytes[valid.len() + invalid.len()..];
+ (valid, invalid)
}
+ };
+ escape_utf8(valid, &mut repr);
+ for &byte in invalid {
+ let _ = write!(repr, r"\x{:02X}", byte);
}
}
- escaped.push('"');
- Literal::_new(escaped)
+ repr.push('"');
+ Literal::_new(repr)
}
pub fn span(&self) -> Span {
@@ -1141,3 +1200,27 @@ impl Debug for Literal {
debug.finish()
}
}
+
+fn escape_utf8(string: &str, repr: &mut String) {
+ let mut chars = string.chars();
+ while let Some(ch) = chars.next() {
+ if ch == '\0' {
+ repr.push_str(
+ if chars
+ .as_str()
+ .starts_with(|next| '0' <= next && next <= '7')
+ {
+ // circumvent clippy::octal_escapes lint
+ r"\x00"
+ } else {
+ r"\0"
+ },
+ );
+ } else if ch == '\'' {
+ // escape_debug turns this into "\'" which is unnecessary.
+ repr.push(ch);
+ } else {
+ repr.extend(ch.escape_debug());
+ }
+ }
+}