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