diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 69 |
1 files changed, 60 insertions, 9 deletions
@@ -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); |