syn_serde/
token_stream.rs1use core::fmt::{self, Write};
4
5use super::*;
6
7ast_struct! {
8 #[derive(Clone, Default)]
10 #[serde(transparent)]
11 pub struct TokenStream {
12 inner: Vec<TokenTree>,
13 }
14}
15
16impl TokenStream {
17 fn _new(inner: Vec<TokenTree>) -> Self {
18 Self { inner }
19 }
20}
21
22ast_enum! {
23 #[derive(Clone)]
25 pub enum TokenTree {
26 Group(Group),
27 Ident(Ident),
28 Punct(Punct),
29 #[serde(rename = "lit")]
30 Literal(Literal),
31 }
32}
33
34ast_struct! {
35 #[derive(Clone)]
37 pub struct Group {
38 delimiter: Delimiter,
39 stream: TokenStream,
40 }
41}
42
43ast_enum! {
44 #[derive(Clone, Copy)]
46 pub enum Delimiter {
47 Parenthesis,
48 Brace,
49 Bracket,
50 None,
51 }
52}
53
54ast_struct! {
55 #[derive(Clone, Copy)]
57 pub struct Punct {
58 op: char,
59 spacing: Spacing,
60 }
61}
62
63ast_enum! {
64 #[derive(Clone, Copy)]
66 pub enum Spacing {
67 Alone,
68 Joint,
69 }
70}
71
72ast_struct! {
73 #[derive(Clone, Eq, PartialEq)]
75 #[serde(transparent)]
76 pub struct Ident {
77 inner: String,
78 }
79}
80
81ast_struct! {
82 #[derive(Clone)]
84 #[serde(transparent)]
85 pub struct Literal {
86 pub(crate) text: String,
87 }
88}
89
90impl Literal {
91 fn _new(text: String) -> Self {
92 Self { text }
93 }
94
95 pub(crate) fn u8_suffixed(n: u8) -> Self {
96 Self::_new(format!(concat!("{}", stringify!(u8)), n))
97 }
98
99 pub(crate) fn string(t: &str) -> Self {
100 let mut s = t.chars().flat_map(char::escape_default).collect::<String>();
101 s.push('"');
102 s.insert(0, '"');
103 Self::_new(s)
104 }
105
106 pub(crate) fn character(t: char) -> Self {
107 Self::_new(format!("'{}'", t.escape_default().collect::<String>()))
108 }
109
110 #[allow(clippy::match_overlapping_arm)]
111 pub(crate) fn byte_string(bytes: &[u8]) -> Self {
112 let mut escaped = "b\"".to_string();
113 for b in bytes {
114 match *b {
115 b'\0' => escaped.push_str(r"\0"),
116 b'\t' => escaped.push_str(r"\t"),
117 b'\n' => escaped.push_str(r"\n"),
118 b'\r' => escaped.push_str(r"\r"),
119 b'"' => escaped.push_str("\\\""),
120 b'\\' => escaped.push_str("\\\\"),
121 b'\x20'..=b'\x7E' => escaped.push(*b as char),
122 _ => {
123 let _ = write!(escaped, "\\x{:02X}", b);
124 }
125 }
126 }
127 escaped.push('"');
128 Self::_new(escaped)
129 }
130}
131
132impl fmt::Display for Literal {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 fmt::Display::fmt(&self.text, f)
136 }
137}
138
139mod convert {
140 use super::*;
141
142 syn_trait_impl!(proc_macro2::TokenStream);
144 impl From<&proc_macro2::TokenStream> for TokenStream {
145 fn from(other: &proc_macro2::TokenStream) -> Self {
146 Self::_new(other.clone().into_iter().map::<TokenTree, _>(|x| x.ref_into()).collect())
147 }
148 }
149 impl From<&TokenStream> for proc_macro2::TokenStream {
150 fn from(other: &TokenStream) -> Self {
151 other.inner.iter().map::<proc_macro2::TokenTree, _>(Into::into).collect()
152 }
153 }
154
155 syn_trait_impl!(proc_macro2::TokenTree);
157 impl From<&proc_macro2::TokenTree> for TokenTree {
158 fn from(other: &proc_macro2::TokenTree) -> Self {
159 use super::TokenTree::*;
160 match other {
161 proc_macro2::TokenTree::Group(t) => Group(t.into()),
162 proc_macro2::TokenTree::Ident(t) => Ident(t.into()),
163 proc_macro2::TokenTree::Punct(t) => Punct(t.into()),
164 proc_macro2::TokenTree::Literal(t) => Literal(t.into()),
165 }
166 }
167 }
168 impl From<&TokenTree> for proc_macro2::TokenTree {
169 fn from(other: &TokenTree) -> Self {
170 use proc_macro2::TokenTree::*;
171 match other {
172 TokenTree::Group(t) => Group(t.into()),
173 TokenTree::Ident(t) => Ident(t.into()),
174 TokenTree::Punct(t) => Punct(t.into()),
175 TokenTree::Literal(t) => Literal(t.into()),
176 }
177 }
178 }
179
180 syn_trait_impl!(proc_macro2::Group);
182 impl From<&proc_macro2::Group> for Group {
183 fn from(other: &proc_macro2::Group) -> Self {
184 Self { delimiter: other.delimiter().ref_into(), stream: other.stream().ref_into() }
185 }
186 }
187 impl From<&Group> for proc_macro2::Group {
188 fn from(other: &Group) -> Self {
189 Self::new(other.delimiter.ref_into(), other.stream.ref_into())
190 }
191 }
192
193 syn_trait_impl!(proc_macro2::Delimiter);
195 impl From<&proc_macro2::Delimiter> for Delimiter {
196 fn from(other: &proc_macro2::Delimiter) -> Self {
197 use super::Delimiter::*;
198 match other {
199 proc_macro2::Delimiter::Parenthesis => Parenthesis,
200 proc_macro2::Delimiter::Brace => Brace,
201 proc_macro2::Delimiter::Bracket => Bracket,
202 proc_macro2::Delimiter::None => None,
203 }
204 }
205 }
206 impl From<&Delimiter> for proc_macro2::Delimiter {
207 fn from(other: &Delimiter) -> Self {
208 use proc_macro2::Delimiter::*;
209 match other {
210 Delimiter::Parenthesis => Parenthesis,
211 Delimiter::Brace => Brace,
212 Delimiter::Bracket => Bracket,
213 Delimiter::None => None,
214 }
215 }
216 }
217
218 syn_trait_impl!(proc_macro2::Ident);
220 impl From<&proc_macro2::Ident> for Ident {
221 fn from(other: &proc_macro2::Ident) -> Self {
222 Self { inner: other.to_string() }
223 }
224 }
225 impl From<&Ident> for proc_macro2::Ident {
226 fn from(other: &Ident) -> Self {
227 Self::new(&other.inner, Span::call_site())
228 }
229 }
230
231 syn_trait_impl!(proc_macro2::Punct);
233 impl From<&proc_macro2::Punct> for Punct {
234 fn from(other: &proc_macro2::Punct) -> Self {
235 Self { op: other.as_char(), spacing: other.spacing().ref_into() }
236 }
237 }
238 impl From<&Punct> for proc_macro2::Punct {
239 fn from(other: &Punct) -> Self {
240 Self::new(other.op, other.spacing.ref_into())
241 }
242 }
243
244 syn_trait_impl!(proc_macro2::Spacing);
246 impl From<&proc_macro2::Spacing> for Spacing {
247 fn from(other: &proc_macro2::Spacing) -> Self {
248 use super::Spacing::*;
249 match other {
250 proc_macro2::Spacing::Alone => Alone,
251 proc_macro2::Spacing::Joint => Joint,
252 }
253 }
254 }
255 impl From<&Spacing> for proc_macro2::Spacing {
256 fn from(other: &Spacing) -> Self {
257 use proc_macro2::Spacing::*;
258 match other {
259 Spacing::Alone => Alone,
260 Spacing::Joint => Joint,
261 }
262 }
263 }
264
265 syn_trait_impl!(proc_macro2::Literal);
267 impl From<&proc_macro2::Literal> for Literal {
268 fn from(other: &proc_macro2::Literal) -> Self {
269 Self { text: other.to_string() }
270 }
271 }
272 impl From<&Literal> for proc_macro2::Literal {
273 fn from(other: &Literal) -> Self {
274 use proc_macro2::*;
275 let stream = other.text.parse::<TokenStream>().unwrap();
276 match stream.into_iter().next().unwrap() {
277 TokenTree::Literal(l) => l,
278 _ => unreachable!(),
279 }
280 }
281 }
282}