1use itertools::Itertools;
4use proc_macro2::TokenStream;
5use quote::{format_ident, quote, ToTokens};
6extern crate alloc;
7
8use syn::{Data, DataEnum, DataStruct, Fields, Ident};
9
10struct DeriveReflect<'a> {
12 consts: Vec<TokenStream>,
13 nesting: Option<String>,
14 parent_stack: Vec<Ident>,
16 most_recent_discriminant_expr: Option<(usize, TokenStream)>,
17 nightly_const: bool,
18 generics: &'a syn::Generics,
19 seen_types: Vec<&'a syn::Type>,
20}
21
22fn primitive(p: &syn::Lit) -> TokenStream {
23 match p {
24 syn::Lit::Str(s) => quote! {_reflect::RustPrimitive::Str(#s)},
25 syn::Lit::ByteStr(bs) => quote! {_reflect::RustPrimitive::ByteStr(#bs)},
26 syn::Lit::Byte(b) => quote! {_reflect::RustPrimitive::Byte(#b)},
27 syn::Lit::Char(c) => quote! {_reflect::RustPrimitive::Char(#c)},
28 syn::Lit::Int(i) => {
29 let i = i
31 .base10_parse::<i128>()
32 .expect("syntax error after parsing?");
33 quote! {_reflect::RustPrimitive::Int(#i) }
34 }
35 syn::Lit::Float(f) => {
36 let f = f
38 .base10_parse::<f64>()
39 .expect("syntax error after parsing?");
40 quote! {_reflect::RustPrimitive::Float(#f) }
41 }
42 syn::Lit::Bool(b) => quote! {_reflect::RustPrimitive::Bool(#b)},
43 syn::Lit::Verbatim(v) => panic!("not really sure what literal this is: {:?}", v),
44 }
45}
46
47impl<'a> DeriveReflect<'a> {
48 fn parent(&self) -> Ident {
49 format_ident!(
50 "{}",
51 self.parent_stack.iter().map(|x| x.to_string()).join("_")
52 )
53 }
54
55 fn nested<T>(&mut self, ix: usize, f: impl FnOnce(&mut Self) -> T) -> T {
56 let old_nesting = self.nesting.replace(
57 self.nesting
58 .as_ref()
59 .map_or(ix.to_string(), |n| format!("{}_{}", n, ix)),
60 );
61 let res = f(self);
62 self.nesting = old_nesting;
63 res
64 }
65
66 fn meta(&mut self, ix: usize, m: &syn::Meta) -> TokenStream {
67 match m {
68 syn::Meta::Path(p) => {
69 let p = p.to_token_stream().to_string();
70 quote! { Attr::Name(#p) }
71 }
72 syn::Meta::List(ml) => {
73 let nesteds = ml
74 .nested
75 .iter()
76 .map(|nested| match nested {
77 syn::NestedMeta::Meta(m) => self.nested(ix, |me| me.meta(0, m)),
78 syn::NestedMeta::Lit(l) => l.to_token_stream(),
79 })
80 .collect::<Vec<_>>();
81 let path = ml.path.to_token_stream().to_string();
82 let nesteds_ident = format_ident!(
83 "{}_META_{}_{}",
84 self.parent(),
85 ix,
86 self.nesting.as_ref().unwrap_or(&String::new())
87 );
88 self.consts.push(quote!{const #nesteds_ident : &'static [_reflect::Attr<'static>] = &[#(#nesteds),*]; });
89 let list = self.list_reference(nesteds_ident, nesteds);
90 quote! { _reflect::Attr::List(#path, #list) }
91 }
92 syn::Meta::NameValue(mnv) => {
93 let path = mnv.path.to_token_stream().to_string();
94 let lit = primitive(&mnv.lit);
95 quote! { _reflect::Attr::NameValue(#path, #lit) }
96 }
97 }
98 }
99 fn list_reference(&self, id: Ident, elts: Vec<TokenStream>) -> TokenStream {
100 if self.nightly_const {
101 quote! { alloc::borrow::Cow::Borrowed(#id) }
102 } else {
103 quote! { alloc::borrow::Cow::Owned(vec![#(#elts),*]) }
104 }
105 }
106
107 fn attrs(&mut self, attrs: &[syn::Attribute]) -> Vec<TokenStream> {
108 attrs
109 .iter()
110 .enumerate()
111 .map(|(ix, a)| self.meta(ix, &a.parse_meta().expect("expected meta in attribute")))
112 .collect()
113 }
114
115 fn field(&mut self, ix: usize, f: &'a syn::Field) -> TokenStream {
116 let attrs_name = format_ident!(
117 "{}_{}_ATTRS",
118 self.parent(),
119 f.ident
120 .clone()
121 .map_or_else(|| ix.to_string(), |f| f.to_string())
122 );
123 let ix = syn::Index::from(ix);
124
125 let attrs = self.attrs(&f.attrs);
126 self.consts.push(
127 quote! { const #attrs_name : &'static [_reflect::Attr<'static>] = & [#(#attrs),*] },
128 );
129 let attrs = self.list_reference(attrs_name, attrs);
130
131 let offset = match &f.ident {
132 Some(name) => {
133 quote! { memoffset::offset_of!(Self, #name) }
134 }
135 None => {
136 quote! { memoffset::offset_of!(Self, #ix) }
137 }
138 };
139
140 let field_ty = &f.ty;
141 let shape = self.visit_ty(offset.clone(), field_ty);
142
143 match &f.ident {
144 Some(name) => quote! {
145 _reflect::Field {
146 offset: #offset,
147 shape: #shape,
148 name: stringify!(#name),
149 attrs: #attrs,
150 }
151 },
152 None => {
153 quote! {
154 _reflect::TupleField {
155 offset: #offset,
156 shape: #shape,
157 attrs: #attrs,
158 }
159 }
160 }
161 }
162 }
163
164 fn visit_ty(&mut self, offset: TokenStream, ty: &'a syn::Type) -> TokenStream {
167 match ty {
168 syn::Type::Array(arr) => {
169 let nested_shape = self.visit_ty(offset, &arr.elem);
170 let len = &arr.len;
171 quote! { _reflect::DataShape::FixedArray(#nested_shape, #len)}
172 }
173 syn::Type::Paren(syn::TypeParen { elem, .. })
174 | syn::Type::Group(syn::TypeGroup { elem, .. }) => self.visit_ty(offset, elem),
175 syn::Type::Infer(_) => panic!("are these even allowed where we're parsing for types?"),
176 syn::Type::Path(path) => {
177 let p = path.to_token_stream();
178 quote! {
179 _reflect::_builtin_search(#path)
180 .unwrap_or(_reflect::DataShape::Leaf(core::any::TypeId::of::<#path>()))
181 }
182 }
183 syn::Type::Reference(refer) => {
184 let nested = self.visit_ty(quote! { 0 }, &refer.elem);
185 quote! { _reflect::DataShape::Ref(alloc::borrow::Cow::Owned(#nested)) }
186 }
187 syn::Type::Slice(slice) => {
188 let nested = self.visit_ty(quote! { 0 }, &slice.elem);
189 quote! { _reflect::DataShape::Slice(alloc::borrow::Cow::Owned(#nested)) }
190 }
191 syn::Type::Tuple(tuple) => {
192 let tup_elts = tuple
193 .elems
194 .iter()
195 .enumerate()
196 .map(|(ix, tp)| {
197 let ix = syn::Index::from(ix);
198 self.visit_ty(quote! { memoffset::offset_of_tuple!(#offset, #ix) }, tp)
199 })
200 .collect::<Vec<_>>();
201 let tup_elts_name = format_ident!("{}_TUP_ELTS", self.parent());
202 self.consts.push(
203 quote! { const #tup_elts_name : &'static [_reflect::DataShape<'static>] = &[#(#tup_elts),*]; },
204 );
205
206 let tup_elts = self.list_reference(tup_elts_name, tup_elts);
207 quote! { _reflect::DataShape::Tuple(#tup_elts) }
208 }
209
210 syn::Type::__Nonexhaustive => unreachable!(),
211 syn::Type::BareFn(_) => panic!("don't reflect over function pointers"),
212 m @ syn::Type::ImplTrait(_)
213 | m @ syn::Type::TraitObject(_)
214 | m @ syn::Type::Verbatim(_)
215 | m @ syn::Type::Macro(_) => {
216 self.seen_types.push(ty);
217 quote! { _reflect::DataShape::Leaf(core::any::TypeId::of::<#m>() ) }
218 }
219 syn::Type::Ptr(_) => panic!("don't reflect over raw pointers"),
220 syn::Type::Never(_) => panic!("don't reflect over never"),
221 }
222 }
223
224 fn variant_data(&mut self, fields: &'a syn::Fields) -> TokenStream {
230 let fields_ident = format_ident!("{}_FIELDS", self.parent());
231
232 match fields {
233 Fields::Named(n) => {
234 let field_labels = n
235 .named
236 .iter()
237 .map(|f| f.ident.as_ref().expect("should be named").to_string());
238
239 let fields = n
240 .named
241 .iter()
242 .enumerate()
243 .map(|(ix, f)| self.field(ix + 1, f))
244 .collect::<Vec<_>>();
245 let field_labels_ident = format_ident!("{}_LABELS", fields_ident);
246
247 self.consts.push(
248 quote! { const #fields_ident : &'static [&'static str] = &[#(#fields),*]; },
249 );
250 let fields = self.list_reference(fields_ident, fields);
251 quote! { _reflect::VariantData::Fields {
252 labels_for_serde: { const #field_labels_ident : &'static [&'static str] = &[#(#field_labels),*]; #field_labels_ident },
253 fields: #fields
254 } }
255 }
256 Fields::Unnamed(n) => {
257 let fields = n
258 .unnamed
259 .iter()
260 .enumerate()
261 .map(|(ix, f)| self.field(ix, f))
262 .collect::<Vec<_>>();
263 self.consts.push(quote!{ const #fields_ident : &'static [_reflect::Field<'static>] = &[#(#fields),*]; } );
264
265 let fields = self.list_reference(fields_ident, fields);
266 quote! { _reflect::VariantData::Tuple(#fields) }
267 }
268 Fields::Unit => {
269 quote! { _reflect::VariantData::Unit }
270 }
271 }
272 }
273
274 fn parented<T>(&mut self, new_parent: Ident, f: impl FnOnce(&mut Self) -> T) -> T {
275 self.parent_stack.push(new_parent);
276 let r = f(self);
277 self.parent_stack.pop();
278 r
279 }
280
281 fn variant(&mut self, ix: usize, v: &'a syn::Variant) -> TokenStream {
286 let attrs = self.parented(format_ident!("V{}", ix), |me| me.attrs(&v.attrs));
287
288 let vdata = self.parented(format_ident!("{}", v.ident), |me| {
289 me.variant_data(&v.fields)
290 });
291 let label = v.ident.to_string();
292 let attrs_name = format_ident!("{}_{}_ATTRS", self.parent(), label);
293
294 self.consts.push(
295 quote! { const #attrs_name : &'static [_reflect::Attr<'static>] = &[#(#attrs),*]; },
296 );
297
298 let attrs = self.list_reference(attrs_name, attrs);
299
300 let (new_disc_base, disc_val) = match &v.discriminant {
301 Some((_eq_token, val)) => (Some((ix, val.to_token_stream())), val.to_token_stream()),
302 None => (
303 self.most_recent_discriminant_expr.clone(),
304 match &self.most_recent_discriminant_expr {
305 Some((disc_setter_ix, prev_disc)) => {
306 quote! { #prev_disc + #(#ix - #disc_setter_ix) }
307 }
308 None => quote! { #ix },
309 },
310 ),
311 };
312 self.most_recent_discriminant_expr = new_disc_base;
313
314 quote! {
315 _reflect::EnumArm {
316 label: #label,
317 variant_index: #ix,
318 discriminant: #disc_val,
319 attrs: #attrs,
320 variant: #vdata,
321 }
322 }
323 }
324
325 fn data_shape(&mut self, d: &'a syn::DeriveInput) -> TokenStream {
326 match &d.data {
327 Data::Struct(DataStruct { fields, .. }) => {
328 let vdata = self.parented(d.ident.clone(), |me| me.variant_data(fields));
329 quote! { _reflect::DataShape::Struct(#vdata) }
330 }
331 Data::Enum(DataEnum { variants, .. }) => {
332 let (labels, variants): (Vec<_>, Vec<_>) = variants
334 .iter()
335 .enumerate()
336 .map(|(ix, v)| {
337 let arm = self.parented(d.ident.clone(), |me| me.variant(ix, v));
338 (v.ident.to_string(), arm)
339 })
340 .unzip();
341 let variants_ident = format_ident!("{}_VARIANTS", d.ident);
342 let field_labels_ident = format_ident!("{}_LABELS", variants_ident);
343 self.consts.push(
344 quote! { { const #field_labels_ident : &'static [&'static str] = &[#(#labels),*]; #field_labels_ident } },
345 );
346 self.consts.push(
347 quote! { const #variants_ident : &'static [_reflect::EnumArm<'static>] = &[#(#variants),*]},
348 );
349 let variants = self.list_reference(variants_ident, variants);
350
351 quote! { _reflect::DataShape::Enum{
352 variant_labels_for_serde: #field_labels_ident,
353 variants: #variants,
354 } }
355 }
356 Data::Union(_) => panic!("unions can not be reflected into"),
357 }
358 }
359}
360
361#[proc_macro_derive(BrokenReflect)]
362pub fn derive_reflect(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
363 let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
364 let mut derive = DeriveReflect {
365 consts: vec![],
366 nesting: None,
367 parent_stack: vec![],
368 most_recent_discriminant_expr: None,
369 nightly_const: false,
370 generics: &ast.generics,
371 seen_types: vec![],
372 };
373
374 let attrs = derive.parented(ast.ident.clone(), |me| me.attrs(&ast.attrs));
375 let shape = derive.data_shape(&ast);
376
377 let leafs = vec![quote! {drop("oh well");}];
378
379 let attr_name = format_ident!("{}_ATTRS", ast.ident);
384 derive
385 .consts
386 .push(quote! { const #attr_name : &'static [_reflect::Attr<'static>] = &[#(#attrs),*]; });
387
388 let generics = &ast.generics;
391
392 let me = &ast.ident;
393
394 let consts = if derive.nightly_const {
395 derive.consts
396 } else {
397 Vec::new()
398 };
399
400 let impl_block = quote! {
401 const _ : () = {
402 extern crate op_reflect as _reflect;
403 extern crate core;
404 extern crate memoffset;
405 extern crate alloc;
406
407 #(#consts)*
408
409 impl #generics _reflect::Reflect for #me #generics where Self: 'static {
410 fn rust_type() -> _reflect::StaticType {
411 alloc::borrow::Cow::Owned(_reflect::ReflectedType {
412 id: core::any::TypeId::of::<Self>(),
413 name: stringify!(#me),
414 layout: core::alloc::Layout::new::<Self>(),
415 shape: #shape,
416 attrs: alloc::borrow::Cow::Owned(vec![#(#attrs),*]),
417 })
418 }
419 fn register(db: &mut _reflect::Db<'_,'_>) {
420 db.register_type::<Self>();
421 #(#leafs);*
422 }
423 }
424 };
425 };
426
427 impl_block.into()
428}