aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs69
1 files changed, 60 insertions, 9 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 8979099..80c1b98 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,7 @@
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
-//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <br>
//!
@@ -138,7 +138,9 @@
//! ```
#![allow(
+ clippy::derive_partial_eq_without_eq,
clippy::doc_markdown,
+ clippy::match_same_arms,
clippy::module_name_repetitions,
clippy::needless_doctest_main,
clippy::too_many_lines
@@ -154,6 +156,7 @@ use crate::attr::expand_attr;
use crate::error::{Error, Result};
use crate::segment::Segment;
use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
+use std::char;
use std::iter;
use std::panic;
@@ -161,8 +164,18 @@ use std::panic;
pub fn paste(input: TokenStream) -> TokenStream {
let mut contains_paste = false;
let flatten_single_interpolation = true;
- match expand(input, &mut contains_paste, flatten_single_interpolation) {
- Ok(expanded) => expanded,
+ match expand(
+ input.clone(),
+ &mut contains_paste,
+ flatten_single_interpolation,
+ ) {
+ Ok(expanded) => {
+ if contains_paste {
+ expanded
+ } else {
+ input
+ }
+ }
Err(err) => err.to_compile_error(),
}
}
@@ -363,14 +376,32 @@ fn parse_bracket_as_segments(input: TokenStream, scope: Span) -> Result<Vec<Segm
for segment in &mut segments {
if let Segment::String(string) = segment {
- if string.value.contains(&['#', '\\', '.', '+'][..]) {
+ if string.value.starts_with("'\\u{") {
+ let hex = &string.value[4..string.value.len() - 2];
+ if let Ok(unsigned) = u32::from_str_radix(hex, 16) {
+ if let Some(ch) = char::from_u32(unsigned) {
+ string.value.clear();
+ string.value.push(ch);
+ continue;
+ }
+ }
+ }
+ if string.value.contains(&['#', '\\', '.', '+'][..])
+ || string.value.starts_with("b'")
+ || string.value.starts_with("b\"")
+ || string.value.starts_with("br\"")
+ {
return Err(Error::new(string.span, "unsupported literal"));
}
- string.value = string
- .value
- .replace('"', "")
- .replace('\'', "")
- .replace('-', "_");
+ let mut range = 0..string.value.len();
+ if string.value.starts_with("r\"") {
+ range.start += 2;
+ range.end -= 1;
+ } else if string.value.starts_with(&['"', '\''][..]) {
+ range.start += 1;
+ range.end -= 1;
+ }
+ string.value = string.value[range].replace('-', "_");
}
}
@@ -380,6 +411,26 @@ fn parse_bracket_as_segments(input: TokenStream, scope: Span) -> Result<Vec<Segm
fn pasted_to_tokens(mut pasted: String, span: Span) -> Result<TokenStream> {
let mut tokens = TokenStream::new();
+ #[cfg(not(no_literal_fromstr))]
+ {
+ use proc_macro::{LexError, Literal};
+ use std::str::FromStr;
+
+ if pasted.starts_with(|ch: char| ch.is_ascii_digit()) {
+ let literal = match panic::catch_unwind(|| Literal::from_str(&pasted)) {
+ Ok(Ok(literal)) => TokenTree::Literal(literal),
+ Ok(Err(LexError { .. })) | Err(_) => {
+ return Err(Error::new(
+ span,
+ &format!("`{:?}` is not a valid literal", pasted),
+ ));
+ }
+ };
+ tokens.extend(iter::once(literal));
+ return Ok(tokens);
+ }
+ }
+
if pasted.starts_with('\'') {
let mut apostrophe = TokenTree::Punct(Punct::new('\'', Spacing::Joint));
apostrophe.set_span(span);