1 use anyhow::{bail, Error}; 2 use proc_macro2::TokenStream; 3 use quote::{quote, ToTokens}; 4 use syn::Meta; 5 6 use crate::field::{set_bool, set_option, tag_attr, word_attr, Label}; 7 8 #[derive(Clone)] 9 pub struct Field { 10 pub label: Label, 11 pub tag: u32, 12 } 13 14 impl Field { new(attrs: &[Meta], inferred_tag: Option<u32>) -> Result<Option<Field>, Error>15 pub fn new(attrs: &[Meta], inferred_tag: Option<u32>) -> Result<Option<Field>, Error> { 16 let mut message = 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("message", attr) { 25 set_bool(&mut message, "duplicate message attribute")?; 26 } else if word_attr("boxed", attr) { 27 set_bool(&mut boxed, "duplicate boxed attribute")?; 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 !message { 38 return Ok(None); 39 } 40 41 match unknown_attrs.len() { 42 0 => (), 43 1 => bail!( 44 "unknown attribute for message field: {:?}", 45 unknown_attrs[0] 46 ), 47 _ => bail!("unknown attributes for message field: {:?}", unknown_attrs), 48 } 49 50 let tag = match tag.or(inferred_tag) { 51 Some(tag) => tag, 52 None => bail!("message field is missing a tag attribute"), 53 }; 54 55 Ok(Some(Field { 56 label: label.unwrap_or(Label::Optional), 57 tag, 58 })) 59 } 60 new_oneof(attrs: &[Meta]) -> Result<Option<Field>, Error>61 pub fn new_oneof(attrs: &[Meta]) -> Result<Option<Field>, Error> { 62 if let Some(mut field) = Field::new(attrs, None)? { 63 if let Some(attr) = attrs.iter().find(|attr| Label::from_attr(attr).is_some()) { 64 bail!( 65 "invalid attribute for oneof field: {}", 66 attr.path().into_token_stream() 67 ); 68 } 69 field.label = Label::Required; 70 Ok(Some(field)) 71 } else { 72 Ok(None) 73 } 74 } 75 encode(&self, ident: TokenStream) -> TokenStream76 pub fn encode(&self, ident: TokenStream) -> TokenStream { 77 let tag = self.tag; 78 match self.label { 79 Label::Optional => quote! { 80 if let Some(ref msg) = #ident { 81 ::prost::encoding::message::encode(#tag, msg, buf); 82 } 83 }, 84 Label::Required => quote! { 85 ::prost::encoding::message::encode(#tag, &#ident, buf); 86 }, 87 Label::Repeated => quote! { 88 for msg in &#ident { 89 ::prost::encoding::message::encode(#tag, msg, buf); 90 } 91 }, 92 } 93 } 94 merge(&self, ident: TokenStream) -> TokenStream95 pub fn merge(&self, ident: TokenStream) -> TokenStream { 96 match self.label { 97 Label::Optional => quote! { 98 ::prost::encoding::message::merge(wire_type, 99 #ident.get_or_insert_with(::core::default::Default::default), 100 buf, 101 ctx) 102 }, 103 Label::Required => quote! { 104 ::prost::encoding::message::merge(wire_type, #ident, buf, ctx) 105 }, 106 Label::Repeated => quote! { 107 ::prost::encoding::message::merge_repeated(wire_type, #ident, buf, ctx) 108 }, 109 } 110 } 111 encoded_len(&self, ident: TokenStream) -> TokenStream112 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::message::encoded_len(#tag, msg)) 117 }, 118 Label::Required => quote! { 119 ::prost::encoding::message::encoded_len(#tag, &#ident) 120 }, 121 Label::Repeated => quote! { 122 ::prost::encoding::message::encoded_len_repeated(#tag, &#ident) 123 }, 124 } 125 } 126 clear(&self, ident: TokenStream) -> TokenStream127 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 } 135