prost_derive/field/
group.rs1use anyhow::{bail, Error};
2use proc_macro2::TokenStream;
3use quote::{quote, ToTokens};
4use syn::Meta;
5
6use crate::field::{set_bool, set_option, tag_attr, word_attr, Label};
7
8#[derive(Clone)]
9pub struct Field {
10 pub label: Label,
11 pub tag: u32,
12}
13
14impl Field {
15 pub fn new(attrs: &[Meta], inferred_tag: Option<u32>) -> Result<Option<Field>, Error> {
16 let mut group = false;
17 let mut label = None;
18 let mut tag = None;
19 let mut boxed = false;
20
21 let mut unknown_attrs = Vec::new();
22
23 for attr in attrs {
24 if word_attr("group", attr) {
25 set_bool(&mut group, "duplicate group attributes")?;
26 } else if word_attr("boxed", attr) {
27 set_bool(&mut boxed, "duplicate boxed attributes")?;
28 } else if let Some(t) = tag_attr(attr)? {
29 set_option(&mut tag, t, "duplicate tag attributes")?;
30 } else if let Some(l) = Label::from_attr(attr) {
31 set_option(&mut label, l, "duplicate label attributes")?;
32 } else {
33 unknown_attrs.push(attr);
34 }
35 }
36
37 if !group {
38 return Ok(None);
39 }
40
41 match unknown_attrs.len() {
42 0 => (),
43 1 => bail!("unknown attribute for group field: {:?}", unknown_attrs[0]),
44 _ => bail!("unknown attributes for group field: {:?}", unknown_attrs),
45 }
46
47 let tag = match tag.or(inferred_tag) {
48 Some(tag) => tag,
49 None => bail!("group field is missing a tag attribute"),
50 };
51
52 Ok(Some(Field {
53 label: label.unwrap_or(Label::Optional),
54 tag,
55 }))
56 }
57
58 pub fn new_oneof(attrs: &[Meta]) -> Result<Option<Field>, Error> {
59 if let Some(mut field) = Field::new(attrs, None)? {
60 if let Some(attr) = attrs.iter().find(|attr| Label::from_attr(attr).is_some()) {
61 bail!(
62 "invalid attribute for oneof field: {}",
63 attr.path().into_token_stream()
64 );
65 }
66 field.label = Label::Required;
67 Ok(Some(field))
68 } else {
69 Ok(None)
70 }
71 }
72
73 pub fn encode(&self, ident: TokenStream) -> TokenStream {
74 let tag = self.tag;
75 match self.label {
76 Label::Optional => quote! {
77 if let Some(ref msg) = #ident {
78 ::prost::encoding::group::encode(#tag, msg, buf);
79 }
80 },
81 Label::Required => quote! {
82 ::prost::encoding::group::encode(#tag, &#ident, buf);
83 },
84 Label::Repeated => quote! {
85 for msg in &#ident {
86 ::prost::encoding::group::encode(#tag, msg, buf);
87 }
88 },
89 }
90 }
91
92 pub fn merge(&self, ident: TokenStream) -> TokenStream {
93 match self.label {
94 Label::Optional => quote! {
95 ::prost::encoding::group::merge(
96 tag,
97 wire_type,
98 #ident.get_or_insert_with(::core::default::Default::default),
99 buf,
100 ctx,
101 )
102 },
103 Label::Required => quote! {
104 ::prost::encoding::group::merge(tag, wire_type, #ident, buf, ctx)
105 },
106 Label::Repeated => quote! {
107 ::prost::encoding::group::merge_repeated(tag, wire_type, #ident, buf, ctx)
108 },
109 }
110 }
111
112 pub fn encoded_len(&self, ident: TokenStream) -> TokenStream {
113 let tag = self.tag;
114 match self.label {
115 Label::Optional => quote! {
116 #ident.as_ref().map_or(0, |msg| ::prost::encoding::group::encoded_len(#tag, msg))
117 },
118 Label::Required => quote! {
119 ::prost::encoding::group::encoded_len(#tag, &#ident)
120 },
121 Label::Repeated => quote! {
122 ::prost::encoding::group::encoded_len_repeated(#tag, &#ident)
123 },
124 }
125 }
126
127 pub fn clear(&self, ident: TokenStream) -> TokenStream {
128 match self.label {
129 Label::Optional => quote!(#ident = ::core::option::Option::None),
130 Label::Required => quote!(#ident.clear()),
131 Label::Repeated => quote!(#ident.clear()),
132 }
133 }
134}