syn_solidity/lit/
str.rs

1use crate::{kw, Spanned};
2use proc_macro2::Span;
3use std::{
4    fmt,
5    ops::{Deref, DerefMut},
6};
7use syn::{
8    parse::{Lookahead1, Parse, ParseStream},
9    Result,
10};
11
12macro_rules! str_lit {
13    ($(#[$attr:meta])* $vis:vis struct $name:ident($t:ty) $(: $kw:ident)?) => {
14        #[derive(Clone, Debug)]
15        $vis struct $name {
16            $vis values: Vec<$t>,
17        }
18
19        impl fmt::Display for $name {
20            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21                for (i, value) in self.values.iter().enumerate() {
22                    if i > 0 {
23                        f.write_str(" ")?;
24                    }
25
26                    $(
27                        f.write_str(stringify!($kw))?;
28                    )?
29                    f.write_str(&value.value())?;
30                }
31                Ok(())
32            }
33        }
34
35        impl Parse for $name {
36            fn parse(input: ParseStream<'_>) -> Result<Self> {
37                let mut values = Vec::new();
38                let mut first = true;
39                while first || Self::peek(&input.lookahead1()) {
40                    first = false;
41                    values.push(input.parse()?);
42                }
43                Ok(Self { values })
44            }
45        }
46
47        impl Spanned for $name {
48            fn span(&self) -> Span {
49                self.values.span()
50            }
51
52            fn set_span(&mut self, span: Span) {
53                self.values.set_span(span);
54            }
55        }
56
57        impl $name {
58            pub fn peek(lookahead: &Lookahead1<'_>) -> bool {
59                $(lookahead.peek(kw::$kw) || )? lookahead.peek(syn::LitStr)
60            }
61
62            pub fn parse_opt(input: ParseStream<'_>) -> Result<Option<Self>> {
63                if Self::peek(&input.lookahead1()) {
64                    input.parse().map(Some)
65                } else {
66                    Ok(None)
67                }
68            }
69
70            pub fn value(&self) -> String {
71                self.values.iter().map(|v| v.value()).collect()
72            }
73        }
74    };
75}
76
77macro_rules! wrap_str {
78    ($(#[$attr:meta])* $vis:vis struct $name:ident { $token:ident : kw::$kw:ident $(,)? }) => {
79        $(#[$attr])*
80        #[derive(Clone)]
81        $vis struct $name {
82            /// The prefix of the string.
83            $vis $token: kw::$kw,
84            /// The string literal.
85            $vis value: syn::LitStr,
86        }
87
88        impl fmt::Debug for $name {
89            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90                f.debug_struct(stringify!($name))
91                    .field("value", &self.value)
92                    .finish()
93            }
94        }
95
96        impl Deref for $name {
97            type Target = syn::LitStr;
98
99            #[inline]
100            fn deref(&self) -> &Self::Target {
101                &self.value
102            }
103        }
104
105        impl DerefMut for $name {
106            #[inline]
107            fn deref_mut(&mut self) -> &mut Self::Target {
108                &mut self.value
109            }
110        }
111
112        impl Parse for $name {
113            fn parse(input: ParseStream<'_>) -> Result<Self> {
114                Ok(Self {
115                    $token: input.parse()?,
116                    value: input.parse()?,
117                })
118            }
119        }
120
121        impl Spanned for $name {
122            fn span(&self) -> Span {
123                let span = self.$token.span;
124                span.join(self.value.span()).unwrap_or(span)
125            }
126
127            fn set_span(&mut self, span: Span) {
128                self.$token.span = span;
129                self.value.set_span(span);
130            }
131        }
132    };
133}
134
135str_lit! {
136    /// A string literal.
137    pub struct LitStr(syn::LitStr)
138}
139
140str_lit! {
141    /// A unicode string literal.
142    pub struct LitUnicodeStr(UnicodeStr): unicode
143}
144
145wrap_str! {
146    /// A unicode string.
147    pub struct UnicodeStr {
148        unicode_token: kw::unicode,
149    }
150}
151
152str_lit! {
153    /// A hex string literal.
154    pub struct LitHexStr(HexStr): hex
155}
156
157wrap_str! {
158    /// A hex string.
159    pub struct HexStr {
160        hex_token: kw::hex,
161    }
162}