1mod group;
2mod map;
3mod message;
4mod oneof;
5mod scalar;
6
7use std::fmt;
8use std::slice;
9
10use anyhow::{bail, Error};
11use proc_macro2::TokenStream;
12use quote::quote;
13use syn::{Attribute, Ident, Lit, LitBool, Meta, MetaList, MetaNameValue, NestedMeta};
14
15#[derive(Clone)]
16pub enum Field {
17 Scalar(scalar::Field),
19 Message(message::Field),
21 Map(map::Field),
23 Oneof(oneof::Field),
25 Group(group::Field),
27}
28
29impl Field {
30 pub fn new(attrs: Vec<Attribute>, inferred_tag: Option<u32>) -> Result<Option<Field>, Error> {
35 let attrs = prost_attrs(attrs);
36
37 let field = if let Some(field) = scalar::Field::new(&attrs, inferred_tag)? {
40 Field::Scalar(field)
41 } else if let Some(field) = message::Field::new(&attrs, inferred_tag)? {
42 Field::Message(field)
43 } else if let Some(field) = map::Field::new(&attrs, inferred_tag)? {
44 Field::Map(field)
45 } else if let Some(field) = oneof::Field::new(&attrs)? {
46 Field::Oneof(field)
47 } else if let Some(field) = group::Field::new(&attrs, inferred_tag)? {
48 Field::Group(field)
49 } else {
50 bail!("no type attribute");
51 };
52
53 Ok(Some(field))
54 }
55
56 pub fn new_oneof(attrs: Vec<Attribute>) -> Result<Option<Field>, Error> {
61 let attrs = prost_attrs(attrs);
62
63 let field = if let Some(field) = scalar::Field::new_oneof(&attrs)? {
66 Field::Scalar(field)
67 } else if let Some(field) = message::Field::new_oneof(&attrs)? {
68 Field::Message(field)
69 } else if let Some(field) = map::Field::new_oneof(&attrs)? {
70 Field::Map(field)
71 } else if let Some(field) = group::Field::new_oneof(&attrs)? {
72 Field::Group(field)
73 } else {
74 bail!("no type attribute for oneof field");
75 };
76
77 Ok(Some(field))
78 }
79
80 pub fn tags(&self) -> Vec<u32> {
81 match *self {
82 Field::Scalar(ref scalar) => vec![scalar.tag],
83 Field::Message(ref message) => vec![message.tag],
84 Field::Map(ref map) => vec![map.tag],
85 Field::Oneof(ref oneof) => oneof.tags.clone(),
86 Field::Group(ref group) => vec![group.tag],
87 }
88 }
89
90 pub fn encode(&self, ident: TokenStream) -> TokenStream {
92 match *self {
93 Field::Scalar(ref scalar) => scalar.encode(ident),
94 Field::Message(ref message) => message.encode(ident),
95 Field::Map(ref map) => map.encode(ident),
96 Field::Oneof(ref oneof) => oneof.encode(ident),
97 Field::Group(ref group) => group.encode(ident),
98 }
99 }
100
101 pub fn merge(&self, ident: TokenStream) -> TokenStream {
104 match *self {
105 Field::Scalar(ref scalar) => scalar.merge(ident),
106 Field::Message(ref message) => message.merge(ident),
107 Field::Map(ref map) => map.merge(ident),
108 Field::Oneof(ref oneof) => oneof.merge(ident),
109 Field::Group(ref group) => group.merge(ident),
110 }
111 }
112
113 pub fn encoded_len(&self, ident: TokenStream) -> TokenStream {
115 match *self {
116 Field::Scalar(ref scalar) => scalar.encoded_len(ident),
117 Field::Map(ref map) => map.encoded_len(ident),
118 Field::Message(ref msg) => msg.encoded_len(ident),
119 Field::Oneof(ref oneof) => oneof.encoded_len(ident),
120 Field::Group(ref group) => group.encoded_len(ident),
121 }
122 }
123
124 pub fn clear(&self, ident: TokenStream) -> TokenStream {
126 match *self {
127 Field::Scalar(ref scalar) => scalar.clear(ident),
128 Field::Message(ref message) => message.clear(ident),
129 Field::Map(ref map) => map.clear(ident),
130 Field::Oneof(ref oneof) => oneof.clear(ident),
131 Field::Group(ref group) => group.clear(ident),
132 }
133 }
134
135 pub fn default(&self) -> TokenStream {
136 match *self {
137 Field::Scalar(ref scalar) => scalar.default(),
138 _ => quote!(::core::default::Default::default()),
139 }
140 }
141
142 pub fn debug(&self, ident: TokenStream) -> TokenStream {
144 match *self {
145 Field::Scalar(ref scalar) => {
146 let wrapper = scalar.debug(quote!(ScalarWrapper));
147 quote! {
148 {
149 #wrapper
150 ScalarWrapper(&#ident)
151 }
152 }
153 }
154 Field::Map(ref map) => {
155 let wrapper = map.debug(quote!(MapWrapper));
156 quote! {
157 {
158 #wrapper
159 MapWrapper(&#ident)
160 }
161 }
162 }
163 _ => quote!(&#ident),
164 }
165 }
166
167 pub fn methods(&self, ident: &Ident) -> Option<TokenStream> {
168 match *self {
169 Field::Scalar(ref scalar) => scalar.methods(ident),
170 Field::Map(ref map) => map.methods(ident),
171 _ => None,
172 }
173 }
174}
175
176#[derive(Clone, Copy, PartialEq, Eq)]
177pub enum Label {
178 Optional,
180 Required,
182 Repeated,
184}
185
186impl Label {
187 fn as_str(self) -> &'static str {
188 match self {
189 Label::Optional => "optional",
190 Label::Required => "required",
191 Label::Repeated => "repeated",
192 }
193 }
194
195 fn variants() -> slice::Iter<'static, Label> {
196 const VARIANTS: &[Label] = &[Label::Optional, Label::Required, Label::Repeated];
197 VARIANTS.iter()
198 }
199
200 fn from_attr(attr: &Meta) -> Option<Label> {
203 if let Meta::Path(ref path) = *attr {
204 for &label in Label::variants() {
205 if path.is_ident(label.as_str()) {
206 return Some(label);
207 }
208 }
209 }
210 None
211 }
212}
213
214impl fmt::Debug for Label {
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 f.write_str(self.as_str())
217 }
218}
219
220impl fmt::Display for Label {
221 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222 f.write_str(self.as_str())
223 }
224}
225
226fn prost_attrs(attrs: Vec<Attribute>) -> Vec<Meta> {
228 attrs
229 .iter()
230 .flat_map(Attribute::parse_meta)
231 .flat_map(|meta| match meta {
232 Meta::List(MetaList { path, nested, .. }) => {
233 if path.is_ident("prost") {
234 nested.into_iter().collect()
235 } else {
236 Vec::new()
237 }
238 }
239 _ => Vec::new(),
240 })
241 .flat_map(|attr| -> Result<_, _> {
242 match attr {
243 NestedMeta::Meta(attr) => Ok(attr),
244 NestedMeta::Lit(lit) => bail!("invalid prost attribute: {:?}", lit),
245 }
246 })
247 .collect()
248}
249
250pub fn set_option<T>(option: &mut Option<T>, value: T, message: &str) -> Result<(), Error>
251where
252 T: fmt::Debug,
253{
254 if let Some(ref existing) = *option {
255 bail!("{}: {:?} and {:?}", message, existing, value);
256 }
257 *option = Some(value);
258 Ok(())
259}
260
261pub fn set_bool(b: &mut bool, message: &str) -> Result<(), Error> {
262 if *b {
263 bail!("{}", message);
264 } else {
265 *b = true;
266 Ok(())
267 }
268}
269
270fn bool_attr(key: &str, attr: &Meta) -> Result<Option<bool>, Error> {
273 if !attr.path().is_ident(key) {
274 return Ok(None);
275 }
276 match *attr {
277 Meta::Path(..) => Ok(Some(true)),
278 Meta::List(ref meta_list) => {
279 if meta_list.nested.len() == 1 {
281 if let NestedMeta::Lit(Lit::Bool(LitBool { value, .. })) = meta_list.nested[0] {
282 return Ok(Some(value));
283 }
284 }
285 bail!("invalid {} attribute", key);
286 }
287 Meta::NameValue(MetaNameValue {
288 lit: Lit::Str(ref lit),
289 ..
290 }) => lit
291 .value()
292 .parse::<bool>()
293 .map_err(Error::from)
294 .map(Option::Some),
295 Meta::NameValue(MetaNameValue {
296 lit: Lit::Bool(LitBool { value, .. }),
297 ..
298 }) => Ok(Some(value)),
299 _ => bail!("invalid {} attribute", key),
300 }
301}
302
303fn word_attr(key: &str, attr: &Meta) -> bool {
305 if let Meta::Path(ref path) = *attr {
306 path.is_ident(key)
307 } else {
308 false
309 }
310}
311
312pub(super) fn tag_attr(attr: &Meta) -> Result<Option<u32>, Error> {
313 if !attr.path().is_ident("tag") {
314 return Ok(None);
315 }
316 match *attr {
317 Meta::List(ref meta_list) => {
318 if meta_list.nested.len() == 1 {
320 if let NestedMeta::Lit(Lit::Int(ref lit)) = meta_list.nested[0] {
321 return Ok(Some(lit.base10_parse()?));
322 }
323 }
324 bail!("invalid tag attribute: {:?}", attr);
325 }
326 Meta::NameValue(ref meta_name_value) => match meta_name_value.lit {
327 Lit::Str(ref lit) => lit
328 .value()
329 .parse::<u32>()
330 .map_err(Error::from)
331 .map(Option::Some),
332 Lit::Int(ref lit) => Ok(Some(lit.base10_parse()?)),
333 _ => bail!("invalid tag attribute: {:?}", attr),
334 },
335 _ => bail!("invalid tag attribute: {:?}", attr),
336 }
337}
338
339fn tags_attr(attr: &Meta) -> Result<Option<Vec<u32>>, Error> {
340 if !attr.path().is_ident("tags") {
341 return Ok(None);
342 }
343 match *attr {
344 Meta::List(ref meta_list) => {
345 let mut tags = Vec::with_capacity(meta_list.nested.len());
346 for item in &meta_list.nested {
347 if let NestedMeta::Lit(Lit::Int(ref lit)) = *item {
348 tags.push(lit.base10_parse()?);
349 } else {
350 bail!("invalid tag attribute: {:?}", attr);
351 }
352 }
353 Ok(Some(tags))
354 }
355 Meta::NameValue(MetaNameValue {
356 lit: Lit::Str(ref lit),
357 ..
358 }) => lit
359 .value()
360 .split(',')
361 .map(|s| s.trim().parse::<u32>().map_err(Error::from))
362 .collect::<Result<Vec<u32>, _>>()
363 .map(Some),
364 _ => bail!("invalid tag attribute: {:?}", attr),
365 }
366}