// SPDX-License-Identifier: Apache-2.0 OR MIT #[cfg(feature = "parsing")]use crate::lookahead;#[cfg(feature = "parsing")]use crate::parse::{Parse, Parser};use crate::{Error, Result};use proc_macro2::{Ident, Literal, Span};#[cfg(feature = "parsing")]use proc_macro2::{TokenStream, TokenTree};use std::ffi::{CStr, CString};use std::fmt::{self, Display};#[cfg(feature = "extra-traits")]use std::hash::{Hash, Hasher};use std::str::{self, FromStr}; ast_enum_of_structs! { /// A Rust literal such as a string or integer or boolean. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[non_exhaustive] pub enum Lit { /// A UTF-8 string literal: `"foo"`. Str(LitStr), /// A byte string literal: `b"foo"`. ByteStr(LitByteStr), /// A nul-terminated C-string literal: `c"foo"`. CStr(LitCStr), /// A byte literal: `b'f'`. Byte(LitByte), /// A character literal: `'a'`. Char(LitChar), /// An integer literal: `1` or `1u16`. Int(LitInt), /// A floating point literal: `1f64` or `1.0e10f64`. /// /// Must be finite. May not be infinite or NaN. Float(LitFloat), /// A boolean literal: `true` or `false`. Bool(LitBool), /// A raw token literal not interpreted by Syn. Verbatim(Literal), }} ast_struct! { /// A UTF-8 string literal: `"foo"`. pub struct LitStr { repr: Box<LitRepr>, }} ast_struct! { /// A byte string literal: `b"foo"`. pub struct LitByteStr { repr: Box<LitRepr>, }} ast_struct! { /// A nul-terminated C-string literal: `c"foo"`. pub struct LitCStr { repr: Box<LitRepr>, }} ast_struct! { /// A byte literal: `b'f'`. pub struct LitByte { repr: Box<LitRepr>, }} ast_struct! { /// A character literal: `'a'`. pub struct LitChar { repr: Box<LitRepr>, }} struct LitRepr { token: Literal, suffix: Box<str>,} ast_struct! { /// An integer literal: `1` or `1u16`. pub struct LitInt { repr: Box<LitIntRepr>, }} struct LitIntRepr { token: Literal, digits: Box<str>, suffix: Box<str>,} ast_struct! { /// A floating point literal: `1f64` or `1.0e10f64`. /// /// Must be finite. May not be infinite or NaN. pub struct LitFloat { repr: Box<LitFloatRepr>, }} struct LitFloatRepr { token: Literal, digits: Box<str>, suffix: Box<str>,} ast_struct! { /// A boolean literal: `true` or `false`. pub struct LitBool { pub value: bool, pub span: Span, }} impl LitStr { pub fn new(value: &str, span: Span) -> Self { let mut token = Literal::string(value); token.set_span(span); LitStr { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> String { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_str(&repr); String::from(value) } /// Parse a syntax tree node from the content of this string literal. /// /// All spans in the syntax tree will point to the span of this `LitStr`. /// /// # Example /// /// ``` /// use syn::{Attribute, Error, Expr, Lit, Meta, Path, Result}; /// /// // Parses the path from an attribute that looks like: /// // /// // #[path = "a::b::c"] /// // /// // or returns `None` if the input is some other attribute. /// fn get_path(attr: &Attribute) -> Result<Option<Path>> { /// if !attr.path().is_ident("path") { /// return Ok(None); /// } /// /// if let Meta::NameValue(meta) = &attr.meta { /// if let Expr::Lit(expr) = &meta.value { /// if let Lit::Str(lit_str) = &expr.lit { /// return lit_str.parse().map(Some); /// } /// } /// } /// /// let message = "expected #[path = \"...\"]"; /// Err(Error::new_spanned(attr, message)) /// } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse<T: Parse>(&self) -> Result<T> { self.parse_with(T::parse) } /// Invoke parser on the content of this string literal. /// /// All spans in the syntax tree will point to the span of this `LitStr`. /// /// # Example /// /// ``` /// # use proc_macro2::Span; /// # use syn::{LitStr, Result}; /// # /// # fn main() -> Result<()> { /// # let lit_str = LitStr::new("a::b::c", Span::call_site()); /// # /// # const IGNORE: &str = stringify! { /// let lit_str: LitStr = /* ... */; /// # }; /// /// // Parse a string literal like "a::b::c" into a Path, not allowing /// // generic arguments on any of the path segments. /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?; /// # /// # Ok(()) /// # } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> { use proc_macro2::Group; // Token stream with every span replaced by the given one. fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream { stream .into_iter() .map(|token| respan_token_tree(token, span)) .collect() } // Token tree with every span replaced by the given one. fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree { match &mut token { TokenTree::Group(g) => { let stream = respan_token_stream(g.stream(), span); *g = Group::new(g.delimiter(), stream); g.set_span(span); } other => other.set_span(span), } token } // Parse string literal into a token stream with every span equal to the // original literal's span. let span = self.span(); let mut tokens = TokenStream::from_str(&self.value())?; tokens = respan_token_stream(tokens, span); let result = crate::parse::parse_scoped(parser, span, tokens)?; let suffix = self.suffix(); if !suffix.is_empty() { return Err(Error::new( self.span(), format!("unexpected suffix `{}` on string literal", suffix), )); } Ok(result) } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() }} impl LitByteStr { pub fn new(value: &[u8], span: Span) -> Self { let mut token = Literal::byte_string(value); token.set_span(span); LitByteStr { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> Vec<u8> { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_byte_str(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() }} impl LitCStr { pub fn new(value: &CStr, span: Span) -> Self { let mut token = Literal::c_string(value); token.set_span(span); LitCStr { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> CString { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_c_str(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() }} impl LitByte { pub fn new(value: u8, span: Span) -> Self { let mut token = Literal::u8_suffixed(value); token.set_span(span); LitByte { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> u8 { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_byte(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() }} impl LitChar { pub fn new(value: char, span: Span) -> Self { let mut token = Literal::character(value); token.set_span(span); LitChar { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> char { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_char(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() }} impl LitInt { pub fn new(repr: &str, span: Span) -> Self { let (digits, suffix) = match value::parse_lit_int(repr) { Some(parse) => parse, None => panic!("not an integer literal: `{}`", repr), }; let mut token: Literal = repr.parse().unwrap(); token.set_span(span); LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), } } pub fn base10_digits(&self) -> &str { &self.repr.digits } /// Parses the literal into a selected number type. /// /// This is equivalent to `lit.base10_digits().parse()` except that the /// resulting errors will be correctly spanned to point to the literal token /// in the macro input. /// /// ``` /// use syn::LitInt; /// use syn::parse::{Parse, ParseStream, Result}; /// /// struct Port { /// value: u16, /// } /// /// impl Parse for Port { /// fn parse(input: ParseStream) -> Result<Self> { /// let lit: LitInt = input.parse()?; /// let value = lit.base10_parse::<u16>()?; /// Ok(Port { value }) /// } /// } /// ``` pub fn base10_parse<N>(&self) -> Result<N> where N: FromStr, N::Err: Display, { self.base10_digits() .parse() .map_err(|err| Error::new(self.span(), err)) } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn token(&self) -> Literal { self.repr.token.clone() }} impl From<Literal> for LitInt { fn from(token: Literal) -> Self { let repr = token.to_string(); if let Some((digits, suffix)) = value::parse_lit_int(&repr) { LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), } } else { panic!("not an integer literal: `{}`", repr); } }Lines 1–500 of 1862. Load more
// SPDX-License-Identifier: Apache-2.0 OR MIT #[cfg(feature = "parsing")] use crate::lookahead; #[cfg(feature = "parsing")] use crate::parse::{Parse, Parser}; use crate::{Error, Result}; use proc_macro2::{Ident, Literal, Span}; #[cfg(feature = "parsing")] use proc_macro2::{TokenStream, TokenTree}; use std::ffi::{CStr, CString}; use std::fmt::{self, Display}; #[cfg(feature = "extra-traits")] use std::hash::{Hash, Hasher}; use std::str::{self, FromStr}; ast_enum_of_structs! { /// A Rust literal such as a string or integer or boolean. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[non_exhaustive] pub enum Lit { /// A UTF-8 string literal: `"foo"`. Str(LitStr), /// A byte string literal: `b"foo"`. ByteStr(LitByteStr), /// A nul-terminated C-string literal: `c"foo"`. CStr(LitCStr), /// A byte literal: `b'f'`. Byte(LitByte), /// A character literal: `'a'`. Char(LitChar), /// An integer literal: `1` or `1u16`. Int(LitInt), /// A floating point literal: `1f64` or `1.0e10f64`. /// /// Must be finite. May not be infinite or NaN. Float(LitFloat), /// A boolean literal: `true` or `false`. Bool(LitBool), /// A raw token literal not interpreted by Syn. Verbatim(Literal), } } ast_struct! { /// A UTF-8 string literal: `"foo"`. pub struct LitStr { repr: Box<LitRepr>, } } ast_struct! { /// A byte string literal: `b"foo"`. pub struct LitByteStr { repr: Box<LitRepr>, } } ast_struct! { /// A nul-terminated C-string literal: `c"foo"`. pub struct LitCStr { repr: Box<LitRepr>, } } ast_struct! { /// A byte literal: `b'f'`. pub struct LitByte { repr: Box<LitRepr>, } } ast_struct! { /// A character literal: `'a'`. pub struct LitChar { repr: Box<LitRepr>, } } struct LitRepr { token: Literal, suffix: Box<str>, } ast_struct! { /// An integer literal: `1` or `1u16`. pub struct LitInt { repr: Box<LitIntRepr>, } } struct LitIntRepr { token: Literal, digits: Box<str>, suffix: Box<str>, } ast_struct! { /// A floating point literal: `1f64` or `1.0e10f64`. /// /// Must be finite. May not be infinite or NaN. pub struct LitFloat { repr: Box<LitFloatRepr>, } } struct LitFloatRepr { token: Literal, digits: Box<str>, suffix: Box<str>, } ast_struct! { /// A boolean literal: `true` or `false`. pub struct LitBool { pub value: bool, pub span: Span, } } impl LitStr { pub fn new(value: &str, span: Span) -> Self { let mut token = Literal::string(value); token.set_span(span); LitStr { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> String { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_str(&repr); String::from(value) } /// Parse a syntax tree node from the content of this string literal. /// /// All spans in the syntax tree will point to the span of this `LitStr`. /// /// # Example /// /// ``` /// use syn::{Attribute, Error, Expr, Lit, Meta, Path, Result}; /// /// // Parses the path from an attribute that looks like: /// // /// // #[path = "a::b::c"] /// // /// // or returns `None` if the input is some other attribute. /// fn get_path(attr: &Attribute) -> Result<Option<Path>> { /// if !attr.path().is_ident("path") { /// return Ok(None); /// } /// /// if let Meta::NameValue(meta) = &attr.meta { /// if let Expr::Lit(expr) = &meta.value { /// if let Lit::Str(lit_str) = &expr.lit { /// return lit_str.parse().map(Some); /// } /// } /// } /// /// let message = "expected #[path = \"...\"]"; /// Err(Error::new_spanned(attr, message)) /// } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse<T: Parse>(&self) -> Result<T> { self.parse_with(T::parse) } /// Invoke parser on the content of this string literal. /// /// All spans in the syntax tree will point to the span of this `LitStr`. /// /// # Example /// /// ``` /// # use proc_macro2::Span; /// # use syn::{LitStr, Result}; /// # /// # fn main() -> Result<()> { /// # let lit_str = LitStr::new("a::b::c", Span::call_site()); /// # /// # const IGNORE: &str = stringify! { /// let lit_str: LitStr = /* ... */; /// # }; /// /// // Parse a string literal like "a::b::c" into a Path, not allowing /// // generic arguments on any of the path segments. /// let basic_path = lit_str.parse_with(syn::Path::parse_mod_style)?; /// # /// # Ok(()) /// # } /// ``` #[cfg(feature = "parsing")] #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn parse_with<F: Parser>(&self, parser: F) -> Result<F::Output> { use proc_macro2::Group; // Token stream with every span replaced by the given one. fn respan_token_stream(stream: TokenStream, span: Span) -> TokenStream { stream .into_iter() .map(|token| respan_token_tree(token, span)) .collect() } // Token tree with every span replaced by the given one. fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree { match &mut token { TokenTree::Group(g) => { let stream = respan_token_stream(g.stream(), span); *g = Group::new(g.delimiter(), stream); g.set_span(span); } other => other.set_span(span), } token } // Parse string literal into a token stream with every span equal to the // original literal's span. let span = self.span(); let mut tokens = TokenStream::from_str(&self.value())?; tokens = respan_token_stream(tokens, span); let result = crate::parse::parse_scoped(parser, span, tokens)?; let suffix = self.suffix(); if !suffix.is_empty() { return Err(Error::new( self.span(), format!("unexpected suffix `{}` on string literal", suffix), )); } Ok(result) } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitByteStr { pub fn new(value: &[u8], span: Span) -> Self { let mut token = Literal::byte_string(value); token.set_span(span); LitByteStr { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> Vec<u8> { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_byte_str(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitCStr { pub fn new(value: &CStr, span: Span) -> Self { let mut token = Literal::c_string(value); token.set_span(span); LitCStr { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> CString { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_c_str(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitByte { pub fn new(value: u8, span: Span) -> Self { let mut token = Literal::u8_suffixed(value); token.set_span(span); LitByte { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> u8 { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_byte(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitChar { pub fn new(value: char, span: Span) -> Self { let mut token = Literal::character(value); token.set_span(span); LitChar { repr: Box::new(LitRepr { token, suffix: Box::<str>::default(), }), } } pub fn value(&self) -> char { let repr = self.repr.token.to_string(); let (value, _suffix) = value::parse_lit_char(&repr); value } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl LitInt { pub fn new(repr: &str, span: Span) -> Self { let (digits, suffix) = match value::parse_lit_int(repr) { Some(parse) => parse, None => panic!("not an integer literal: `{}`", repr), }; let mut token: Literal = repr.parse().unwrap(); token.set_span(span); LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), } } pub fn base10_digits(&self) -> &str { &self.repr.digits } /// Parses the literal into a selected number type. /// /// This is equivalent to `lit.base10_digits().parse()` except that the /// resulting errors will be correctly spanned to point to the literal token /// in the macro input. /// /// ``` /// use syn::LitInt; /// use syn::parse::{Parse, ParseStream, Result}; /// /// struct Port { /// value: u16, /// } /// /// impl Parse for Port { /// fn parse(input: ParseStream) -> Result<Self> { /// let lit: LitInt = input.parse()?; /// let value = lit.base10_parse::<u16>()?; /// Ok(Port { value }) /// } /// } /// ``` pub fn base10_parse<N>(&self) -> Result<N> where N: FromStr, N::Err: Display, { self.base10_digits() .parse() .map_err(|err| Error::new(self.span(), err)) } pub fn suffix(&self) -> &str { &self.repr.suffix } pub fn span(&self) -> Span { self.repr.token.span() } pub fn set_span(&mut self, span: Span) { self.repr.token.set_span(span); } pub fn token(&self) -> Literal { self.repr.token.clone() } } impl From<Literal> for LitInt { fn from(token: Literal) -> Self { let repr = token.to_string(); if let Some((digits, suffix)) = value::parse_lit_int(&repr) { LitInt { repr: Box::new(LitIntRepr { token, digits, suffix, }), } } else { panic!("not an integer literal: `{}`", repr); } }