1use std::collections::BTreeSet;
2
3use proc_macro::TokenStream;
4use quote::{quote, quote_spanned};
5use syn::{
6 Attribute, Data, DeriveInput, Error, GenericParam, Generics, Ident, LitStr, Type, parse::Parse,
7 parse_macro_input, parse_quote, parse_quote_spanned, spanned::Spanned, token::Comma,
8};
9
10use self::contains_generics::{GContext, type_contains_generics};
11
12mod contains_generics;
13
14fn bounds_g(generics: &Generics) -> BTreeSet<Ident> {
15 generics
16 .params
17 .iter()
18 .filter_map(|param| match param {
19 GenericParam::Lifetime(_) => None,
20 GenericParam::Type(param) => Some(¶m.ident),
21 GenericParam::Const(param) => Some(¶m.ident),
22 })
23 .cloned()
24 .collect()
25}
26
27#[proc_macro_derive(ToOutput)]
28pub fn derive_to_output(input: TokenStream) -> TokenStream {
29 let input = parse_macro_input!(input as DeriveInput);
30 let name = input.ident;
31 let generics = match bounds_to_output(input.generics, &input.data) {
32 Ok(g) => g,
33 Err(e) => return e.into_compile_error().into(),
34 };
35 let to_output = gen_to_output(&input.data);
36 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
37 let output = quote! {
38 #[automatically_derived]
39 impl #impl_generics ::object_rainbow::ToOutput for #name #ty_generics #where_clause {
40 fn to_output(&self, output: &mut dyn ::object_rainbow::Output) {
41 #to_output
42 }
43 }
44 };
45 TokenStream::from(output)
46}
47
48fn bounds_to_output(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
49 let g = &bounds_g(&generics);
50 match data {
51 Data::Struct(data) => {
52 for f in data.fields.iter() {
53 let ty = &f.ty;
54 if type_contains_generics(GContext { g, points: false }, ty) {
55 generics.make_where_clause().predicates.push(
56 parse_quote_spanned! { ty.span() =>
57 #ty: ::object_rainbow::ToOutput
58 },
59 );
60 }
61 }
62 }
63 Data::Enum(data) => {
64 for v in data.variants.iter() {
65 for f in v.fields.iter() {
66 let ty = &f.ty;
67 if type_contains_generics(GContext { g, points: false }, ty) {
68 generics.make_where_clause().predicates.push(
69 parse_quote_spanned! { ty.span() =>
70 #ty: ::object_rainbow::ToOutput
71 },
72 );
73 }
74 }
75 }
76 }
77 Data::Union(data) => {
78 return Err(Error::new_spanned(
79 data.union_token,
80 "`union`s are not supported",
81 ));
82 }
83 }
84 Ok(generics)
85}
86
87fn fields_to_output(fields: &syn::Fields) -> proc_macro2::TokenStream {
88 match fields {
89 syn::Fields::Named(fields) => {
90 let let_self = fields.named.iter().map(|f| f.ident.as_ref().unwrap());
91 let to_output = let_self.clone().zip(fields.named.iter()).map(|(i, f)| {
92 quote_spanned! { f.ty.span() =>
93 #i.to_output(output)
94 }
95 });
96 quote! {
97 { #(#let_self),* } => {
98 #(#to_output);*
99 }
100 }
101 }
102 syn::Fields::Unnamed(fields) => {
103 let let_self = fields
104 .unnamed
105 .iter()
106 .enumerate()
107 .map(|(i, f)| Ident::new(&format!("field{i}"), f.ty.span()));
108 let to_output = let_self.clone().zip(fields.unnamed.iter()).map(|(i, f)| {
109 quote_spanned! { f.ty.span() =>
110 #i.to_output(output)
111 }
112 });
113 quote! {
114 (#(#let_self),*) => {
115 #(#to_output);*
116 }
117 }
118 }
119 syn::Fields::Unit => quote! {
120 => {}
121 },
122 }
123}
124
125fn gen_to_output(data: &Data) -> proc_macro2::TokenStream {
126 match data {
127 Data::Struct(data) => {
128 let arm = fields_to_output(&data.fields);
129 quote! {
130 match self {
131 Self #arm
132 }
133 }
134 }
135 Data::Enum(data) => {
136 let to_output = data.variants.iter().map(|v| {
137 let ident = &v.ident;
138 let arm = fields_to_output(&v.fields);
139 quote! { Self::#ident #arm }
140 });
141 quote! {
142 let kind = ::object_rainbow::Enum::kind(self);
143 let tag = ::object_rainbow::enumkind::EnumKind::to_tag(kind);
144 tag.to_output(output);
145 match self {
146 #(#to_output)*
147 }
148 }
149 }
150 Data::Union(data) => {
151 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
152 }
153 }
154}
155
156#[proc_macro_derive(Topological)]
157pub fn derive_topological(input: TokenStream) -> TokenStream {
158 let input = parse_macro_input!(input as DeriveInput);
159 let name = input.ident;
160 let generics = input.generics.clone();
161 let (_, ty_generics, _) = generics.split_for_impl();
162 let generics = match bounds_topological(input.generics, &input.data) {
163 Ok(g) => g,
164 Err(e) => return e.into_compile_error().into(),
165 };
166 let accept_points = gen_accept_points(&input.data);
167 let (impl_generics, _, where_clause) = generics.split_for_impl();
168 let output = quote! {
169 #[automatically_derived]
170 impl #impl_generics ::object_rainbow::Topological<__E> for #name #ty_generics #where_clause {
171 fn accept_points(&self, visitor: &mut impl ::object_rainbow::PointVisitor<__E>) {
172 #accept_points
173 }
174 }
175 };
176 TokenStream::from(output)
177}
178
179fn bounds_topological(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
180 let g = &bounds_g(&generics);
181 match data {
182 Data::Struct(data) => {
183 for f in data.fields.iter() {
184 let ty = &f.ty;
185 if type_contains_generics(GContext { g, points: true }, ty) {
186 generics.make_where_clause().predicates.push(
187 parse_quote_spanned! { ty.span() =>
188 #ty: ::object_rainbow::Topological<__E>
189 },
190 );
191 }
192 }
193 }
194 Data::Enum(data) => {
195 for v in data.variants.iter() {
196 for f in v.fields.iter() {
197 let ty = &f.ty;
198 if type_contains_generics(GContext { g, points: true }, ty) {
199 generics.make_where_clause().predicates.push(
200 parse_quote_spanned! { ty.span() =>
201 #ty: ::object_rainbow::Topological<__E>
202 },
203 );
204 }
205 }
206 }
207 }
208 Data::Union(data) => {
209 return Err(Error::new_spanned(
210 data.union_token,
211 "`union`s are not supported",
212 ));
213 }
214 }
215 generics.params.push(parse_quote!(__E: 'static));
216 Ok(generics)
217}
218
219fn fields_accept_points(fields: &syn::Fields) -> proc_macro2::TokenStream {
220 match fields {
221 syn::Fields::Named(fields) => {
222 let let_self = fields.named.iter().map(|f| f.ident.as_ref().unwrap());
223 let accept_points = let_self.clone().zip(fields.named.iter()).map(|(i, f)| {
224 quote_spanned! { f.ty.span() =>
225 #i.accept_points(visitor)
226 }
227 });
228 quote! {
229 { #(#let_self),* } => {
230 #(#accept_points);*
231 }
232 }
233 }
234 syn::Fields::Unnamed(fields) => {
235 let let_self = fields
236 .unnamed
237 .iter()
238 .enumerate()
239 .map(|(i, f)| Ident::new(&format!("field{i}"), f.ty.span()));
240 let accept_points = let_self.clone().zip(fields.unnamed.iter()).map(|(i, f)| {
241 quote_spanned! { f.ty.span() =>
242 #i.accept_points(visitor)
243 }
244 });
245 quote! {
246 (#(#let_self),*) => {
247 #(#accept_points);*
248 }
249 }
250 }
251 syn::Fields::Unit => quote! {
252 => {}
253 },
254 }
255}
256
257fn gen_accept_points(data: &Data) -> proc_macro2::TokenStream {
258 match data {
259 Data::Struct(data) => {
260 let arm = fields_accept_points(&data.fields);
261 quote! {
262 match self {
263 Self #arm
264 }
265 }
266 }
267 Data::Enum(data) => {
268 let to_output = data.variants.iter().map(|v| {
269 let ident = &v.ident;
270 let arm = fields_accept_points(&v.fields);
271 quote! { Self::#ident #arm }
272 });
273 quote! {
274 let kind = ::object_rainbow::Enum::kind(self);
275 let tag = ::object_rainbow::enumkind::EnumKind::to_tag(kind);
276 tag.accept_points(visitor);
277 match self {
278 #(#to_output)*
279 }
280 }
281 }
282 Data::Union(data) => {
283 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
284 }
285 }
286}
287
288#[proc_macro_derive(Tagged, attributes(tags))]
289pub fn derive_tagged(input: TokenStream) -> TokenStream {
290 let input = parse_macro_input!(input as DeriveInput);
291 let name = input.ident;
292 let mut errors = Vec::new();
293 let generics = match bounds_tagged(input.generics, &input.data, &mut errors) {
294 Ok(g) => g,
295 Err(e) => return e.into_compile_error().into(),
296 };
297 let tags = gen_tags(&input.data, &input.attrs, &mut errors);
298 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
299 let errors = errors.into_iter().map(|e| e.into_compile_error());
300 let output = quote! {
301 #(#errors)*
302
303 #[automatically_derived]
304 impl #impl_generics ::object_rainbow::Tagged for #name #ty_generics #where_clause {
305 const TAGS: ::object_rainbow::Tags = #tags;
306 }
307 };
308 TokenStream::from(output)
309}
310
311struct FieldTagArgs {
312 skip: bool,
313}
314
315impl Parse for FieldTagArgs {
316 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
317 let mut skip = false;
318 while !input.is_empty() {
319 let ident = input.parse::<Ident>()?;
320 if ident.to_string().as_str() != "skip" {
321 return Err(Error::new(ident.span(), "expected: skip"));
322 }
323 skip = true;
324 if !input.is_empty() {
325 input.parse::<Comma>()?;
326 }
327 }
328 Ok(Self { skip })
329 }
330}
331
332fn bounds_tagged(
333 mut generics: Generics,
334 data: &Data,
335 errors: &mut Vec<Error>,
336) -> syn::Result<Generics> {
337 let g = &bounds_g(&generics);
338 match data {
339 Data::Struct(data) => {
340 for f in data.fields.iter() {
341 let mut skip = false;
342 for attr in &f.attrs {
343 if attr_str(attr).as_deref() == Some("tags") {
344 match attr.parse_args::<FieldTagArgs>() {
345 Ok(args) => skip |= args.skip,
346 Err(e) => errors.push(e),
347 }
348 }
349 }
350 if !skip {
351 let ty = &f.ty;
352 if type_contains_generics(GContext { g, points: false }, ty) {
353 generics.make_where_clause().predicates.push(
354 parse_quote_spanned! { ty.span() =>
355 #ty: ::object_rainbow::Tagged
356 },
357 );
358 }
359 }
360 }
361 }
362 Data::Enum(data) => {
363 for v in data.variants.iter() {
364 for f in v.fields.iter() {
365 let mut skip = false;
366 for attr in &f.attrs {
367 if attr_str(attr).as_deref() == Some("tags") {
368 match attr.parse_args::<FieldTagArgs>() {
369 Ok(args) => skip |= args.skip,
370 Err(e) => errors.push(e),
371 }
372 }
373 }
374 if !skip {
375 let ty = &f.ty;
376 if type_contains_generics(GContext { g, points: false }, ty) {
377 generics.make_where_clause().predicates.push(
378 parse_quote_spanned! { ty.span() =>
379 #ty: ::object_rainbow::Tagged
380 },
381 );
382 }
383 }
384 }
385 }
386 }
387 Data::Union(data) => {
388 return Err(Error::new_spanned(
389 data.union_token,
390 "`union`s are not supported",
391 ));
392 }
393 }
394 Ok(generics)
395}
396
397struct StructTagArgs {
398 tags: Vec<LitStr>,
399}
400
401impl Parse for StructTagArgs {
402 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
403 let mut tags = Vec::new();
404 while !input.is_empty() {
405 let tag = input.parse::<LitStr>()?;
406 tags.push(tag);
407 if !input.is_empty() {
408 input.parse::<Comma>()?;
409 }
410 }
411 Ok(Self { tags })
412 }
413}
414
415fn fields_tags(fields: &syn::Fields) -> Vec<proc_macro2::TokenStream> {
416 fields
417 .iter()
418 .filter_map(|f| {
419 let mut skip = false;
420 for attr in &f.attrs {
421 if attr_str(attr).as_deref() == Some("tags") {
422 skip |= attr.parse_args::<FieldTagArgs>().ok()?.skip;
423 }
424 }
425 let ty = &f.ty;
426 (!skip).then_some(quote! { <#ty as ::object_rainbow::Tagged>::TAGS })
427 })
428 .collect()
429}
430
431fn gen_tags(data: &Data, attrs: &[Attribute], errors: &mut Vec<Error>) -> proc_macro2::TokenStream {
432 match data {
433 Data::Struct(data) => {
434 let mut tags = Vec::new();
435 for attr in attrs {
436 if attr_str(attr).as_deref() == Some("tags") {
437 match attr.parse_args::<StructTagArgs>() {
438 Ok(mut args) => tags.append(&mut args.tags),
439 Err(e) => errors.push(e),
440 }
441 }
442 }
443 let nested = fields_tags(&data.fields);
444 if nested.len() == 1 && tags.is_empty() {
445 let nested = nested.into_iter().next().unwrap();
446 quote! {
447 #nested
448 }
449 } else {
450 quote! {
451 ::object_rainbow::Tags(&[#(#tags),*], &[#(&#nested),*])
452 }
453 }
454 }
455 Data::Enum(data) => {
456 let mut tags = Vec::new();
457 for attr in attrs {
458 if attr_str(attr).as_deref() == Some("tags") {
459 match attr.parse_args::<StructTagArgs>() {
460 Ok(mut args) => tags.append(&mut args.tags),
461 Err(e) => errors.push(e),
462 }
463 }
464 }
465 let mut nested: Vec<_> = data
466 .variants
467 .iter()
468 .flat_map(|v| fields_tags(&v.fields))
469 .collect();
470 let kind_tags = quote! {
471 <
472 <
473 <
474 Self
475 as
476 ::object_rainbow::Enum
477 >::Kind
478 as
479 ::object_rainbow::enumkind::EnumKind
480 >::Tag
481 as ::object_rainbow::Tagged
482 >::TAGS
483 };
484 nested.insert(0, kind_tags);
485 if nested.len() == 1 && tags.is_empty() {
486 let nested = nested.into_iter().next().unwrap();
487 quote! {
488 #nested
489 }
490 } else {
491 quote! {
492 ::object_rainbow::Tags(&[#(#tags),*], &[#(&#nested),*])
493 }
494 }
495 }
496 Data::Union(data) => {
497 Error::new_spanned(data.union_token, "`union`s are not supported").into_compile_error()
498 }
499 }
500}
501
502#[proc_macro_derive(Object)]
503pub fn derive_object(input: TokenStream) -> TokenStream {
504 let input = parse_macro_input!(input as DeriveInput);
505 let name = input.ident;
506 let generics = input.generics.clone();
507 let (_, ty_generics, _) = generics.split_for_impl();
508 let generics = match bounds_object(input.generics, &input.data) {
509 Ok(g) => g,
510 Err(e) => return e.into_compile_error().into(),
511 };
512 let (impl_generics, _, where_clause) = generics.split_for_impl();
513 let output = quote! {
514 #[automatically_derived]
515 impl #impl_generics ::object_rainbow::Object<__E> for #name #ty_generics #where_clause {}
516 };
517 TokenStream::from(output)
518}
519
520fn bounds_object(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
521 let g = &bounds_g(&generics);
522 match data {
523 Data::Struct(data) => {
524 let last_at = data.fields.len().checked_sub(1).unwrap_or_default();
525 for (i, f) in data.fields.iter().enumerate() {
526 let last = i == last_at;
527 let ty = &f.ty;
528 let tr = if last {
529 quote!(::object_rainbow::Object<__E>)
530 } else {
531 quote!(::object_rainbow::Inline<__E>)
532 };
533 if type_contains_generics(GContext { g, points: true }, ty) {
534 generics.make_where_clause().predicates.push(
535 parse_quote_spanned! { ty.span() =>
536 #ty: #tr
537 },
538 );
539 }
540 }
541 }
542 Data::Enum(data) => {
543 for v in data.variants.iter() {
544 let last_at = v.fields.len().checked_sub(1).unwrap_or_default();
545 for (i, f) in v.fields.iter().enumerate() {
546 let last = i == last_at;
547 let ty = &f.ty;
548 let tr = if last {
549 quote!(::object_rainbow::Object<__E>)
550 } else {
551 quote!(::object_rainbow::Inline<__E>)
552 };
553 if type_contains_generics(GContext { g, points: true }, ty) {
554 generics.make_where_clause().predicates.push(
555 parse_quote_spanned! { ty.span() =>
556 #ty: #tr
557 },
558 );
559 }
560 }
561 }
562 }
563 Data::Union(data) => {
564 return Err(Error::new_spanned(
565 data.union_token,
566 "`union`s are not supported",
567 ));
568 }
569 }
570 generics.params.push(parse_quote!(__E: 'static));
571 Ok(generics)
572}
573
574#[proc_macro_derive(Inline)]
575pub fn derive_inline(input: TokenStream) -> TokenStream {
576 let input = parse_macro_input!(input as DeriveInput);
577 let name = input.ident;
578 let generics = input.generics.clone();
579 let (_, ty_generics, _) = generics.split_for_impl();
580 let generics = match bounds_inline(input.generics, &input.data) {
581 Ok(g) => g,
582 Err(e) => return e.into_compile_error().into(),
583 };
584 let (impl_generics, _, where_clause) = generics.split_for_impl();
585 let output = quote! {
586 #[automatically_derived]
587 impl #impl_generics ::object_rainbow::Inline<__E> for #name #ty_generics #where_clause {}
588 };
589 TokenStream::from(output)
590}
591
592fn bounds_inline(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
593 let g = &bounds_g(&generics);
594 match data {
595 Data::Struct(data) => {
596 for f in data.fields.iter() {
597 let ty = &f.ty;
598 if type_contains_generics(GContext { g, points: true }, ty) {
599 generics.make_where_clause().predicates.push(
600 parse_quote_spanned! { ty.span() =>
601 #ty: ::object_rainbow::Inline<__E>
602 },
603 );
604 }
605 }
606 }
607 Data::Enum(data) => {
608 for v in data.variants.iter() {
609 for f in v.fields.iter() {
610 let ty = &f.ty;
611 if type_contains_generics(GContext { g, points: true }, ty) {
612 generics.make_where_clause().predicates.push(
613 parse_quote_spanned! { ty.span() =>
614 #ty: ::object_rainbow::Inline<__E>
615 },
616 );
617 }
618 }
619 }
620 }
621 Data::Union(data) => {
622 return Err(Error::new_spanned(
623 data.union_token,
624 "`union`s are not supported",
625 ));
626 }
627 }
628 generics.params.push(parse_quote!(__E: 'static));
629 Ok(generics)
630}
631
632#[proc_macro_derive(ReflessObject)]
633pub fn derive_refless_object(input: TokenStream) -> TokenStream {
634 let input = parse_macro_input!(input as DeriveInput);
635 let name = input.ident;
636 let generics = match bounds_refless_object(input.generics, &input.data) {
637 Ok(g) => g,
638 Err(e) => return e.into_compile_error().into(),
639 };
640 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
641 let output = quote! {
642 #[automatically_derived]
643 impl #impl_generics ::object_rainbow::ReflessObject for #name #ty_generics #where_clause {}
644 };
645 TokenStream::from(output)
646}
647
648fn bounds_refless_object(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
649 let g = &bounds_g(&generics);
650 match data {
651 Data::Struct(data) => {
652 let last_at = data.fields.len().checked_sub(1).unwrap_or_default();
653 for (i, f) in data.fields.iter().enumerate() {
654 let last = i == last_at;
655 let ty = &f.ty;
656 let tr = if last {
657 quote!(::object_rainbow::ReflessObject)
658 } else {
659 quote!(::object_rainbow::ReflessInline)
660 };
661 if type_contains_generics(GContext { g, points: false }, ty) {
662 generics.make_where_clause().predicates.push(
663 parse_quote_spanned! { ty.span() =>
664 #ty: #tr
665 },
666 );
667 }
668 }
669 }
670 Data::Enum(data) => {
671 for v in data.variants.iter() {
672 let last_at = v.fields.len().checked_sub(1).unwrap_or_default();
673 for (i, f) in v.fields.iter().enumerate() {
674 let last = i == last_at;
675 let ty = &f.ty;
676 let tr = if last {
677 quote!(::object_rainbow::ReflessObject)
678 } else {
679 quote!(::object_rainbow::ReflessInline)
680 };
681 if type_contains_generics(GContext { g, points: false }, ty) {
682 generics.make_where_clause().predicates.push(
683 parse_quote_spanned! { ty.span() =>
684 #ty: #tr
685 },
686 );
687 }
688 }
689 }
690 }
691 Data::Union(data) => {
692 return Err(Error::new_spanned(
693 data.union_token,
694 "`union`s are not supported",
695 ));
696 }
697 }
698 Ok(generics)
699}
700
701#[proc_macro_derive(ReflessInline)]
702pub fn derive_refless_inline(input: TokenStream) -> TokenStream {
703 let input = parse_macro_input!(input as DeriveInput);
704 let name = input.ident;
705 let generics = match bounds_refless_inline(input.generics, &input.data) {
706 Ok(g) => g,
707 Err(e) => return e.into_compile_error().into(),
708 };
709 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
710 let output = quote! {
711 #[automatically_derived]
712 impl #impl_generics ::object_rainbow::ReflessInline for #name #ty_generics #where_clause {}
713 };
714 TokenStream::from(output)
715}
716
717fn bounds_refless_inline(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
718 let g = &bounds_g(&generics);
719 match data {
720 Data::Struct(data) => {
721 for f in data.fields.iter() {
722 let ty = &f.ty;
723 if type_contains_generics(GContext { g, points: false }, ty) {
724 generics.make_where_clause().predicates.push(
725 parse_quote_spanned! { ty.span() =>
726 #ty: ::object_rainbow::ReflessInline
727 },
728 );
729 }
730 }
731 }
732 Data::Enum(data) => {
733 for v in data.variants.iter() {
734 for f in v.fields.iter() {
735 let ty = &f.ty;
736 if type_contains_generics(GContext { g, points: false }, ty) {
737 generics.make_where_clause().predicates.push(
738 parse_quote_spanned! { ty.span() =>
739 #ty: ::object_rainbow::ReflessInline
740 },
741 );
742 }
743 }
744 }
745 }
746 Data::Union(data) => {
747 return Err(Error::new_spanned(
748 data.union_token,
749 "`union`s are not supported",
750 ));
751 }
752 }
753 Ok(generics)
754}
755
756#[proc_macro_derive(Size)]
757pub fn derive_size(input: TokenStream) -> TokenStream {
758 let input = parse_macro_input!(input as DeriveInput);
759 let name = input.ident;
760 let size_arr = gen_size_arr(&input.data);
761 let size = gen_size(&input.data);
762 let generics = match bounds_size(input.generics.clone(), &input.data, &size_arr) {
763 Ok(g) => g,
764 Err(e) => return e.into_compile_error().into(),
765 };
766 let (_, ty_generics, where_clause) = generics.split_for_impl();
767 let mut generics = input.generics;
768 generics.params.push(parse_quote!(
769 __Output: ::object_rainbow::typenum::Unsigned
770 ));
771 let (impl_generics, _, _) = generics.split_for_impl();
772 let output = quote! {
773 const _: () = {
774 use ::object_rainbow::typenum::tarr;
775
776 #[automatically_derived]
777 impl #impl_generics ::object_rainbow::Size for #name #ty_generics #where_clause {
778 const SIZE: usize = #size;
779
780 type Size = <#size_arr as ::object_rainbow::typenum::FoldAdd>::Output;
781 }
782 };
783 };
784 TokenStream::from(output)
785}
786
787fn bounds_size(
788 mut generics: Generics,
789 data: &Data,
790 size_arr: &proc_macro2::TokenStream,
791) -> syn::Result<Generics> {
792 let g = &bounds_g(&generics);
793 match data {
794 Data::Struct(data) => {
795 for f in data.fields.iter() {
796 let ty = &f.ty;
797 if type_contains_generics(GContext { g, points: false }, ty) {
798 generics.make_where_clause().predicates.push(
799 parse_quote_spanned! { ty.span() =>
800 #ty: ::object_rainbow::Size
801 },
802 );
803 }
804 }
805 }
806 Data::Enum(data) => {
807 for v in data.variants.iter() {
808 for f in v.fields.iter() {
809 let ty = &f.ty;
810 if type_contains_generics(GContext { g, points: false }, ty) {
811 generics.make_where_clause().predicates.push(
812 parse_quote_spanned! { ty.span() =>
813 #ty: ::object_rainbow::Size
814 },
815 );
816 }
817 }
818 }
819 for v in data.variants.iter().skip(1) {
820 let arr = fields_size_arr(&v.fields, true);
821 generics.make_where_clause().predicates.push(parse_quote!(
822 #arr: ::object_rainbow::typenum::FoldAdd<Output = __Output>
823 ));
824 }
825 }
826 Data::Union(data) => {
827 return Err(Error::new_spanned(
828 data.union_token,
829 "`union`s are not supported",
830 ));
831 }
832 }
833 generics.make_where_clause().predicates.push(parse_quote!(
834 #size_arr: ::object_rainbow::typenum::FoldAdd<Output = __Output>
835 ));
836 Ok(generics)
837}
838
839fn fields_size_arr(fields: &syn::Fields, as_enum: bool) -> proc_macro2::TokenStream {
840 let kind_size = quote! {
841 <
842 <
843 <
844 Self
845 as
846 ::object_rainbow::Enum
847 >::Kind
848 as
849 ::object_rainbow::enumkind::EnumKind
850 >::Tag
851 as ::object_rainbow::Size
852 >::Size
853 };
854 if fields.is_empty() {
855 return if as_enum {
856 quote! { tarr![#kind_size, ::object_rainbow::typenum::consts::U0] }
857 } else {
858 quote! { tarr![::object_rainbow::typenum::consts::U0] }
859 };
860 }
861 let size_arr = fields.iter().map(|f| {
862 let ty = &f.ty;
863 quote! { <#ty as ::object_rainbow::Size>::Size }
864 });
865 if as_enum {
866 quote! { tarr![#kind_size, #(#size_arr),*] }
867 } else {
868 quote! { tarr![#(#size_arr),*] }
869 }
870}
871
872fn gen_size_arr(data: &Data) -> proc_macro2::TokenStream {
873 match data {
874 Data::Struct(data) => fields_size_arr(&data.fields, false),
875 Data::Enum(data) => {
876 if let Some(v) = data.variants.first() {
877 fields_size_arr(&v.fields, true)
878 } else {
879 Error::new_spanned(data.enum_token, "empty `enum`s are not supported")
880 .into_compile_error()
881 }
882 }
883 Data::Union(data) => {
884 Error::new_spanned(data.union_token, "`union`s are not supported").into_compile_error()
885 }
886 }
887}
888
889fn fields_size(fields: &syn::Fields) -> proc_macro2::TokenStream {
890 if fields.is_empty() {
891 return quote! {0};
892 }
893 let size = fields.iter().map(|f| {
894 let ty = &f.ty;
895 quote! { <#ty as ::object_rainbow::Size>::SIZE }
896 });
897 quote! {
898 #(#size)+*
899 }
900}
901
902fn gen_size(data: &Data) -> proc_macro2::TokenStream {
903 match data {
904 Data::Struct(data) => fields_size(&data.fields),
905 Data::Enum(data) => {
906 if let Some(v) = data.variants.first() {
907 let size = fields_size(&v.fields);
908 let kind_size = quote! {
909 <
910 <
911 <
912 Self
913 as
914 ::object_rainbow::Enum
915 >::Kind
916 as
917 ::object_rainbow::enumkind::EnumKind
918 >::Tag
919 as ::object_rainbow::Size
920 >::SIZE
921 };
922 quote! { #kind_size + #size }
923 } else {
924 Error::new_spanned(data.enum_token, "empty `enum`s are not supported")
925 .into_compile_error()
926 }
927 }
928 Data::Union(data) => {
929 Error::new_spanned(data.union_token, "`union`s are not supported").into_compile_error()
930 }
931 }
932}
933
934#[proc_macro_derive(Parse)]
935pub fn derive_parse(input: TokenStream) -> TokenStream {
936 let input = parse_macro_input!(input as DeriveInput);
937 let name = input.ident;
938 let generics = input.generics.clone();
939 let (_, ty_generics, _) = generics.split_for_impl();
940 let generics = match bounds_parse(input.generics, &input.data) {
941 Ok(g) => g,
942 Err(e) => return e.into_compile_error().into(),
943 };
944 let parse = gen_parse(&input.data);
945 let (impl_generics, _, where_clause) = generics.split_for_impl();
946 let output = quote! {
947 #[automatically_derived]
948 impl #impl_generics ::object_rainbow::Parse<__I> for #name #ty_generics #where_clause {
949 fn parse(mut input: __I) -> ::object_rainbow::Result<Self> {
950 #parse
951 }
952 }
953 };
954 TokenStream::from(output)
955}
956
957fn bounds_parse(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
958 match data {
959 Data::Struct(data) => {
960 let last_at = data.fields.len().checked_sub(1).unwrap_or_default();
961 for (i, f) in data.fields.iter().enumerate() {
962 let last = i == last_at;
963 let ty = &f.ty;
964 let tr = if last {
965 quote!(::object_rainbow::Parse<__I>)
966 } else {
967 quote!(::object_rainbow::ParseInline<__I>)
968 };
969 generics
970 .make_where_clause()
971 .predicates
972 .push(parse_quote_spanned! { ty.span() =>
973 #ty: #tr
974 });
975 }
976 }
977 Data::Enum(data) => {
978 for v in data.variants.iter() {
979 let last_at = v.fields.len().checked_sub(1).unwrap_or_default();
980 for (i, f) in v.fields.iter().enumerate() {
981 let last = i == last_at;
982 let ty = &f.ty;
983 let tr = if last {
984 quote!(::object_rainbow::Parse<__I>)
985 } else {
986 quote!(::object_rainbow::ParseInline<__I>)
987 };
988 generics.make_where_clause().predicates.push(
989 parse_quote_spanned! { ty.span() =>
990 #ty: #tr
991 },
992 );
993 }
994 }
995 }
996 Data::Union(data) => {
997 return Err(Error::new_spanned(
998 data.union_token,
999 "`union`s are not supported",
1000 ));
1001 }
1002 }
1003 generics
1004 .params
1005 .push(parse_quote!(__I: ::object_rainbow::ParseInput));
1006 Ok(generics)
1007}
1008
1009fn gen_parse(data: &Data) -> proc_macro2::TokenStream {
1010 match data {
1011 Data::Struct(data) => {
1012 let arm = fields_parse(&data.fields);
1013 quote! { Ok(Self #arm)}
1014 }
1015 Data::Enum(data) => {
1016 let parse = data.variants.iter().map(|v| {
1017 let ident = &v.ident;
1018 let arm = fields_parse(&v.fields);
1019 quote! {
1020 <Self as ::object_rainbow::Enum>::Kind::#ident => Self::#ident #arm,
1021 }
1022 });
1023 quote! {
1024 Ok(match input.parse_inline()? {
1025 #(#parse)*
1026 })
1027 }
1028 }
1029 Data::Union(data) => {
1030 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1031 }
1032 }
1033}
1034
1035fn fields_parse(fields: &syn::Fields) -> proc_macro2::TokenStream {
1036 let last_at = fields.len().checked_sub(1).unwrap_or_default();
1037 match fields {
1038 syn::Fields::Named(fields) => {
1039 let parse = fields.named.iter().enumerate().map(|(i, f)| {
1040 let last = i == last_at;
1041 let i = f.ident.as_ref().unwrap();
1042 let method = if last {
1043 quote!(parse)
1044 } else {
1045 quote!(parse_inline)
1046 };
1047 quote_spanned! { f.ty.span() =>
1048 #i: input.#method()?
1049 }
1050 });
1051 quote! { { #(#parse),* } }
1052 }
1053 syn::Fields::Unnamed(fields) => {
1054 let parse = fields.unnamed.iter().enumerate().map(|(i, f)| {
1055 let last = i == last_at;
1056 let method = if last {
1057 quote!(parse)
1058 } else {
1059 quote!(parse_inline)
1060 };
1061 quote_spanned! { f.ty.span() =>
1062 input.#method()?
1063 }
1064 });
1065 quote! { (#(#parse),*) }
1066 }
1067 syn::Fields::Unit => quote! {},
1068 }
1069}
1070
1071#[proc_macro_derive(ParseInline)]
1072pub fn derive_parse_inline(input: TokenStream) -> TokenStream {
1073 let input = parse_macro_input!(input as DeriveInput);
1074 let name = input.ident;
1075 let generics = input.generics.clone();
1076 let (_, ty_generics, _) = generics.split_for_impl();
1077 let generics = match bounds_parse_inline(input.generics, &input.data) {
1078 Ok(g) => g,
1079 Err(e) => return e.into_compile_error().into(),
1080 };
1081 let parse_inline = gen_parse_inline(&input.data);
1082 let (impl_generics, _, where_clause) = generics.split_for_impl();
1083 let output = quote! {
1084 #[automatically_derived]
1085 impl #impl_generics ::object_rainbow::ParseInline<__I> for #name #ty_generics #where_clause {
1086 fn parse_inline(input: &mut __I) -> ::object_rainbow::Result<Self> {
1087 #parse_inline
1088 }
1089 }
1090 };
1091 TokenStream::from(output)
1092}
1093
1094fn bounds_parse_inline(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
1095 match data {
1096 Data::Struct(data) => {
1097 for f in data.fields.iter() {
1098 let ty = &f.ty;
1099 generics
1100 .make_where_clause()
1101 .predicates
1102 .push(parse_quote_spanned! { ty.span() =>
1103 #ty: ::object_rainbow::ParseInline<__I>
1104 });
1105 }
1106 }
1107 Data::Enum(data) => {
1108 for v in data.variants.iter() {
1109 for f in v.fields.iter() {
1110 let ty = &f.ty;
1111 generics.make_where_clause().predicates.push(
1112 parse_quote_spanned! { ty.span() =>
1113 #ty: ::object_rainbow::ParseInline<__I>
1114 },
1115 );
1116 }
1117 }
1118 }
1119 Data::Union(data) => {
1120 return Err(Error::new_spanned(
1121 data.union_token,
1122 "`union`s are not supported",
1123 ));
1124 }
1125 }
1126 generics
1127 .params
1128 .push(parse_quote!(__I: ::object_rainbow::ParseInput));
1129 Ok(generics)
1130}
1131
1132fn fields_parse_inline(fields: &syn::Fields) -> proc_macro2::TokenStream {
1133 match fields {
1134 syn::Fields::Named(fields) => {
1135 let parse = fields.named.iter().map(|f| {
1136 let i = f.ident.as_ref().unwrap();
1137 quote_spanned! { f.ty.span() =>
1138 #i: input.parse_inline()?
1139 }
1140 });
1141 quote! { { #(#parse),* } }
1142 }
1143 syn::Fields::Unnamed(fields) => {
1144 let parse = fields.unnamed.iter().map(|f| {
1145 quote_spanned! { f.ty.span() =>
1146 input.parse_inline()?
1147 }
1148 });
1149 quote! { (#(#parse),*) }
1150 }
1151 syn::Fields::Unit => quote! {},
1152 }
1153}
1154
1155fn gen_parse_inline(data: &Data) -> proc_macro2::TokenStream {
1156 match data {
1157 Data::Struct(data) => {
1158 let arm = fields_parse_inline(&data.fields);
1159 quote! { Ok(Self #arm) }
1160 }
1161 Data::Enum(data) => {
1162 let parse_inline = data.variants.iter().map(|v| {
1163 let ident = &v.ident;
1164 let arm = fields_parse_inline(&v.fields);
1165 quote! {
1166 <Self as ::object_rainbow::Enum>::Kind::#ident => Self::#ident #arm,
1167 }
1168 });
1169 quote! {
1170 Ok(match input.parse_inline()? {
1171 #(#parse_inline)*
1172 })
1173 }
1174 }
1175 Data::Union(data) => {
1176 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1177 }
1178 }
1179}
1180
1181#[proc_macro_derive(ParseAsInline)]
1182pub fn derive_parse_as_inline(input: TokenStream) -> TokenStream {
1183 let input = parse_macro_input!(input as DeriveInput);
1184 let name = input.ident;
1185 let generics = input.generics.clone();
1186 let (_, ty_generics, _) = generics.split_for_impl();
1187 let generics = match bounds_parse_as_inline(input.generics, &name) {
1188 Ok(g) => g,
1189 Err(e) => return e.into_compile_error().into(),
1190 };
1191 let (impl_generics, _, where_clause) = generics.split_for_impl();
1192 let output = quote! {
1193 #[automatically_derived]
1194 impl #impl_generics ::object_rainbow::Parse<__I> for #name #ty_generics #where_clause {
1195 fn parse(input: __I) -> ::object_rainbow::Result<Self> {
1196 ::object_rainbow::ParseInline::<__I>::parse_as_inline(input)
1197 }
1198 }
1199 };
1200 TokenStream::from(output)
1201}
1202
1203fn bounds_parse_as_inline(mut generics: Generics, name: &Ident) -> syn::Result<Generics> {
1204 generics
1205 .make_where_clause()
1206 .predicates
1207 .push(parse_quote_spanned! { name.span() =>
1208 Self: ::object_rainbow::ParseInline::<__I>
1209 });
1210 generics
1211 .params
1212 .push(parse_quote!(__I: ::object_rainbow::ParseInput));
1213 Ok(generics)
1214}
1215
1216fn parse_path(attr: &Attribute) -> syn::Result<Type> {
1217 attr.parse_args::<LitStr>()?.parse()
1218}
1219
1220fn attr_str(attr: &Attribute) -> Option<String> {
1221 Some(attr.path().get_ident()?.to_string())
1222}
1223
1224#[proc_macro_derive(Enum, attributes(enumtag))]
1225pub fn derive_enum(input: TokenStream) -> TokenStream {
1226 let input = parse_macro_input!(input as DeriveInput);
1227 let name = input.ident;
1228 let generics = input.generics.clone();
1229 let (_, ty_generics, _) = generics.split_for_impl();
1230 let generics = input.generics;
1231 let variants = gen_variants(&input.data);
1232 let variant_count = gen_variant_count(&input.data);
1233 let to_tag = gen_to_tag(&input.data);
1234 let from_tag = gen_from_tag(&input.data);
1235 let kind = gen_kind(&input.data);
1236 let (impl_generics, _, where_clause) = generics.split_for_impl();
1237 let mut errors = Vec::new();
1238 let mut enumtag = None;
1239 for attr in &input.attrs {
1240 if attr_str(attr).as_deref() == Some("enumtag") {
1241 match parse_path(attr) {
1242 Ok(path) => {
1243 if enumtag.is_some() {
1244 errors.push(Error::new_spanned(path, "duplicate tag"));
1245 } else {
1246 enumtag = Some(path);
1247 }
1248 }
1249 Err(e) => errors.push(e),
1250 }
1251 }
1252 }
1253 let enumtag = enumtag
1254 .unwrap_or_else(|| parse_quote!(::object_rainbow::numeric::Le<::core::num::NonZero<u8>>));
1255 let errors = errors.into_iter().map(|e| e.into_compile_error());
1256 let output = quote! {
1257 const _: () = {
1258 #(#errors)*
1259
1260 use ::object_rainbow::enumkind::EnumKind;
1261
1262 #[derive(Clone, Copy, ::object_rainbow::ParseAsInline)]
1263 pub enum __Kind {
1264 #variants
1265 }
1266
1267 #[automatically_derived]
1268 impl ::object_rainbow::enumkind::EnumKind for __Kind {
1269 type Tag = ::object_rainbow::enumkind::EnumTag<
1270 #enumtag,
1271 #variant_count,
1272 >;
1273
1274 fn to_tag(self) -> Self::Tag {
1275 #to_tag
1276 }
1277
1278 fn from_tag(tag: Self::Tag) -> Self {
1279 #from_tag
1280 }
1281 }
1282
1283 impl<I: ::object_rainbow::ParseInput> ::object_rainbow::ParseInline<I> for __Kind {
1284 fn parse_inline(input: &mut I) -> ::object_rainbow::Result<Self> {
1285 Ok(::object_rainbow::enumkind::EnumKind::from_tag(input.parse_inline()?))
1286 }
1287 }
1288
1289 #[automatically_derived]
1290 impl #impl_generics ::object_rainbow::Enum for #name #ty_generics #where_clause {
1291 type Kind = __Kind;
1292
1293 fn kind(&self) -> Self::Kind {
1294 #kind
1295 }
1296 }
1297 };
1298 };
1299 TokenStream::from(output)
1300}
1301
1302fn gen_variants(data: &Data) -> proc_macro2::TokenStream {
1303 match data {
1304 Data::Struct(data) => {
1305 Error::new_spanned(data.struct_token, "`struct`s are not supported").to_compile_error()
1306 }
1307 Data::Enum(data) => {
1308 let variants = data.variants.iter().map(|v| &v.ident);
1309 quote! { #(#variants),* }
1310 }
1311 Data::Union(data) => {
1312 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1313 }
1314 }
1315}
1316
1317fn gen_variant_count(data: &Data) -> proc_macro2::TokenStream {
1318 match data {
1319 Data::Struct(data) => {
1320 Error::new_spanned(data.struct_token, "`struct`s are not supported").to_compile_error()
1321 }
1322 Data::Enum(data) => {
1323 let variant_count = data.variants.len();
1324 quote! { #variant_count }
1325 }
1326 Data::Union(data) => {
1327 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1328 }
1329 }
1330}
1331
1332fn gen_to_tag(data: &Data) -> proc_macro2::TokenStream {
1333 match data {
1334 Data::Struct(data) => {
1335 Error::new_spanned(data.struct_token, "`struct`s are not supported").to_compile_error()
1336 }
1337 Data::Enum(data) => {
1338 let to_tag = data.variants.iter().enumerate().map(|(i, v)| {
1339 let ident = &v.ident;
1340 quote_spanned! { ident.span() =>
1341 Self::#ident => ::object_rainbow::enumkind::EnumTag::from_const::<#i>(),
1342 }
1343 });
1344 quote! {
1345 match self {
1346 #(#to_tag)*
1347 }
1348 }
1349 }
1350 Data::Union(data) => {
1351 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1352 }
1353 }
1354}
1355
1356fn gen_from_tag(data: &Data) -> proc_macro2::TokenStream {
1357 match data {
1358 Data::Struct(data) => {
1359 Error::new_spanned(data.struct_token, "`struct`s are not supported").to_compile_error()
1360 }
1361 Data::Enum(data) => {
1362 let from_tag = data.variants.iter().enumerate().map(|(i, v)| {
1363 let ident = &v.ident;
1364 quote_spanned! { ident.span() =>
1365 #i => Self::#ident,
1366 }
1367 });
1368 quote! {
1369 match tag.to_usize() {
1370 #(#from_tag)*
1371 _ => unreachable!(),
1372 }
1373 }
1374 }
1375 Data::Union(data) => {
1376 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1377 }
1378 }
1379}
1380
1381fn gen_kind(data: &Data) -> proc_macro2::TokenStream {
1382 match data {
1383 Data::Struct(data) => {
1384 Error::new_spanned(data.struct_token, "`struct`s are not supported").to_compile_error()
1385 }
1386 Data::Enum(data) => {
1387 let variants = data.variants.iter().map(|v| {
1388 let ident = &v.ident;
1389 quote_spanned! { ident.span() =>
1390 Self::#ident {..} => __Kind::#ident,
1391 }
1392 });
1393 quote! {
1394 match self {
1395 #(#variants)*
1396 }
1397 }
1398 }
1399 Data::Union(data) => {
1400 Error::new_spanned(data.union_token, "`union`s are not supported").to_compile_error()
1401 }
1402 }
1403}
1404
1405#[proc_macro_derive(MaybeHasNiche)]
1406pub fn derive_maybe_has_niche(input: TokenStream) -> TokenStream {
1407 let input = parse_macro_input!(input as DeriveInput);
1408 let name = input.ident;
1409 let mn_array = gen_mn_array(&input.data);
1410 let (_, ty_generics, _) = input.generics.split_for_impl();
1411 let generics = match bounds_maybe_has_niche(input.generics.clone(), &input.data) {
1412 Ok(g) => g,
1413 Err(e) => return e.into_compile_error().into(),
1414 };
1415 let (impl_generics, _, where_clause) = generics.split_for_impl();
1416 let output = quote! {
1417 const _: () = {
1418 use ::object_rainbow::typenum::tarr;
1419
1420 #[automatically_derived]
1421 impl #impl_generics ::object_rainbow::MaybeHasNiche for #name #ty_generics #where_clause {
1422 type MnArray = #mn_array;
1423 }
1424 };
1425 };
1426 TokenStream::from(output)
1427}
1428
1429fn bounds_maybe_has_niche(mut generics: Generics, data: &Data) -> syn::Result<Generics> {
1430 match data {
1431 Data::Struct(data) => {
1432 for f in data.fields.iter() {
1433 let ty = &f.ty;
1434 generics
1435 .make_where_clause()
1436 .predicates
1437 .push(parse_quote_spanned! { ty.span() =>
1438 #ty: ::object_rainbow::MaybeHasNiche<
1439 MnArray: ::object_rainbow::MnArray<
1440 MaybeNiche: ::object_rainbow::MaybeNiche
1441 >
1442 >
1443 });
1444 }
1445 }
1446 Data::Enum(data) => {
1447 generics.params.push(parse_quote!(
1448 __N: ::object_rainbow::typenum::Unsigned
1449 ));
1450 for (i, v) in data.variants.iter().enumerate() {
1451 let mn_array = fields_mn_array(&v.fields, Some(i));
1452 generics
1453 .make_where_clause()
1454 .predicates
1455 .push(parse_quote_spanned! { v.span() =>
1456 #mn_array: ::object_rainbow::MnArray<
1457 MaybeNiche: ::object_rainbow::NicheOr<N = __N>
1458 >
1459 });
1460 for f in v.fields.iter() {
1461 let ty = &f.ty;
1462 generics.make_where_clause().predicates.push(
1463 parse_quote_spanned! { ty.span() =>
1464 #ty: ::object_rainbow::MaybeHasNiche<
1465 MnArray: ::object_rainbow::MnArray<
1466 MaybeNiche: ::object_rainbow::MaybeNiche
1467 >
1468 >
1469 },
1470 );
1471 }
1472 }
1473 }
1474 Data::Union(data) => {
1475 return Err(Error::new_spanned(
1476 data.union_token,
1477 "`union`s are not supported",
1478 ));
1479 }
1480 }
1481 Ok(generics)
1482}
1483
1484fn fields_mn_array(fields: &syn::Fields, variant: Option<usize>) -> proc_macro2::TokenStream {
1485 let mn_array = fields.iter().map(|f| {
1486 let ty = &f.ty;
1487 quote! {
1488 <
1489 <
1490 #ty
1491 as
1492 ::object_rainbow::MaybeHasNiche
1493 >::MnArray
1494 as
1495 ::object_rainbow::MnArray
1496 >::MaybeNiche
1497 }
1498 });
1499 if let Some(variant) = variant {
1500 let kind_niche = quote! {
1501 ::object_rainbow::AutoEnumNiche<Self, #variant>
1502 };
1503 quote! { tarr![#kind_niche, ::object_rainbow::NoNiche<::object_rainbow::HackNiche<#variant>>, #(#mn_array),*] }
1504 } else {
1505 quote! { tarr![#(#mn_array),*] }
1506 }
1507}
1508
1509fn gen_mn_array(data: &Data) -> proc_macro2::TokenStream {
1510 match data {
1511 Data::Struct(data) => fields_mn_array(&data.fields, None),
1512 Data::Enum(data) => {
1513 let mn_array = data.variants.iter().enumerate().map(|(i, v)| {
1514 let mn_array = fields_mn_array(&v.fields, Some(i));
1515 quote! { <#mn_array as ::object_rainbow::MnArray>::MaybeNiche }
1516 });
1517 quote! {
1518 ::object_rainbow::NicheFoldOrArray<tarr![#(#mn_array),*]>
1519 }
1520 }
1521 Data::Union(data) => {
1522 Error::new_spanned(data.union_token, "`union`s are not supported").into_compile_error()
1523 }
1524 }
1525}