const_format_proc_macros/
datastructure.rs

1use syn::{
2    self, Attribute, Data, DeriveInput, Field as SynField, Fields as SynFields, Generics, Ident,
3    Type, Visibility,
4};
5
6use quote::ToTokens;
7
8use proc_macro2::TokenStream;
9
10use std::fmt::{self, Display};
11
12mod field_map;
13
14pub use self::field_map::FieldMap;
15
16//////////////////////////////////////////////////////////////////////////////
17
18/// A type definition(enum,struct,union).
19#[derive(Clone)]
20pub struct DataStructure<'a> {
21    pub vis: &'a Visibility,
22    pub name: &'a Ident,
23    pub generics: &'a Generics,
24    pub attrs: &'a [Attribute],
25
26    /// Whether this is a struct/union/enum.
27    pub data_variant: DataVariant,
28
29    /// The variants in the type definition.
30    ///
31    /// If it is a struct or a union this only has 1 element.
32    pub variants: Vec<Struct<'a>>,
33}
34
35impl<'a> DataStructure<'a> {
36    pub fn new(ast: &'a DeriveInput) -> Self {
37        let name = &ast.ident;
38
39        let data_variant: DataVariant;
40
41        let mut variants = Vec::new();
42
43        match &ast.data {
44            Data::Enum(enum_) => {
45                for (variant, var) in enum_.variants.iter().enumerate() {
46                    variants.push(Struct::new(
47                        StructParams {
48                            variant: variant,
49                            name: &var.ident,
50                        },
51                        &var.fields,
52                    ));
53                }
54                data_variant = DataVariant::Enum;
55            }
56            Data::Struct(struct_) => {
57                variants.push(Struct::new(
58                    StructParams {
59                        variant: 0,
60                        name: name,
61                    },
62                    &struct_.fields,
63                ));
64                data_variant = DataVariant::Struct;
65            }
66
67            Data::Union(union_) => {
68                let fields = Some(&union_.fields.named);
69                let sk = StructKind::Braced;
70                let vari = Struct::with_fields(
71                    StructParams {
72                        variant: 0,
73                        name: name,
74                    },
75                    sk,
76                    fields,
77                );
78                variants.push(vari);
79                data_variant = DataVariant::Union;
80            }
81        }
82
83        Self {
84            vis: &ast.vis,
85            name,
86            attrs: &ast.attrs,
87            generics: &ast.generics,
88            data_variant,
89            variants,
90        }
91    }
92}
93
94//////////////////////////////////////////////////////////////////////////////
95
96/// Whether the struct is tupled or not.
97#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
98pub enum StructKind {
99    /// structs declared using the `struct Name( ... ) syntax.
100    Tupled,
101    /// structs declared using the `struct Name{ ... }` or `struct name;` syntaxes
102    Braced,
103}
104
105#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
106pub enum DataVariant {
107    Struct,
108    Enum,
109    Union,
110}
111
112#[derive(Copy, Clone)]
113pub struct FieldIndex {
114    pub variant: usize,
115    pub pos: usize,
116}
117
118//////////////////////////////////////////////////////////////////////////////
119
120#[derive(Copy, Clone)]
121struct StructParams<'a> {
122    variant: usize,
123    name: &'a Ident,
124}
125
126/// A struct/union or a variant of an enum.
127#[derive(Clone)]
128pub struct Struct<'a> {
129    /// The name of this `Struct`.
130    ///
131    /// If this is a struct/union:these is the same as DataStructure.name.
132    ///
133    /// If this is an enum:this is the name of the variant.
134    pub name: &'a Ident,
135    pub kind: StructKind,
136    pub fields: Vec<Field<'a>>,
137    _priv: (),
138}
139
140impl<'a> Struct<'a> {
141    fn new(p: StructParams<'a>, fields: &'a SynFields) -> Self {
142        let kind = match *fields {
143            SynFields::Named { .. } => StructKind::Braced,
144            SynFields::Unnamed { .. } => StructKind::Tupled,
145            SynFields::Unit { .. } => StructKind::Braced,
146        };
147        let fields = match fields {
148            SynFields::Named(f) => Some(&f.named),
149            SynFields::Unnamed(f) => Some(&f.unnamed),
150            SynFields::Unit => None,
151        };
152
153        Self::with_fields(p, kind, fields)
154    }
155
156    fn with_fields<I>(p: StructParams<'a>, kind: StructKind, fields: Option<I>) -> Self
157    where
158        I: IntoIterator<Item = &'a SynField>,
159    {
160        let fields = match fields {
161            Some(x) => Field::from_iter(p, x),
162            None => Vec::new(),
163        };
164
165        Self {
166            name: p.name,
167            kind,
168            fields,
169            _priv: (),
170        }
171    }
172}
173
174//////////////////////////////////////////////////////////////////////////////
175
176/// Represent a struct field
177///
178#[derive(Clone)]
179pub struct Field<'a> {
180    pub index: FieldIndex,
181    pub attrs: &'a [Attribute],
182    /// identifier for the field,which is either an index(in a tuple struct) or a name.
183    pub ident: FieldIdent<'a>,
184    pub pattern_ident: Ident,
185    pub ty: &'a Type,
186}
187
188impl<'a> Field<'a> {
189    fn new(index: FieldIndex, field: &'a SynField) -> Self {
190        let span;
191        let ident = match field.ident.as_ref() {
192            Some(ident) => {
193                span = ident.span();
194                FieldIdent::Named(ident)
195            }
196            None => {
197                span = syn::spanned::Spanned::span(&field.ty);
198                FieldIdent::new_index(index.pos)
199            }
200        };
201        let pattern_ident = Ident::new(&format!("f{}_7ac4rtizw8q", ident), span);
202
203        Self {
204            index,
205            attrs: &field.attrs,
206            ident,
207            pattern_ident,
208            ty: &field.ty,
209        }
210    }
211
212    /// Gets the identifier of this field as an `&Ident`.
213    pub fn pattern_ident(&self) -> &Ident {
214        &self.pattern_ident
215    }
216
217    fn from_iter<I>(p: StructParams<'a>, fields: I) -> Vec<Self>
218    where
219        I: IntoIterator<Item = &'a SynField>,
220    {
221        fields
222            .into_iter()
223            .enumerate()
224            .map(|(pos, f)| {
225                let fi = FieldIndex {
226                    variant: p.variant,
227                    pos,
228                };
229                Field::new(fi, f)
230            })
231            .collect()
232    }
233}
234
235//////////////////////////////////////////////////////////////////////////////
236
237#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
238pub enum FieldIdent<'a> {
239    Index(usize),
240    Named(&'a Ident),
241}
242
243impl<'a> Display for FieldIdent<'a> {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        match self {
246            FieldIdent::Index(x) => Display::fmt(x, f),
247            FieldIdent::Named(x) => Display::fmt(x, f),
248        }
249    }
250}
251
252impl<'a> ToTokens for FieldIdent<'a> {
253    fn to_tokens(&self, tokens: &mut TokenStream) {
254        match *self {
255            FieldIdent::Index(ind) => syn::Index::from(ind).to_tokens(tokens),
256            FieldIdent::Named(name) => name.to_tokens(tokens),
257        }
258    }
259}
260
261impl<'a> FieldIdent<'a> {
262    fn new_index(index: usize) -> Self {
263        FieldIdent::Index(index)
264    }
265}