const_format_proc_macros/
datastructure.rs1use 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#[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 pub data_variant: DataVariant,
28
29 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#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
98pub enum StructKind {
99 Tupled,
101 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#[derive(Copy, Clone)]
121struct StructParams<'a> {
122 variant: usize,
123 name: &'a Ident,
124}
125
126#[derive(Clone)]
128pub struct Struct<'a> {
129 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#[derive(Clone)]
179pub struct Field<'a> {
180 pub index: FieldIndex,
181 pub attrs: &'a [Attribute],
182 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 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#[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}