autoproto_derive/
lib.rs

1#![cfg_attr(feature = "nightly", feature(backtrace))]
2
3extern crate proc_macro;
4
5use anyhow::{anyhow, bail};
6use proc_macro::TokenStream;
7use proc_macro2::{Span, TokenStream as TokenStream2};
8use quote::{quote, ToTokens};
9use std::{iter, num::NonZeroU32};
10use syn::{
11    punctuated::Punctuated, Arm, Attribute, Block, Data, DataEnum, DataStruct, DeriveInput, Expr,
12    ExprMatch, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam, Generics, Ident, ItemConst,
13    ItemImpl, ItemStruct, Lit, LitInt, Member, Stmt, Token, Type, TypePath,
14};
15
16mod newtype;
17mod util;
18
19use util::{FieldAttributes, MessageAttributes, Result, WhereClauseBuilder};
20
21#[proc_macro_derive(Message, attributes(autoproto))]
22pub fn derive_message(input: TokenStream) -> TokenStream {
23    #[cfg(feature = "nightly")]
24    if cfg!(debug_assertions) {
25        std::panic::set_hook(Box::new(|_panic_info| {
26            eprintln!("{}", std::backtrace::Backtrace::capture());
27        }));
28    }
29
30    try_derive_message(input).unwrap().into()
31}
32
33#[proc_macro_derive(Proto, attributes(autoproto))]
34pub fn derive_proto(input: TokenStream) -> TokenStream {
35    try_derive_proto(input).unwrap().into()
36}
37
38#[proc_macro_derive(ProtoEncode, attributes(autoproto))]
39pub fn derive_protoencode(input: TokenStream) -> TokenStream {
40    try_derive_protoencode(input).unwrap().into()
41}
42
43#[proc_macro_derive(ProtoScalar, attributes(autoproto))]
44pub fn derive_protoscalar(input: TokenStream) -> TokenStream {
45    try_derive_protoscalar(input).unwrap().into()
46}
47
48#[proc_macro_derive(IsDefault, attributes(autoproto))]
49pub fn derive_is_default(input: TokenStream) -> TokenStream {
50    try_derive_is_default(input).unwrap().into()
51}
52
53fn derive_protoscalar_enum(
54    ident: &Ident,
55    generics: &Generics,
56    data: &DataEnum,
57) -> Result<TokenStream2> {
58    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
59
60    let variant_constants = data
61        .variants
62        .iter()
63        .enumerate()
64        .map::<Result<_>, _>(|(i, variant)| {
65            if variant.fields.is_empty() {
66                let variant_ident = &variant.ident;
67
68                let const_name = Ident::new(&format!("__TAG_{}", i), variant_ident.span().clone());
69
70                let item: ItemConst = syn::parse_quote!(
71                    const #const_name: ::core::primitive::i32 = #ident::#variant_ident as ::core::primitive::i32;
72                );
73
74                Ok((const_name, variant_ident, item))
75            } else {
76                bail!("Cannot derive `protoscalar` for an enum with fields");
77            }
78        })
79        .collect::<Result<Vec<_>>>()?;
80
81    let constant_items = variant_constants
82        .iter()
83        .map(|(_, _, item)| item)
84        .collect::<Vec<_>>();
85
86    let match_arms = variant_constants
87        .iter()
88        .map::<Arm, _>(|(const_name, variant_ident, _)| syn::parse_quote!(#const_name => #ident :: #variant_ident))
89        .collect::<Punctuated<_, Token!(,)>>();
90
91    let (
92        protoscalar_impl,
93        is_default_impl,
94        protoencode_impl,
95        protoencoderepeated_impl,
96        protomergerepeated_impl,
97        proto_impl,
98    ): (ItemImpl, ItemImpl, ItemImpl, ItemImpl, ItemImpl, ItemImpl) = (
99        syn::parse_quote!(
100            impl #impl_generics ::autoproto::ProtoScalar for #ident #ty_generics #where_clause {
101                const DEFAULT_FIXED: ::autoproto::Fixed =
102                    <::core::primitive::i32 as ::autoproto::ProtoScalar>::DEFAULT_FIXED;
103                const DEFAULT_VARINT: ::autoproto::Varint =
104                    <::core::primitive::i32 as ::autoproto::ProtoScalar>::DEFAULT_VARINT;
105                const DEFAULT_ENCODING: ::autoproto::ScalarEncoding =
106                    <::core::primitive::i32 as ::autoproto::ProtoScalar>::DEFAULT_ENCODING;
107
108                fn from_value(other: ::autoproto::Value) -> Option<Self> {
109                    ::core::debug_assert_eq!(<Self as ::core::default::Default>::default() as i32, 0);
110
111                    #(#constant_items)*
112
113                    Some(match <::core::primitive::i32 as ::autoproto::ProtoScalar>::from_value(other)? {
114                        #match_arms,
115                        _ => return None,
116                    })
117                }
118
119                fn to_value(&self) -> ::autoproto::Value {
120                    ::core::debug_assert_eq!(<Self as ::core::default::Default>::default() as i32, 0);
121
122                    <::core::primitive::i32 as ::autoproto::ProtoScalar>::to_value(
123                        &(::core::clone::Clone::clone(self) as ::core::primitive::i32)
124                    )
125                }
126            }
127        ),
128        syn::parse_quote!(
129            impl #impl_generics ::autoproto::IsDefault for #ident #ty_generics #where_clause {
130                fn is_default(&self) -> ::core::primitive::bool {
131                    (::core::clone::Clone::clone(self) as ::core::primitive::i32) == 0
132                }
133            }
134        ),
135        syn::parse_quote!(
136            impl #impl_generics ::autoproto::ProtoEncode for #ident #ty_generics #where_clause {
137                fn encode_as_field(
138                    &self,
139                    tag: ::core::num::NonZeroU32,
140                    buf: &mut dyn ::autoproto::prost::bytes::BufMut,
141                ) {
142                    <
143                        ::autoproto::MappedInt::<Self>
144                        as ::autoproto::ProtoEncode
145                    >::encode_as_field(
146                        &::autoproto::MappedInt::new(::core::clone::Clone::clone(self)),
147                        tag,
148                        buf,
149                    )
150                }
151
152                fn encoded_len_as_field(&self, tag: ::core::num::NonZeroU32) -> usize {
153                    <
154                        ::autoproto::MappedInt::<Self>
155                        as ::autoproto::ProtoEncode
156                    >::encoded_len_as_field(
157                        &::autoproto::MappedInt::new(::core::clone::Clone::clone(self)),
158                        tag,
159                    )
160                }
161            }
162        ),
163        syn::parse_quote!(
164            impl #impl_generics ::autoproto::ProtoEncodeRepeated for #ident #ty_generics #where_clause {
165                fn encode_as_field_repeated<'__lifetime, I>(
166                    iter: I,
167                    tag: ::core::num::NonZeroU32,
168                    buf: &mut dyn ::autoproto::bytes::BufMut,
169                )
170                where
171                    I: ExactSizeIterator<Item = &'__lifetime Self> + Clone,
172                    Self: '__lifetime,
173                {
174                    ::autoproto::MappedInt::<Self>::encode_as_field_repeated(
175                        iter,
176                        tag,
177                        buf,
178                    );
179                }
180
181                fn encoded_len_as_field_repeated<'__lifetime, I>(iter: I, tag: ::core::num::NonZeroU32) -> usize
182                where
183                    I: ExactSizeIterator<Item = &'__lifetime Self>,
184                    Self: '__lifetime,
185                {
186                    ::autoproto::MappedInt::<Self>::encoded_len_as_field_repeated(
187                        iter,
188                        tag,
189                    )
190                }
191        }),
192        syn::parse_quote!(
193            impl #impl_generics ::autoproto::ProtoMergeRepeated for #ident #ty_generics #where_clause {
194                fn merge_repeated<T>(
195                    values: &mut T,
196                    wire_type: ::autoproto::prost::encoding::WireType,
197                    buf: &mut dyn ::autoproto::bytes::Buf,
198                    ctx: ::autoproto::prost::encoding::DecodeContext,
199                ) -> Result<(), ::autoproto::prost::DecodeError>
200                where
201                    T: std::iter::Extend<Self>,
202                {
203                    <::autoproto::MappedInt::<Self> as ::autoproto::ProtoMergeRepeated>::merge_repeated(
204                        &mut ::autoproto::MapExtend::new(values, |::autoproto::MappedInt(i, _)| i),
205                        wire_type,
206                        buf,
207                        ctx,
208                    )
209                }
210            }
211        ),
212        syn::parse_quote!(
213            impl #impl_generics ::autoproto::Proto for #ident #ty_generics #where_clause {
214                fn merge_self(
215                    &mut self,
216                    wire_type: ::autoproto::prost::encoding::WireType,
217                    buf: &mut dyn ::autoproto::prost::bytes::Buf,
218                    ctx: ::autoproto::prost::encoding::DecodeContext,
219                ) -> Result<(), ::autoproto::prost::DecodeError> {
220                    let mut mapped = ::autoproto::MappedInt::<Self>::new(::core::clone::Clone::clone(self));
221                    ::autoproto::Proto::merge_self(&mut mapped, wire_type, buf, ctx)?;
222
223                    *self = mapped.0;
224
225                    Ok(())
226                }
227            }
228        ),
229    );
230
231    Ok(quote! {
232        #is_default_impl
233
234        #protoscalar_impl
235
236        #protoencode_impl
237
238        #proto_impl
239
240        #protoencoderepeated_impl
241
242        #protomergerepeated_impl
243    })
244}
245
246fn derive_protoscalar_struct(
247    ident: &Ident,
248    generics: &Generics,
249    data: &DataStruct,
250) -> Result<TokenStream2> {
251    let (impl_generics, ty_generics, _) = generics.split_for_impl();
252
253    let (inner_field, bracket) = {
254        let (fields, bracket): (_, fn(_) -> _) = match data {
255            DataStruct {
256                fields: Fields::Named(FieldsNamed { named: fields, .. }),
257                ..
258            } => (fields, |toks| quote!({ #toks })),
259            DataStruct {
260                fields:
261                    Fields::Unnamed(FieldsUnnamed {
262                        unnamed: fields, ..
263                    }),
264                ..
265            } => (fields, |toks| quote!(( #toks ))),
266            DataStruct {
267                fields: Fields::Unit,
268                ..
269            } => {
270                bail!("`ProtoScalar` can only be implemented for `newtype` structs");
271            }
272        };
273
274        (
275            fields.first().ok_or_else(|| anyhow!("Programmer error"))?,
276            bracket,
277        )
278    };
279
280    let field: Member = inner_field
281        .ident
282        .clone()
283        .map(Member::Named)
284        .unwrap_or_else(|| Member::Unnamed(0.into()));
285
286    let mut where_clause_builder = WhereClauseBuilder::new(generics);
287    let (
288        is_default_impl,
289        protoscalar_impl,
290        protoencode_impl,
291        proto_impl,
292        protoencoderepeated_impl,
293        protomergerepeated_impl,
294    ) = (
295        newtype::is_default(
296            ident,
297            &field,
298            &impl_generics,
299            &ty_generics,
300            &mut where_clause_builder,
301        ),
302        newtype::protoscalar(
303            ident,
304            &field,
305            &inner_field.ty,
306            bracket,
307            &impl_generics,
308            &ty_generics,
309            &mut where_clause_builder,
310        ),
311        newtype::protoencode(
312            ident,
313            &field,
314            &impl_generics,
315            &ty_generics,
316            &mut where_clause_builder,
317        ),
318        newtype::proto(
319            ident,
320            &field,
321            &impl_generics,
322            &ty_generics,
323            &mut where_clause_builder,
324        ),
325        newtype::protoencoderepeated(
326            ident,
327            &field,
328            &inner_field.ty,
329            &impl_generics,
330            &ty_generics,
331            &mut where_clause_builder,
332        ),
333        newtype::protomergerepeated(
334            ident,
335            &field,
336            &inner_field.ty,
337            bracket,
338            &impl_generics,
339            &ty_generics,
340            &mut where_clause_builder,
341        ),
342    );
343
344    Ok(quote! {
345        #is_default_impl
346
347        #protoscalar_impl
348
349        #protoencode_impl
350
351        #proto_impl
352
353        #protoencoderepeated_impl
354
355        #protomergerepeated_impl
356    })
357}
358
359fn try_derive_protoscalar(input: TokenStream) -> Result<TokenStream2> {
360    let input: DeriveInput = syn::parse(input)?;
361    let DeriveInput {
362        attrs: _,
363        vis: _,
364        ident,
365        generics,
366        data,
367    } = &input;
368
369    match data {
370        Data::Struct(data) => derive_protoscalar_struct(ident, generics, data),
371        Data::Enum(data) => derive_protoscalar_enum(ident, generics, data),
372        Data::Union(_) => bail!("Cannot derive `ProtoScalar` for an untagged union"),
373    }
374}
375
376fn try_derive_is_default(input: TokenStream) -> Result<TokenStream2> {
377    let input: DeriveInput = syn::parse(input)?;
378    let DeriveInput {
379        attrs,
380        vis: _,
381        ident,
382        generics,
383        data,
384    } = &input;
385
386    let attrs = MessageAttributes::new(attrs)?;
387
388    let (impl_generics, ty_generics, _) = generics.split_for_impl();
389    if attrs.transparent {
390        let inner_field = match data {
391            Data::Struct(DataStruct {
392                fields: Fields::Named(FieldsNamed { named: fields, .. }),
393                ..
394            })
395            | Data::Struct(DataStruct {
396                fields:
397                    Fields::Unnamed(FieldsUnnamed {
398                        unnamed: fields, ..
399                    }),
400                ..
401            }) => {
402                if fields.len() != 1 {
403                    bail!("`transparent` message must have exactly one field");
404                }
405
406                fields.first().ok_or_else(|| anyhow!("Programmer error"))?
407            }
408            Data::Struct(DataStruct {
409                fields: Fields::Unit,
410                ..
411            }) => {
412                bail!("Cannot have a `transparent` message without fields");
413            }
414            _ => {
415                bail!("Invalid type for a `transparent` message");
416            }
417        };
418
419        let field: Member = inner_field
420            .ident
421            .clone()
422            .map(Member::Named)
423            .unwrap_or_else(|| Member::Unnamed(0.into()));
424
425        let mut where_clause_builder = WhereClauseBuilder::new(generics);
426        let is_default_impl = newtype::is_default(
427            ident,
428            &field,
429            &impl_generics,
430            &ty_generics,
431            &mut where_clause_builder,
432        );
433
434        Ok(quote! { #is_default_impl })
435    } else {
436        let where_clause_builder = WhereClauseBuilder::new(&generics);
437        let where_clause = where_clause_builder
438            .with_self_bound(quote!(::core::default::Default + ::core::cmp::PartialEq));
439
440        Ok(quote! {
441            impl #impl_generics ::autoproto::IsDefault for #ident #ty_generics
442            #where_clause
443            {
444                fn is_default(&self) -> bool {
445                    ::autoproto::generic::default::is_default(self)
446                }
447            }
448        })
449    }
450}
451
452enum DeriveMode {
453    ImmutableOnly,
454    ImmutableAndMutable,
455}
456
457impl Default for DeriveMode {
458    fn default() -> Self {
459        Self::ImmutableAndMutable
460    }
461}
462
463fn try_derive_protoencode(input: TokenStream) -> Result<TokenStream2> {
464    let input: DeriveInput = syn::parse(input)?;
465    let DeriveInput {
466        attrs,
467        vis: _,
468        ident,
469        generics,
470        data,
471    } = &input;
472
473    let attrs = MessageAttributes::new(attrs)?;
474
475    if attrs.transparent {
476        let inner_field = match data {
477            Data::Struct(DataStruct {
478                fields: Fields::Named(FieldsNamed { named: fields, .. }),
479                ..
480            })
481            | Data::Struct(DataStruct {
482                fields:
483                    Fields::Unnamed(FieldsUnnamed {
484                        unnamed: fields, ..
485                    }),
486                ..
487            }) => {
488                if fields.len() != 1 {
489                    bail!("`transparent` message must have exactly one field");
490                }
491
492                fields.first().ok_or_else(|| anyhow!("Programmer error"))?
493            }
494            Data::Struct(DataStruct {
495                fields: Fields::Unit,
496                ..
497            }) => {
498                bail!("Cannot have a `transparent` message without fields");
499            }
500            _ => {
501                bail!("Invalid type for a `transparent` message");
502            }
503        };
504
505        let (impl_generics, ty_generics, _) = generics.split_for_impl();
506        let field: Member = inner_field
507            .ident
508            .clone()
509            .map(Member::Named)
510            .unwrap_or_else(|| Member::Unnamed(0.into()));
511
512        let mut where_clause_builder = WhereClauseBuilder::new(generics);
513        let protoencode_impl = newtype::protoencode(
514            ident,
515            &field,
516            &impl_generics,
517            &ty_generics,
518            &mut where_clause_builder,
519        );
520
521        Ok(quote! { #protoencode_impl })
522    } else {
523        match data {
524            Data::Struct(DataStruct {
525                fields: Fields::Named(FieldsNamed { named: fields, .. }),
526                ..
527            })
528            | Data::Struct(DataStruct {
529                fields:
530                    Fields::Unnamed(FieldsUnnamed {
531                        unnamed: fields, ..
532                    }),
533                ..
534            }) => {
535                let protostruct_impl = try_derive_protostruct(
536                    fields.into_iter(),
537                    ident,
538                    generics,
539                    DeriveMode::ImmutableOnly,
540                )?;
541
542                let (impl_generics, ty_generics, _) = generics.split_for_impl();
543
544                let protoencode_impl = impl_protoencode_for_protostruct(
545                    ident,
546                    &impl_generics,
547                    &ty_generics,
548                    &mut WhereClauseBuilder::new(generics),
549                );
550
551                Ok(quote!(
552                    #protostruct_impl
553                    #protoencode_impl
554                ))
555            }
556            Data::Union(..) => {
557                bail!("Message can not be derived for an untagged union (try using `enum`)")
558            }
559            _ => {
560                bail!("Currently unsupported type for `derive(ProtoEncode)`")
561            }
562        }
563    }
564}
565
566fn try_derive_message(input: TokenStream) -> Result<TokenStream2> {
567    let input: DeriveInput = syn::parse(input)?;
568    let DeriveInput {
569        attrs,
570        vis: _,
571        ident,
572        generics,
573        data,
574    } = &input;
575
576    match data {
577        Data::Struct(data) => try_derive_message_for_struct(attrs, ident, generics, data),
578        Data::Enum(data) => try_derive_oneof(attrs, ident, generics, data),
579        Data::Union(..) => {
580            bail!("Message can not be derived for an untagged union (try using `enum`)")
581        }
582    }
583}
584
585fn try_derive_proto(input: TokenStream) -> Result<TokenStream2> {
586    let input: DeriveInput = syn::parse(input)?;
587    let DeriveInput {
588        attrs,
589        vis: _,
590        ident,
591        generics,
592        data,
593    } = &input;
594
595    match data {
596        Data::Struct(data) => try_derive_proto_for_struct(attrs, ident, generics, data),
597        Data::Enum(..) => todo!(),
598        Data::Union(..) => {
599            bail!("Message can not be derived for an untagged union (try using `enum`)")
600        }
601    }
602}
603
604fn try_derive_oneof(
605    _attrs: &[Attribute],
606    ident: &Ident,
607    generics: &Generics,
608    data: &DataEnum,
609) -> Result<TokenStream2> {
610    fn make_variant_get_field_arm_with_fields<F, T, FIter>(
611        ident: &Ident,
612        tag: &Lit,
613        generics: &Generics,
614        mut brackets: F,
615        semicolon: Option<Token!(;)>,
616        fields: &FIter,
617    ) -> Arm
618    where
619        F: FnMut(TokenStream2) -> T,
620        T: ToTokens,
621        for<'a> &'a FIter: IntoIterator<Item = &'a Field>,
622    {
623        let names = fields
624            .into_iter()
625            .enumerate()
626            .map(|(i, field)| {
627                field
628                    .ident
629                    .clone()
630                    .unwrap_or_else(|| Ident::new(&format!("__field_{}", i), Span::call_site()))
631            })
632            .collect::<Punctuated<_, Token!(,)>>();
633
634        let make_refs = names
635            .iter()
636            .map::<Expr, _>(|name| syn::parse_quote!(::autoproto::generic::Wrapper(#name)))
637            .collect::<Punctuated<_, Token!(,)>>();
638
639        let make_refs: Stmt = syn::parse_quote!(let (#names) = (#make_refs););
640
641        let (typarams, dummy_fields): (Vec<Ident>, Punctuated<_, Token!(,)>) = fields
642            .into_iter()
643            .cloned()
644            .enumerate()
645            .map(|(i, field)| {
646                let tyident = Ident::new(&format!("__Ty{}", i), Span::call_site());
647                let ty = Type::Path(TypePath {
648                    qself: None,
649                    path: tyident.clone().into(),
650                });
651
652                (tyident, Field { ty, ..field })
653            })
654            .unzip();
655
656        let dummy_generics = Generics {
657            params: typarams
658                .into_iter()
659                .map(|name| GenericParam::Type(name.into()))
660                .collect(),
661            where_clause: None,
662            ..generics.clone()
663        };
664
665        let struct_body = brackets(quote!(#dummy_fields));
666        let variant_bindings = brackets(quote!(#names));
667
668        syn::parse_quote!(
669            Self::#ident #variant_bindings => {
670                #[derive(::autoproto::ProtoEncode)]
671                struct #ident #dummy_generics #struct_body #semicolon
672
673                #make_refs
674
675                __proto_arg_func(
676                    &#ident #variant_bindings,
677                    unsafe { ::core::num::NonZeroU32::new_unchecked(#tag) },
678                )
679            }
680        )
681    }
682
683    fn make_unit_variant_get_field_arm<T: ToTokens>(ident: &Ident, tag: &Lit, brackets: T) -> Arm {
684        syn::parse_quote!(
685            Self::#ident #brackets => __proto_arg_func(
686                &(),
687                unsafe { ::core::num::NonZeroU32::new_unchecked(#tag) },
688            )
689        )
690    }
691
692    fn make_newtype_variant_get_field_arm<F, T>(
693        ident: &Ident,
694        tag: &Lit,
695        field_name: Ident,
696        brackets: F,
697    ) -> Arm
698    where
699        F: FnOnce(TokenStream2) -> T,
700        T: ToTokens,
701    {
702        let field_name_pat = brackets(quote!(#field_name));
703
704        syn::parse_quote!(
705            Self::#ident #field_name_pat => __proto_arg_func(
706                #field_name,
707                unsafe { ::core::num::NonZeroU32::new_unchecked(#tag) },
708            )
709        )
710    }
711
712    fn make_variant_get_field_arm(
713        ident: &Ident,
714        tag: &Lit,
715        generics: &Generics,
716        fields: &Fields,
717    ) -> Arm {
718        match &fields {
719            Fields::Named(FieldsNamed { named: fields, .. }) => match fields.len() {
720                0 => make_unit_variant_get_field_arm(ident, tag, quote!({})),
721                1 => {
722                    let field_name = fields
723                        .first()
724                        .and_then(|field| field.ident.clone())
725                        .expect("Programmer error: names array should have one named element");
726
727                    make_newtype_variant_get_field_arm(ident, tag, field_name, |f| quote!( { #f } ))
728                }
729                _ => make_variant_get_field_arm_with_fields(
730                    ident,
731                    tag,
732                    generics,
733                    |val| quote!( { #val } ),
734                    None,
735                    fields,
736                ),
737            },
738            Fields::Unnamed(FieldsUnnamed {
739                unnamed: fields, ..
740            }) => match fields.len() {
741                0 => make_unit_variant_get_field_arm(ident, tag, quote!(())),
742                1 => {
743                    let field_name = Ident::new("__proto_enum_inner", Span::call_site());
744
745                    make_newtype_variant_get_field_arm(ident, tag, field_name, |f| quote!( ( #f ) ))
746                }
747                _ => make_variant_get_field_arm_with_fields(
748                    ident,
749                    tag,
750                    generics,
751                    |val| quote!( ( #val ) ),
752                    Some(Default::default()),
753                    fields,
754                ),
755            },
756            Fields::Unit => make_unit_variant_get_field_arm(ident, tag, quote!()),
757        }
758    }
759
760    fn make_variant_exec_merge_arm_with_fields<F, T, FIter>(
761        ident: &Ident,
762        tag: &Lit,
763        generics: &Generics,
764        mut brackets: F,
765        semicolon: Option<Token!(;)>,
766        fields: &FIter,
767    ) -> Arm
768    where
769        F: FnMut(TokenStream2) -> T,
770        T: ToTokens,
771        for<'a> &'a FIter: IntoIterator<Item = &'a Field>,
772    {
773        let names = fields
774            .into_iter()
775            .enumerate()
776            .map(|(i, field)| {
777                field
778                    .ident
779                    .clone()
780                    .unwrap_or_else(|| Ident::new(&format!("__field_{}", i), Span::call_site()))
781            })
782            .collect::<Punctuated<_, Token!(,)>>();
783
784        let (typarams, dummy_fields): (Vec<Ident>, Punctuated<_, Token!(,)>) = fields
785            .into_iter()
786            .cloned()
787            .enumerate()
788            .map(|(i, field)| {
789                let tyident = Ident::new(&format!("__Ty{}", i), Span::call_site());
790                let ty = Type::Path(TypePath {
791                    qself: None,
792                    path: tyident.clone().into(),
793                });
794
795                (tyident, Field { ty, ..field })
796            })
797            .unzip();
798
799        let dummy_generics = Generics {
800            params: typarams
801                .into_iter()
802                .map(|name| GenericParam::Type(name.into()))
803                .collect(),
804            where_clause: None,
805            ..generics.clone()
806        };
807
808        let struct_body = brackets(quote!(
809            #dummy_fields,
810        ));
811        let ref_mut_construct: Stmt = {
812            let construct = names
813                .iter()
814                .map::<Expr, _>(|name| syn::parse_quote!(::autoproto::generic::Wrapper(#name)))
815                .collect::<Punctuated<_, Token!(,)>>();
816            syn::parse_quote!(let (#names) = (#construct);)
817        };
818        let owned_construct: Stmt = {
819            let default: Expr = syn::parse_quote!(::core::default::Default::default());
820
821            let construct = names
822                .iter()
823                .map(|_| default.clone())
824                .collect::<Punctuated<_, Token!(,)>>();
825            syn::parse_quote!(let (#names) = (#construct);)
826        };
827        let variant_bindings = brackets(quote!(#names));
828
829        let (dummy_impl_generics, dummy_ty_generics, _) = dummy_generics.split_for_impl();
830
831        let where_clause_builder = WhereClauseBuilder::new(&dummy_generics);
832        let clear_where_clause = where_clause_builder.with_bound(quote!(::autoproto::Clear));
833
834        let deconstruct_dummy = brackets(quote!(#names));
835
836        let clear_all = Block {
837            brace_token: syn::token::Brace {
838                span: Span::call_site(),
839            },
840            stmts: names
841                .iter()
842                .map::<Stmt, _>(|name| syn::parse_quote!(::autoproto::Clear::clear(#name);))
843                .collect(),
844        };
845
846        let (dummy_struct_def, dummy_clear_impl): (ItemStruct, ItemImpl) = (
847            syn::parse_quote!(
848                #[derive(::autoproto::Proto)]
849                struct #ident #dummy_generics #struct_body #semicolon
850            ),
851            syn::parse_quote!(
852                impl #dummy_impl_generics ::autoproto::Clear for #ident #dummy_ty_generics
853                #clear_where_clause
854                {
855                    fn clear(&mut self)  {
856                        let Self #deconstruct_dummy = self;
857
858                        #clear_all
859                    }
860                }
861            ),
862        );
863
864        syn::parse_quote!(
865            #tag => {
866                #dummy_struct_def
867
868                #dummy_clear_impl
869
870                match self {
871                    Self :: #ident #variant_bindings => {
872                        #ref_mut_construct
873
874                        let mut __proto_dummy_struct = #ident #variant_bindings;
875
876                        __proto_arg_func(&mut __proto_dummy_struct)
877                    }
878                    _ => {
879                        #owned_construct
880
881                        let mut __proto_dummy_struct = #ident #variant_bindings;
882
883                        let out = __proto_arg_func(&mut __proto_dummy_struct);
884
885                        let #ident #deconstruct_dummy = __proto_dummy_struct;
886
887                        *self = Self::#ident #variant_bindings;
888
889                        out
890                    }
891                }
892            }
893        )
894    }
895
896    fn make_unit_variant_exec_merge_arm(tag: &Lit) -> Arm {
897        syn::parse_quote!(
898            #tag => __proto_arg_func(&mut ())
899        )
900    }
901
902    fn make_newtype_variant_exec_merge_arm<F, T>(
903        ident: &Ident,
904        tag: &Lit,
905        field_name: Option<Ident>,
906        brackets: F,
907    ) -> Arm
908    where
909        F: FnOnce(TokenStream2) -> T,
910        T: ToTokens,
911    {
912        let name = Ident::new("__proto_new_inner", Span::call_site());
913
914        let field_spec = field_name.map(|name| quote!(#name :));
915
916        let construct_variant = brackets(quote!(#field_spec #name));
917
918        syn::parse_quote!(
919            #tag => {
920                let mut #name = Default::default();
921
922                let out = __proto_arg_func(&mut #name);
923
924                *self = Self::#ident #construct_variant;
925
926                out
927            }
928        )
929    }
930
931    fn make_variant_exec_merge_arm(
932        ident: &Ident,
933        tag: &Lit,
934        generics: &Generics,
935        fields: &Fields,
936    ) -> Arm {
937        match &fields {
938            Fields::Named(FieldsNamed { named: fields, .. }) => match fields.len() {
939                0 => make_unit_variant_exec_merge_arm(tag),
940                1 => {
941                    let field_name = fields
942                        .first()
943                        .and_then(|field| field.ident.clone())
944                        .expect("Programmer error: names array should have one named element");
945
946                    make_newtype_variant_exec_merge_arm(
947                        ident,
948                        tag,
949                        Some(field_name),
950                        |f| quote!( { #f } ),
951                    )
952                }
953                _ => make_variant_exec_merge_arm_with_fields(
954                    ident,
955                    tag,
956                    generics,
957                    |val| quote!( { #val } ),
958                    None,
959                    fields,
960                ),
961            },
962            Fields::Unnamed(FieldsUnnamed {
963                unnamed: fields, ..
964            }) => match fields.len() {
965                0 => make_unit_variant_exec_merge_arm(tag),
966                1 => make_newtype_variant_exec_merge_arm(ident, tag, None, |f| quote!( ( #f ) )),
967                _ => make_variant_exec_merge_arm_with_fields(
968                    ident,
969                    tag,
970                    generics,
971                    |val| quote!( ( #val ) ),
972                    Some(Default::default()),
973                    fields,
974                ),
975            },
976            Fields::Unit => make_unit_variant_exec_merge_arm(tag),
977        }
978    }
979
980    let mut explicitly_tagged = None::<bool>;
981
982    let variants = data
983        .variants
984        .iter()
985        .enumerate()
986        .map(|(i, variant)| {
987            let attributes = FieldAttributes::new(&variant.attrs)?;
988
989            match (explicitly_tagged, &attributes.tag) {
990                (None, _) | (Some(true), Some(_)) | (Some(false), None) => {}
991                (Some(true), None) | (Some(false), Some(_)) => {
992                    return Err(anyhow!(
993                        "If `tag` is specified for one field it must be specified for all fields"
994                    ));
995                }
996            }
997
998            explicitly_tagged = Some(attributes.tag.is_some());
999
1000            let tag = attributes
1001                .tag
1002                .unwrap_or_else(|| NonZeroU32::new(i as u32 + 1).unwrap());
1003            let tag: Lit = LitInt::new(&tag.get().to_string(), Span::call_site()).into();
1004
1005            Ok((tag, variant))
1006        })
1007        .collect::<Result<Vec<_>>>()?;
1008
1009    let (impl_generics, ty_generics, _) = generics.split_for_impl();
1010
1011    let variant_get_field: Vec<Arm> = variants
1012        .iter()
1013        .map::<Arm, _>(|(tag, variant)| {
1014            make_variant_get_field_arm(&variant.ident, tag, generics, &variant.fields)
1015        })
1016        .collect();
1017
1018    let variant_exec_merge: Vec<Arm> = variants
1019        .iter()
1020        .map::<Arm, _>(|(tag, variant)| {
1021            make_variant_exec_merge_arm(&variant.ident, tag, generics, &variant.fields)
1022        })
1023        .chain(iter::once(
1024            syn::parse_quote!(_ => { return ::core::option::Option::<__FuncOut>::None; }),
1025        ))
1026        .collect();
1027
1028    let where_clause_builder = WhereClauseBuilder::new(generics);
1029
1030    let get_variant = ExprMatch {
1031        attrs: vec![],
1032        match_token: Default::default(),
1033        expr: syn::parse_quote!(self),
1034        brace_token: Default::default(),
1035        arms: variant_get_field,
1036    };
1037
1038    let exec_merge = ExprMatch {
1039        attrs: vec![],
1040        match_token: Default::default(),
1041        expr: syn::parse_quote!(::core::num::NonZeroU32::get(tag)),
1042        brace_token: Default::default(),
1043        arms: variant_exec_merge,
1044    };
1045
1046    let message_where_clause = where_clause_builder.with_self_bound(quote!(
1047        ::autoproto::ProtoOneof
1048            + ::autoproto::Clear
1049            + ::core::fmt::Debug
1050            + ::core::marker::Send
1051            + ::core::marker::Sync
1052    ));
1053    let message_impl = impl_message_for_protooneof(
1054        ident,
1055        &impl_generics,
1056        &ty_generics,
1057        Some(&message_where_clause),
1058    );
1059
1060    let protooneof_where_clause = where_clause_builder.with_bound(quote!(
1061        ::core::default::Default + ::autoproto::Proto + ::autoproto::Clear
1062    ));
1063
1064    Ok(quote!(
1065        impl #impl_generics ::autoproto::ProtoOneof for #ident #ty_generics
1066        #protooneof_where_clause
1067        {
1068            fn variant<__Func, __FuncOut>(&self, __proto_arg_func: __Func) -> __FuncOut
1069            where
1070                __Func: ::core::ops::FnOnce(&(dyn ::autoproto::ProtoEncode + '_), ::core::num::NonZeroU32) -> __FuncOut
1071            {
1072                #get_variant
1073            }
1074
1075            fn exec_merge<__Func, __FuncOut>(&mut self, tag: ::core::num::NonZeroU32, __proto_arg_func: __Func) -> Option<__FuncOut>
1076            where
1077                __Func: ::core::ops::FnOnce(&mut (dyn ::autoproto::Proto + '_)) -> __FuncOut
1078            {
1079                ::core::option::Option::<__FuncOut>::Some(#exec_merge)
1080            }
1081        }
1082
1083        impl #impl_generics ::autoproto::IsMessage for #ident #ty_generics #protooneof_where_clause {}
1084
1085        #message_impl
1086    ))
1087}
1088
1089fn try_derive_protostruct<'a>(
1090    fields: impl ExactSizeIterator<Item = &'a Field>,
1091    ident: &Ident,
1092    generics: &Generics,
1093    mode: DeriveMode,
1094) -> Result<TokenStream2> {
1095    let (impl_generics, ty_generics, _) = generics.split_for_impl();
1096
1097    let num_fields = fields.len();
1098
1099    let mut explicitly_tagged = None::<bool>;
1100
1101    let fields: Result<Vec<(NonZeroU32, Member)>> = fields
1102        .enumerate()
1103        .map(|(i, field)| {
1104            let attributes = FieldAttributes::new(&field.attrs)?;
1105
1106            match (explicitly_tagged, &attributes.tag) {
1107                (None, _) | (Some(true), Some(_)) | (Some(false), None) => {}
1108                (Some(true), None) | (Some(false), Some(_)) => {
1109                    return Err(anyhow!(
1110                        "If `tag` is specified for one field it must be specified for all fields"
1111                    ));
1112                }
1113            }
1114
1115            explicitly_tagged = Some(attributes.tag.is_some());
1116
1117            Ok((
1118                attributes
1119                    .tag
1120                    .unwrap_or_else(|| NonZeroU32::new(i as u32 + 1).unwrap()),
1121                field
1122                    .ident
1123                    .clone()
1124                    .map(Member::Named)
1125                    .unwrap_or_else(|| Member::Unnamed(i.into())),
1126            ))
1127        })
1128        .collect();
1129    let fields = fields?;
1130
1131    let fields_array: Punctuated<_, Token!(,)> = fields
1132        .iter()
1133        .map(|(tag, member)| {
1134            let tag: Lit = LitInt::new(&tag.get().to_string(), Span::call_site()).into();
1135
1136            quote!(
1137                (
1138                    unsafe { ::core::num::NonZeroU32::new_unchecked(#tag) },
1139                    &self.#member as &dyn ::autoproto::ProtoEncode,
1140                )
1141            )
1142        })
1143        .collect();
1144
1145    let get_field_mut: Punctuated<_, Token!(,)> = fields
1146        .into_iter()
1147        .map::<Arm, _>(|(tag, member)| {
1148            let tag: Lit = LitInt::new(&tag.get().to_string(), Span::call_site()).into();
1149
1150            syn::parse_quote!(#tag => &mut self.#member)
1151        })
1152        .chain(iter::once(syn::parse_quote!(_ => { return None; })))
1153        .collect();
1154
1155    let where_clause_builder = WhereClauseBuilder::new(generics);
1156
1157    let protostruct_where_clause =
1158        where_clause_builder.with_bound(quote!(::autoproto::ProtoEncode));
1159    let protostructmut_where_clause = where_clause_builder
1160        .with_bound(quote!(::autoproto::Proto))
1161        .with_self_bound(quote!(::autoproto::ProtoStruct));
1162
1163    let immut: ItemImpl = syn::parse_quote! {
1164        impl #impl_generics ::autoproto::ProtoStruct for #ident #ty_generics #protostruct_where_clause {
1165            type Fields<'__field_lifetime>
1166            where
1167                Self: '__field_lifetime
1168            = [
1169                (
1170                    ::core::num::NonZeroU32,
1171                    &'__field_lifetime (dyn ::autoproto::ProtoEncode + '__field_lifetime),
1172                );
1173                #num_fields
1174            ];
1175
1176            fn fields(&self) -> Self::Fields<'_> {
1177                [#fields_array]
1178            }
1179        }
1180    };
1181    let mutable: Option<ItemImpl> = match mode {
1182        DeriveMode::ImmutableOnly => None,
1183        DeriveMode::ImmutableAndMutable => Some(syn::parse_quote! {
1184            impl #impl_generics ::autoproto::ProtoStructMut for #ident #ty_generics
1185            #protostructmut_where_clause
1186            {
1187                fn field_mut(&mut self, tag: ::core::num::NonZeroU32) -> Option<&mut dyn ::autoproto::Proto> {
1188                    Some(match ::core::num::NonZeroU32::get(tag) {
1189                        #get_field_mut
1190                    })
1191                }
1192            }
1193        }),
1194    };
1195
1196    Ok(quote! {
1197        impl #impl_generics ::autoproto::IsMessage for #ident #ty_generics #protostruct_where_clause {}
1198
1199        #immut
1200
1201        #mutable
1202    })
1203}
1204
1205fn try_derive_proto_for_struct(
1206    attrs: &[Attribute],
1207    ident: &Ident,
1208    generics: &Generics,
1209    data: &DataStruct,
1210) -> Result<TokenStream2> {
1211    let attrs = MessageAttributes::new(attrs)?;
1212
1213    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
1214
1215    let mut where_clause_builder = WhereClauseBuilder::new(generics);
1216
1217    if attrs.transparent {
1218        let inner_field = match data {
1219            DataStruct {
1220                fields: Fields::Named(FieldsNamed { named: fields, .. }),
1221                ..
1222            }
1223            | DataStruct {
1224                fields:
1225                    Fields::Unnamed(FieldsUnnamed {
1226                        unnamed: fields, ..
1227                    }),
1228                ..
1229            } => {
1230                if fields.len() != 1 {
1231                    bail!("`transparent` message must have exactly one field");
1232                }
1233
1234                fields.first().ok_or_else(|| anyhow!("Programmer error"))?
1235            }
1236            DataStruct {
1237                fields: Fields::Unit,
1238                ..
1239            } => {
1240                bail!("Cannot have a `transparent` message without fields");
1241            }
1242        };
1243
1244        let field: Member = inner_field
1245            .ident
1246            .clone()
1247            .map(Member::Named)
1248            .unwrap_or_else(|| Member::Unnamed(0.into()));
1249
1250        let mut where_clause_builder = WhereClauseBuilder::new(generics);
1251
1252        let (protoencode_impl, proto_impl) = (
1253            newtype::protoencode(
1254                ident,
1255                &field,
1256                &impl_generics,
1257                &ty_generics,
1258                &mut where_clause_builder,
1259            ),
1260            newtype::proto(
1261                ident,
1262                &field,
1263                &impl_generics,
1264                &ty_generics,
1265                &mut where_clause_builder,
1266            ),
1267        );
1268
1269        Ok(quote! {
1270            #protoencode_impl
1271            #proto_impl
1272        })
1273    } else {
1274        match data {
1275            DataStruct {
1276                fields: Fields::Named(FieldsNamed { named: fields, .. }),
1277                ..
1278            }
1279            | DataStruct {
1280                fields:
1281                    Fields::Unnamed(FieldsUnnamed {
1282                        unnamed: fields, ..
1283                    }),
1284                ..
1285            } => {
1286                if fields.is_empty() {
1287                    Ok(unit_proto_impl(
1288                        ident,
1289                        impl_generics,
1290                        ty_generics,
1291                        where_clause,
1292                    ))
1293                } else {
1294                    let protostruct_impl = try_derive_protostruct(
1295                        fields.into_iter(),
1296                        ident,
1297                        generics,
1298                        Default::default(),
1299                    )?;
1300
1301                    let proto_impl = impl_proto_for_protostruct(
1302                        ident,
1303                        &impl_generics,
1304                        &ty_generics,
1305                        &mut where_clause_builder,
1306                    );
1307
1308                    Ok(quote!(
1309                        #protostruct_impl
1310
1311                        #proto_impl
1312                    ))
1313                }
1314            }
1315            DataStruct {
1316                fields: Fields::Unit,
1317                ..
1318            } => Ok(unit_proto_impl(
1319                ident,
1320                impl_generics,
1321                ty_generics,
1322                where_clause,
1323            )),
1324        }
1325    }
1326}
1327
1328fn try_derive_message_for_struct(
1329    attrs: &[Attribute],
1330    ident: &Ident,
1331    generics: &Generics,
1332    data: &DataStruct,
1333) -> Result<TokenStream2> {
1334    let attrs = MessageAttributes::new(attrs)?;
1335
1336    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
1337
1338    let where_clause_builder = WhereClauseBuilder::new(generics);
1339
1340    if attrs.transparent {
1341        let inner_field = match data {
1342            DataStruct {
1343                fields: Fields::Named(FieldsNamed { named: fields, .. }),
1344                ..
1345            }
1346            | DataStruct {
1347                fields:
1348                    Fields::Unnamed(FieldsUnnamed {
1349                        unnamed: fields, ..
1350                    }),
1351                ..
1352            } => {
1353                if fields.len() != 1 {
1354                    bail!("`transparent` message must have exactly one field");
1355                }
1356
1357                fields.first().ok_or_else(|| anyhow!("Programmer error"))?
1358            }
1359            DataStruct {
1360                fields: Fields::Unit,
1361                ..
1362            } => {
1363                bail!("Cannot have a `transparent` message without fields");
1364            }
1365        };
1366
1367        let field: Member = inner_field
1368            .ident
1369            .clone()
1370            .map(Member::Named)
1371            .unwrap_or_else(|| Member::Unnamed(0.into()));
1372
1373        let mut where_clause_builder = WhereClauseBuilder::new(generics);
1374
1375        let (protoencode_impl, proto_impl, message_impl) = (
1376            newtype::protoencode(
1377                ident,
1378                &field,
1379                &impl_generics,
1380                &ty_generics,
1381                &mut where_clause_builder,
1382            ),
1383            newtype::proto(
1384                ident,
1385                &field,
1386                &impl_generics,
1387                &ty_generics,
1388                &mut where_clause_builder,
1389            ),
1390            newtype::message(
1391                ident,
1392                &field,
1393                &impl_generics,
1394                &ty_generics,
1395                &mut where_clause_builder,
1396            ),
1397        );
1398
1399        Ok(quote! {
1400            #protoencode_impl
1401            #proto_impl
1402            #message_impl
1403        })
1404    } else {
1405        match data {
1406            DataStruct {
1407                fields: Fields::Named(FieldsNamed { named: fields, .. }),
1408                ..
1409            }
1410            | DataStruct {
1411                fields:
1412                    Fields::Unnamed(FieldsUnnamed {
1413                        unnamed: fields, ..
1414                    }),
1415                ..
1416            } => {
1417                if fields.is_empty() {
1418                    Ok(unit_proto_impl(
1419                        ident,
1420                        impl_generics,
1421                        ty_generics,
1422                        where_clause,
1423                    ))
1424                } else {
1425                    let protostruct_impl = try_derive_protostruct(
1426                        fields.into_iter(),
1427                        ident,
1428                        generics,
1429                        Default::default(),
1430                    )?;
1431
1432                    let message_where_clause = where_clause_builder.with_self_bound(quote!(
1433                        ::autoproto::ProtoStructMut
1434                            + ::autoproto::Clear
1435                            + ::core::fmt::Debug
1436                            + ::core::marker::Send
1437                            + ::core::marker::Sync
1438                    ));
1439                    let message_impl = impl_message_for_protostruct(
1440                        ident,
1441                        &impl_generics,
1442                        &ty_generics,
1443                        Some(&message_where_clause),
1444                    );
1445
1446                    Ok(quote!(
1447                        #protostruct_impl
1448
1449                        #message_impl
1450                    ))
1451                }
1452            }
1453            DataStruct {
1454                fields: Fields::Unit,
1455                ..
1456            } => Ok(unit_proto_impl(
1457                ident,
1458                impl_generics,
1459                ty_generics,
1460                where_clause,
1461            )),
1462        }
1463    }
1464}
1465
1466fn impl_message_for_protooneof(
1467    ident: &Ident,
1468    impl_generics: &syn::ImplGenerics,
1469    ty_generics: &syn::TypeGenerics,
1470    where_clause: Option<&syn::WhereClause>,
1471) -> ItemImpl {
1472    syn::parse_quote!(
1473        impl #impl_generics ::autoproto::prost::Message for #ident #ty_generics #where_clause
1474        {
1475            fn encode_raw<__Buffer>(&self, buf: &mut __Buffer)
1476            where
1477                __Buffer: ::autoproto::prost::bytes::BufMut,
1478            {
1479                ::autoproto::generic::protooneof::message_encode_raw(self, buf)
1480            }
1481
1482            fn merge_field<__Buffer: ::autoproto::prost::bytes::Buf>(
1483                &mut self,
1484                tag: u32,
1485                wire_type: ::autoproto::prost::encoding::WireType,
1486                buf: &mut __Buffer,
1487                ctx: ::autoproto::prost::encoding::DecodeContext,
1488            ) -> Result<(), ::autoproto::prost::DecodeError> {
1489                ::autoproto::generic::protooneof::message_merge_field(self, tag, wire_type, buf, ctx)
1490            }
1491
1492            fn encoded_len(&self) -> usize {
1493                ::autoproto::generic::protooneof::message_encoded_len(self)
1494            }
1495
1496            fn clear(&mut self) {
1497                ::autoproto::generic::clear::message_clear(self)
1498            }
1499        }
1500    )
1501}
1502
1503fn impl_message_for_protostruct(
1504    ident: &Ident,
1505    impl_generics: &syn::ImplGenerics,
1506    ty_generics: &syn::TypeGenerics,
1507    where_clause: Option<&syn::WhereClause>,
1508) -> ItemImpl {
1509    syn::parse_quote!(
1510        impl #impl_generics ::autoproto::prost::Message for #ident #ty_generics #where_clause
1511        {
1512            fn encode_raw<__Buffer>(&self, buf: &mut __Buffer)
1513            where
1514                __Buffer: ::autoproto::prost::bytes::BufMut,
1515            {
1516                ::autoproto::generic::protostruct::message_encode_raw(self, buf)
1517            }
1518
1519            fn merge_field<__Buffer: ::autoproto::prost::bytes::Buf>(
1520                &mut self,
1521                tag: u32,
1522                wire_type: ::autoproto::prost::encoding::WireType,
1523                buf: &mut __Buffer,
1524                ctx: ::autoproto::prost::encoding::DecodeContext,
1525            ) -> Result<(), ::autoproto::prost::DecodeError> {
1526                ::autoproto::generic::protostruct::message_merge_field(self, tag, wire_type, buf, ctx)
1527            }
1528
1529            fn encoded_len(&self) -> usize {
1530                ::autoproto::generic::protostruct::message_encoded_len(self)
1531            }
1532
1533            fn clear(&mut self) {
1534                ::autoproto::generic::clear::message_clear(self)
1535            }
1536        }
1537    )
1538}
1539
1540fn impl_proto_for_protostruct(
1541    ident: &Ident,
1542    impl_generics: &syn::ImplGenerics,
1543    ty_generics: &syn::TypeGenerics,
1544    where_clause_builder: &mut WhereClauseBuilder,
1545) -> TokenStream2 {
1546    let protoencode_impl =
1547        impl_protoencode_for_protostruct(ident, impl_generics, ty_generics, where_clause_builder);
1548    let proto_where_clause = where_clause_builder.build().with_self_bound(quote!(
1549        ::autoproto::ProtoStructMut + ::autoproto::ProtoEncode + ::autoproto::Clear
1550    ));
1551
1552    quote!(
1553        impl #impl_generics ::autoproto::Proto for #ident #ty_generics #proto_where_clause
1554        {
1555            fn merge_self(
1556                &mut self,
1557                wire_type: ::autoproto::prost::encoding::WireType,
1558                mut buf: &mut dyn ::autoproto::prost::bytes::Buf,
1559                ctx: ::autoproto::prost::encoding::DecodeContext,
1560            ) -> Result<(), ::autoproto::prost::DecodeError> {
1561                ::autoproto::generic::protostruct::proto_merge_self(self, wire_type, &mut buf, ctx)
1562            }
1563        }
1564
1565        #protoencode_impl
1566    )
1567}
1568
1569fn impl_protoencode_for_protostruct(
1570    ident: &Ident,
1571    impl_generics: &syn::ImplGenerics,
1572    ty_generics: &syn::TypeGenerics,
1573    where_clause_builder: &mut WhereClauseBuilder,
1574) -> ItemImpl {
1575    let where_clause = where_clause_builder.with_self_bound(quote!(::autoproto::ProtoStruct));
1576
1577    syn::parse_quote!(
1578        impl #impl_generics ::autoproto::ProtoEncode for #ident #ty_generics #where_clause
1579        {
1580            fn encode_as_field(&self, tag: ::core::num::NonZeroU32, mut buf: &mut dyn ::autoproto::prost::bytes::BufMut) {
1581                ::autoproto::generic::protostruct::protoencode_encode_as_field(self, tag, buf)
1582            }
1583
1584            fn encoded_len_as_field(&self, tag: ::core::num::NonZeroU32) -> usize {
1585                ::autoproto::generic::protostruct::protoencode_encoded_len_as_field(self, tag)
1586            }
1587        }
1588    )
1589}
1590
1591fn unit_proto_impl(
1592    ident: &Ident,
1593    impl_generics: syn::ImplGenerics,
1594    ty_generics: syn::TypeGenerics,
1595    where_clause: Option<&syn::WhereClause>,
1596) -> TokenStream2 {
1597    quote!(
1598        impl #impl_generics ::autoproto::ProtoEncode for #ident #ty_generics #where_clause {
1599            fn encode_as_field(&self, tag: ::core::num::NonZeroU32, buf: &mut dyn prost::bytes::BufMut) {
1600                <() as ::autoproto::ProtoEncode>::encode_as_field(&(), tag, buf)
1601            }
1602
1603            fn encoded_len_as_field(&self, tag: ::core::num::NonZeroU32) -> usize {
1604                <() as ::autoproto::ProtoEncode>::encoded_len_as_field(&(), tag)
1605            }
1606        }
1607
1608        impl #impl_generics ::autoproto::Proto for #ident #ty_generics #where_clause {
1609            fn merge_self(
1610                &mut self,
1611                wire_type: ::autoproto::prost::encoding::WireType,
1612                buf: &mut dyn ::autoproto::prost::bytes::Buf,
1613                ctx: ::autoproto::prost::encoding::DecodeContext,
1614            ) -> Result<(), ::autoproto::prost::DecodeError> {
1615                <() as ::autoproto::Proto>::merge_self(&mut (), wire_type, buf, ctx)
1616            }
1617        }
1618
1619        impl #impl_generics ::autoproto::prost::Message for #ident #ty_generics #where_clause {
1620            fn encode_raw<__Buffer>(&self, buf: &mut __Buffer)
1621            where
1622                __Buffer: prost::bytes::BufMut,
1623            {
1624                <() as ::autoproto::prost::Message>::encode_raw(&(), buf)
1625            }
1626
1627            fn merge_field<__Buffer: prost::bytes::Buf>(
1628                &mut self,
1629                tag: u32,
1630                wire_type: ::autoproto::prost::encoding::WireType,
1631                buf: &mut __Buffer,
1632                ctx: ::autoproto::prost::encoding::DecodeContext,
1633            ) -> Result<(), ::autoproto::prost::DecodeError> {
1634                <() as ::autoproto::prost::Message>::merge_field(&mut (), tag, wire_type, buf, ctx)
1635            }
1636
1637            fn encoded_len(&self) -> usize {
1638                <() as ::autoproto::prost::Message>::encoded_len(&())
1639            }
1640
1641            fn clear(&mut self) {
1642                <() as ::autoproto::prost::Message>::clear(&mut ())
1643            }
1644        }
1645    )
1646}