Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/data.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
use crate::attr::Attribute;
4
use crate::expr::{Expr, Index, Member};
5
use crate::ident::Ident;
6
use crate::punctuated::{self, Punctuated};
7
use crate::restriction::{FieldMutability, Visibility};
8
use crate::token;
9
use crate::ty::Type;
10
11
ast_struct! {
12
/// An enum variant.
13
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
14
pub struct Variant {
15
pub attrs: Vec<Attribute>,
16
17
/// Name of the variant.
18
pub ident: Ident,
19
20
/// Content stored in the variant.
21
pub fields: Fields,
22
23
/// Explicit discriminant: `Variant = 1`
24
pub discriminant: Option<(Token![=], Expr)>,
25
}
26
}
27
28
ast_enum_of_structs! {
29
/// Data stored within an enum variant or struct.
30
///
31
/// # Syntax tree enum
32
///
33
/// This type is a [syntax tree enum].
34
///
35
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
36
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
37
pub enum Fields {
38
/// Named fields of a struct or struct variant such as `Point { x: f64,
39
/// y: f64 }`.
40
Named(FieldsNamed),
41
42
/// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
43
Unnamed(FieldsUnnamed),
44
45
/// Unit struct or unit variant such as `None`.
46
Unit,
47
}
48
}
49
50
ast_struct! {
51
/// Named fields of a struct or struct variant such as `Point { x: f64,
52
/// y: f64 }`.
53
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
54
pub struct FieldsNamed {
55
pub brace_token: token::Brace,
56
pub named: Punctuated<Field, Token![,]>,
57
}
58
}
59
60
ast_struct! {
61
/// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
62
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
63
pub struct FieldsUnnamed {
64
pub paren_token: token::Paren,
65
pub unnamed: Punctuated<Field, Token![,]>,
66
}
67
}
68
69
impl Fields {
70
/// Get an iterator over the borrowed [`Field`] items in this object. This
71
/// iterator can be used to iterate over a named or unnamed struct or
72
/// variant's fields uniformly.
73
pub fn iter(&self) -> punctuated::Iter<Field> {
74
match self {
75
Fields::Unit => crate::punctuated::empty_punctuated_iter(),
76
Fields::Named(f) => f.named.iter(),
77
Fields::Unnamed(f) => f.unnamed.iter(),
78
}
79
}
80
81
/// Get an iterator over the mutably borrowed [`Field`] items in this
82
/// object. This iterator can be used to iterate over a named or unnamed
83
/// struct or variant's fields uniformly.
84
pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
85
match self {
86
Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
87
Fields::Named(f) => f.named.iter_mut(),
88
Fields::Unnamed(f) => f.unnamed.iter_mut(),
89
}
90
}
91
92
/// Returns the number of fields.
93
pub fn len(&self) -> usize {
94
match self {
95
Fields::Unit => 0,
96
Fields::Named(f) => f.named.len(),
97
Fields::Unnamed(f) => f.unnamed.len(),
98
}
99
}
100
101
/// Returns `true` if there are zero fields.
102
pub fn is_empty(&self) -> bool {
103
match self {
104
Fields::Unit => true,
105
Fields::Named(f) => f.named.is_empty(),
106
Fields::Unnamed(f) => f.unnamed.is_empty(),
107
}
108
}
109
110
return_impl_trait! {
111
/// Get an iterator over the fields of a struct or variant as [`Member`]s.
112
/// This iterator can be used to iterate over a named or unnamed struct or
113
/// variant's fields uniformly.
114
///
115
/// # Example
116
///
117
/// The following is a simplistic [`Clone`] derive for structs. (A more
118
/// complete implementation would additionally want to infer trait bounds on
119
/// the generic type parameters.)
120
///
121
/// ```
122
/// # use quote::quote;
123
/// #
124
/// fn derive_clone(input: &syn::ItemStruct) -> proc_macro2::TokenStream {
125
/// let ident = &input.ident;
126
/// let members = input.fields.members();
127
/// let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
128
/// quote! {
129
/// impl #impl_generics Clone for #ident #ty_generics #where_clause {
130
/// fn clone(&self) -> Self {
131
/// Self {
132
/// #(#members: self.#members.clone()),*
133
/// }
134
/// }
135
/// }
136
/// }
137
/// }
138
/// ```
139
///
140
/// For structs with named fields, it produces an expression like `Self { a:
141
/// self.a.clone() }`. For structs with unnamed fields, `Self { 0:
142
/// self.0.clone() }`. And for unit structs, `Self {}`.
143
pub fn members(&self) -> impl Iterator<Item = Member> + Clone + '_ [Members] {
144
Members {
145
fields: self.iter(),
146
index: 0,
147
}
148
}
149
}
150
}
151
152
impl IntoIterator for Fields {
153
type Item = Field;
154
type IntoIter = punctuated::IntoIter<Field>;
155
156
fn into_iter(self) -> Self::IntoIter {
157
match self {
158
Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
159
Fields::Named(f) => f.named.into_iter(),
160
Fields::Unnamed(f) => f.unnamed.into_iter(),
161
}
162
}
163
}
164
165
impl<'a> IntoIterator for &'a Fields {
166
type Item = &'a Field;
167
type IntoIter = punctuated::Iter<'a, Field>;
168
169
fn into_iter(self) -> Self::IntoIter {
170
self.iter()
171
}
172
}
173
174
impl<'a> IntoIterator for &'a mut Fields {
175
type Item = &'a mut Field;
176
type IntoIter = punctuated::IterMut<'a, Field>;
177
178
fn into_iter(self) -> Self::IntoIter {
179
self.iter_mut()
180
}
181
}
182
183
ast_struct! {
184
/// A field of a struct or enum variant.
185
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
186
pub struct Field {
187
pub attrs: Vec<Attribute>,
188
189
pub vis: Visibility,
190
191
pub mutability: FieldMutability,
192
193
/// Name of the field, if any.
194
///
195
/// Fields of tuple structs have no names.
196
pub ident: Option<Ident>,
197
198
pub colon_token: Option<Token![:]>,
199
200
pub ty: Type,
201
}
202
}
203
204
pub struct Members<'a> {
205
fields: punctuated::Iter<'a, Field>,
206
index: u32,
207
}
208
209
impl<'a> Iterator for Members<'a> {
210
type Item = Member;
211
212
fn next(&mut self) -> Option<Self::Item> {
213
let field = self.fields.next()?;
214
let member = match &field.ident {
215
Some(ident) => Member::Named(ident.clone()),
216
None => {
217
#[cfg(all(feature = "parsing", feature = "printing"))]
218
let span = crate::spanned::Spanned::span(&field.ty);
219
#[cfg(not(all(feature = "parsing", feature = "printing")))]
220
let span = proc_macro2::Span::call_site();
221
Member::Unnamed(Index {
222
index: self.index,
223
span,
224
})
225
}
226
};
227
self.index += 1;
228
Some(member)
229
}
230
}
231
232
impl<'a> Clone for Members<'a> {
233
fn clone(&self) -> Self {
234
Members {
235
fields: self.fields.clone(),
236
index: self.index,
237
}
238
}
239
}
240
241
#[cfg(feature = "parsing")]
242
pub(crate) mod parsing {
243
use crate::attr::Attribute;
244
use crate::data::{Field, Fields, FieldsNamed, FieldsUnnamed, Variant};
245
use crate::error::Result;
246
use crate::expr::Expr;
247
use crate::ext::IdentExt as _;
248
use crate::ident::Ident;
249
#[cfg(not(feature = "full"))]
250
use crate::parse::discouraged::Speculative as _;
251
use crate::parse::{Parse, ParseStream};
252
use crate::restriction::{FieldMutability, Visibility};
253
#[cfg(not(feature = "full"))]
254
use crate::scan_expr::scan_expr;
255
use crate::token;
256
use crate::ty::Type;
257
use crate::verbatim;
258
259
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
260
impl Parse for Variant {
261
fn parse(input: ParseStream) -> Result<Self> {
262
let attrs = input.call(Attribute::parse_outer)?;
263
let _visibility: Visibility = input.parse()?;
264
let ident: Ident = input.parse()?;
265
let fields = if input.peek(token::Brace) {
266
Fields::Named(input.parse()?)
267
} else if input.peek(token::Paren) {
268
Fields::Unnamed(input.parse()?)
269
} else {
270
Fields::Unit
271
};
272
let discriminant = if input.peek(Token![=]) {
273
let eq_token: Token![=] = input.parse()?;
274
#[cfg(feature = "full")]
275
let discriminant: Expr = input.parse()?;
276
#[cfg(not(feature = "full"))]
277
let discriminant = {
278
let begin = input.fork();
279
let ahead = input.fork();
280
let mut discriminant: Result<Expr> = ahead.parse();
281
if discriminant.is_ok() {
282
input.advance_to(&ahead);
283
} else if scan_expr(input).is_ok() {
284
discriminant = Ok(Expr::Verbatim(verbatim::between(&begin, input)));
285
}
286
discriminant?
287
};
288
Some((eq_token, discriminant))
289
} else {
290
None
291
};
292
Ok(Variant {
293
attrs,
294
ident,
295
fields,
296
discriminant,
297
})
298
}
299
}
300
301
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
302
impl Parse for FieldsNamed {
303
fn parse(input: ParseStream) -> Result<Self> {
304
let content;
305
Ok(FieldsNamed {
306
brace_token: braced!(content in input),
307
named: content.parse_terminated(Field::parse_named, Token![,])?,
308
})
309
}
310
}
311
312
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
313
impl Parse for FieldsUnnamed {
314
fn parse(input: ParseStream) -> Result<Self> {
315
let content;
316
Ok(FieldsUnnamed {
317
paren_token: parenthesized!(content in input),
318
unnamed: content.parse_terminated(Field::parse_unnamed, Token![,])?,
319
})
320
}
321
}
322
323
impl Field {
324
/// Parses a named (braced struct) field.
325
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
326
pub fn parse_named(input: ParseStream) -> Result<Self> {
327
let attrs = input.call(Attribute::parse_outer)?;
328
let vis: Visibility = input.parse()?;
329
330
let unnamed_field = cfg!(feature = "full") && input.peek(Token![_]);
331
let ident = if unnamed_field {
332
input.call(Ident::parse_any)
333
} else {
334
input.parse()
335
}?;
336
337
let colon_token: Token![:] = input.parse()?;
338
339
let ty: Type = if unnamed_field
340
&& (input.peek(Token![struct])
341
|| input.peek(Token![union]) && input.peek2(token::Brace))
342
{
343
let begin = input.fork();
344
input.call(Ident::parse_any)?;
345
input.parse::<FieldsNamed>()?;
346
Type::Verbatim(verbatim::between(&begin, input))
347
} else {
348
input.parse()?
349
};
350
351
Ok(Field {
352
attrs,
353
vis,
354
mutability: FieldMutability::None,
355
ident: Some(ident),
356
colon_token: Some(colon_token),
357
ty,
358
})
359
}
360
361
/// Parses an unnamed (tuple struct) field.
362
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
363
pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
364
Ok(Field {
365
attrs: input.call(Attribute::parse_outer)?,
366
vis: input.parse()?,
367
mutability: FieldMutability::None,
368
ident: None,
369
colon_token: None,
370
ty: input.parse()?,
371
})
372
}
373
}
374
}
375
376
#[cfg(feature = "printing")]
377
mod printing {
378
use crate::data::{Field, FieldsNamed, FieldsUnnamed, Variant};
379
use crate::print::TokensOrDefault;
380
use proc_macro2::TokenStream;
381
use quote::{ToTokens, TokenStreamExt};
382
383
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
384
impl ToTokens for Variant {
385
fn to_tokens(&self, tokens: &mut TokenStream) {
386
tokens.append_all(&self.attrs);
387
self.ident.to_tokens(tokens);
388
self.fields.to_tokens(tokens);
389
if let Some((eq_token, disc)) = &self.discriminant {
390
eq_token.to_tokens(tokens);
391
disc.to_tokens(tokens);
392
}
393
}
394
}
395
396
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
397
impl ToTokens for FieldsNamed {
398
fn to_tokens(&self, tokens: &mut TokenStream) {
399
self.brace_token.surround(tokens, |tokens| {
400
self.named.to_tokens(tokens);
401
});
402
}
403
}
404
405
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
406
impl ToTokens for FieldsUnnamed {
407
fn to_tokens(&self, tokens: &mut TokenStream) {
408
self.paren_token.surround(tokens, |tokens| {
409
self.unnamed.to_tokens(tokens);
410
});
411
}
412
}
413
414
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
415
impl ToTokens for Field {
416
fn to_tokens(&self, tokens: &mut TokenStream) {
417
tokens.append_all(&self.attrs);
418
self.vis.to_tokens(tokens);
419
if let Some(ident) = &self.ident {
420
ident.to_tokens(tokens);
421
TokensOrDefault(&self.colon_token).to_tokens(tokens);
422
}
423
self.ty.to_tokens(tokens);
424
}
425
}
426
}
427
428