1use std::fmt;
2
3use anyhow::{anyhow, bail, Error};
4use proc_macro2::{Span, TokenStream};
5use quote::{quote, ToTokens, TokenStreamExt};
6use syn::{parse_str, Expr, ExprLit, Ident, Index, Lit, LitByteStr, Meta, MetaNameValue, Path};
7
8use crate::field::{bool_attr, set_option, tag_attr, Label};
9
10#[derive(Clone)]
12pub struct Field {
13 pub ty: Ty,
14 pub kind: Kind,
15 pub tag: u32,
16}
17
18impl Field {
19 pub fn new(attrs: &[Meta], inferred_tag: Option<u32>) -> Result<Option<Field>, Error> {
20 let mut ty = None;
21 let mut label = None;
22 let mut packed = None;
23 let mut default = None;
24 let mut tag = None;
25
26 let mut unknown_attrs = Vec::new();
27
28 for attr in attrs {
29 if let Some(t) = Ty::from_attr(attr)? {
30 set_option(&mut ty, t, "duplicate type attributes")?;
31 } else if let Some(p) = bool_attr("packed", attr)? {
32 set_option(&mut packed, p, "duplicate packed attributes")?;
33 } else if let Some(t) = tag_attr(attr)? {
34 set_option(&mut tag, t, "duplicate tag attributes")?;
35 } else if let Some(l) = Label::from_attr(attr) {
36 set_option(&mut label, l, "duplicate label attributes")?;
37 } else if let Some(d) = DefaultValue::from_attr(attr)? {
38 set_option(&mut default, d, "duplicate default attributes")?;
39 } else {
40 unknown_attrs.push(attr);
41 }
42 }
43
44 let ty = match ty {
45 Some(ty) => ty,
46 None => return Ok(None),
47 };
48
49 if !unknown_attrs.is_empty() {
50 bail!(
51 "unknown attribute(s): #[prost({})]",
52 quote!(#(#unknown_attrs),*)
53 );
54 }
55
56 let tag = match tag.or(inferred_tag) {
57 Some(tag) => tag,
58 None => bail!("missing tag attribute"),
59 };
60
61 let has_default = default.is_some();
62 let default = default.map_or_else(
63 || Ok(DefaultValue::new(&ty)),
64 |lit| DefaultValue::from_lit(&ty, lit),
65 )?;
66
67 let kind = match (label, packed, has_default) {
68 (None, Some(true), _)
69 | (Some(Label::Optional), Some(true), _)
70 | (Some(Label::Required), Some(true), _) => {
71 bail!("packed attribute may only be applied to repeated fields");
72 }
73 (Some(Label::Repeated), Some(true), _) if !ty.is_numeric() => {
74 bail!("packed attribute may only be applied to numeric types");
75 }
76 (Some(Label::Repeated), _, true) => {
77 bail!("repeated fields may not have a default value");
78 }
79
80 (None, _, _) => Kind::Plain(default),
81 (Some(Label::Optional), _, _) => Kind::Optional(default),
82 (Some(Label::Required), _, _) => Kind::Required(default),
83 (Some(Label::Repeated), packed, false) if packed.unwrap_or_else(|| ty.is_numeric()) => {
84 Kind::Packed
85 }
86 (Some(Label::Repeated), _, false) => Kind::Repeated,
87 };
88
89 Ok(Some(Field { ty, kind, tag }))
90 }
91
92 pub fn new_oneof(attrs: &[Meta]) -> Result<Option<Field>, Error> {
93 if let Some(mut field) = Field::new(attrs, None)? {
94 match field.kind {
95 Kind::Plain(default) => {
96 field.kind = Kind::Required(default);
97 Ok(Some(field))
98 }
99 Kind::Optional(..) => bail!("invalid optional attribute on oneof field"),
100 Kind::Required(..) => bail!("invalid required attribute on oneof field"),
101 Kind::Packed | Kind::Repeated => bail!("invalid repeated attribute on oneof field"),
102 }
103 } else {
104 Ok(None)
105 }
106 }
107
108 pub fn encode(&self, prost_path: &Path, ident: TokenStream) -> TokenStream {
109 let module = self.ty.module();
110 let encode_fn = match self.kind {
111 Kind::Plain(..) | Kind::Optional(..) | Kind::Required(..) => quote!(encode),
112 Kind::Repeated => quote!(encode_repeated),
113 Kind::Packed => quote!(encode_packed),
114 };
115 let encode_fn = quote!(#prost_path::encoding::#module::#encode_fn);
116 let tag = self.tag;
117
118 match self.kind {
119 Kind::Plain(ref default) => {
120 let default = default.typed();
121 quote! {
122 if #ident != #default {
123 #encode_fn(#tag, &#ident, buf);
124 }
125 }
126 }
127 Kind::Optional(..) => quote! {
128 if let ::core::option::Option::Some(ref value) = #ident {
129 #encode_fn(#tag, value, buf);
130 }
131 },
132 Kind::Required(..) | Kind::Repeated | Kind::Packed => quote! {
133 #encode_fn(#tag, &#ident, buf);
134 },
135 }
136 }
137
138 pub fn merge(&self, prost_path: &Path, ident: TokenStream) -> TokenStream {
141 let module = self.ty.module();
142 let merge_fn = match self.kind {
143 Kind::Plain(..) | Kind::Optional(..) | Kind::Required(..) => quote!(merge),
144 Kind::Repeated | Kind::Packed => quote!(merge_repeated),
145 };
146 let merge_fn = quote!(#prost_path::encoding::#module::#merge_fn);
147
148 match self.kind {
149 Kind::Plain(..) | Kind::Required(..) | Kind::Repeated | Kind::Packed => quote! {
150 #merge_fn(wire_type, #ident, buf, ctx)
151 },
152 Kind::Optional(..) => quote! {
153 #merge_fn(wire_type,
154 #ident.get_or_insert_with(::core::default::Default::default),
155 buf,
156 ctx)
157 },
158 }
159 }
160
161 pub fn encoded_len(&self, prost_path: &Path, ident: TokenStream) -> TokenStream {
163 let module = self.ty.module();
164 let encoded_len_fn = match self.kind {
165 Kind::Plain(..) | Kind::Optional(..) | Kind::Required(..) => quote!(encoded_len),
166 Kind::Repeated => quote!(encoded_len_repeated),
167 Kind::Packed => quote!(encoded_len_packed),
168 };
169 let encoded_len_fn = quote!(#prost_path::encoding::#module::#encoded_len_fn);
170 let tag = self.tag;
171
172 match self.kind {
173 Kind::Plain(ref default) => {
174 let default = default.typed();
175 quote! {
176 if #ident != #default {
177 #encoded_len_fn(#tag, &#ident)
178 } else {
179 0
180 }
181 }
182 }
183 Kind::Optional(..) => quote! {
184 #ident.as_ref().map_or(0, |value| #encoded_len_fn(#tag, value))
185 },
186 Kind::Required(..) | Kind::Repeated | Kind::Packed => quote! {
187 #encoded_len_fn(#tag, &#ident)
188 },
189 }
190 }
191
192 pub fn clear(&self, ident: TokenStream) -> TokenStream {
193 match self.kind {
194 Kind::Plain(ref default) | Kind::Required(ref default) => {
195 let default = default.typed();
196 match self.ty {
197 Ty::String | Ty::Bytes(..) => quote!(#ident.clear()),
198 _ => quote!(#ident = #default),
199 }
200 }
201 Kind::Optional(_) => quote!(#ident = ::core::option::Option::None),
202 Kind::Repeated | Kind::Packed => quote!(#ident.clear()),
203 }
204 }
205
206 pub fn default(&self, prost_path: &Path) -> TokenStream {
208 match self.kind {
209 Kind::Plain(ref value) | Kind::Required(ref value) => value.owned(prost_path),
210 Kind::Optional(_) => quote!(::core::option::Option::None),
211 Kind::Repeated | Kind::Packed => quote!(#prost_path::alloc::vec::Vec::new()),
212 }
213 }
214
215 fn debug_inner(&self, wrap_name: TokenStream) -> TokenStream {
217 if let Ty::Enumeration(ref ty) = self.ty {
218 quote! {
219 struct #wrap_name<'a>(&'a i32);
220 impl<'a> ::core::fmt::Debug for #wrap_name<'a> {
221 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
222 let res: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(*self.0);
223 match res {
224 Err(_) => ::core::fmt::Debug::fmt(&self.0, f),
225 Ok(en) => ::core::fmt::Debug::fmt(&en, f),
226 }
227 }
228 }
229 }
230 } else {
231 quote! {
232 #[allow(non_snake_case)]
233 fn #wrap_name<T>(v: T) -> T { v }
234 }
235 }
236 }
237
238 pub fn debug(&self, prost_path: &Path, wrapper_name: TokenStream) -> TokenStream {
240 let wrapper = self.debug_inner(quote!(Inner));
241 let inner_ty = self.ty.rust_type(prost_path);
242 match self.kind {
243 Kind::Plain(_) | Kind::Required(_) => self.debug_inner(wrapper_name),
244 Kind::Optional(_) => quote! {
245 struct #wrapper_name<'a>(&'a ::core::option::Option<#inner_ty>);
246 impl<'a> ::core::fmt::Debug for #wrapper_name<'a> {
247 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
248 #wrapper
249 ::core::fmt::Debug::fmt(&self.0.as_ref().map(Inner), f)
250 }
251 }
252 },
253 Kind::Repeated | Kind::Packed => {
254 quote! {
255 struct #wrapper_name<'a>(&'a #prost_path::alloc::vec::Vec<#inner_ty>);
256 impl<'a> ::core::fmt::Debug for #wrapper_name<'a> {
257 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
258 let mut vec_builder = f.debug_list();
259 for v in self.0 {
260 #wrapper
261 vec_builder.entry(&Inner(v));
262 }
263 vec_builder.finish()
264 }
265 }
266 }
267 }
268 }
269 }
270
271 pub fn methods(&self, ident: &TokenStream) -> Option<TokenStream> {
273 let mut ident_str = ident.to_string();
274 if ident_str.starts_with("r#") {
275 ident_str = ident_str.split_off(2);
276 }
277
278 let get = match syn::parse_str::<Index>(&ident_str) {
280 Ok(index) => {
281 let get = Ident::new(&format!("get_{}", index.index), Span::call_site());
282 quote!(#get)
283 }
284 Err(_) => quote!(#ident),
285 };
286
287 if let Ty::Enumeration(ref ty) = self.ty {
288 let set = Ident::new(&format!("set_{ident_str}"), Span::call_site());
289 let set_doc = format!("Sets `{ident_str}` to the provided enum value.");
290 Some(match self.kind {
291 Kind::Plain(ref default) | Kind::Required(ref default) => {
292 let get_doc = format!(
293 "Returns the enum value of `{ident_str}`, \
294 or the default if the field is set to an invalid enum value."
295 );
296 quote! {
297 #[doc=#get_doc]
298 pub fn #get(&self) -> #ty {
299 ::core::convert::TryFrom::try_from(self.#ident).unwrap_or(#default)
300 }
301
302 #[doc=#set_doc]
303 pub fn #set(&mut self, value: #ty) {
304 self.#ident = value as i32;
305 }
306 }
307 }
308 Kind::Optional(ref default) => {
309 let get_doc = format!(
310 "Returns the enum value of `{ident_str}`, \
311 or the default if the field is unset or set to an invalid enum value."
312 );
313 quote! {
314 #[doc=#get_doc]
315 pub fn #get(&self) -> #ty {
316 self.#ident.and_then(|x| {
317 let result: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
318 result.ok()
319 }).unwrap_or(#default)
320 }
321
322 #[doc=#set_doc]
323 pub fn #set(&mut self, value: #ty) {
324 self.#ident = ::core::option::Option::Some(value as i32);
325 }
326 }
327 }
328 Kind::Repeated | Kind::Packed => {
329 let iter_doc = format!(
330 "Returns an iterator which yields the valid enum values contained in `{ident_str}`."
331 );
332 let push = Ident::new(&format!("push_{ident_str}"), Span::call_site());
333 let push_doc = format!("Appends the provided enum value to `{ident_str}`.");
334 quote! {
335 #[doc=#iter_doc]
336 pub fn #get(&self) -> ::core::iter::FilterMap<
337 ::core::iter::Cloned<::core::slice::Iter<i32>>,
338 fn(i32) -> ::core::option::Option<#ty>,
339 > {
340 self.#ident.iter().cloned().filter_map(|x| {
341 let result: ::core::result::Result<#ty, _> = ::core::convert::TryFrom::try_from(x);
342 result.ok()
343 })
344 }
345 #[doc=#push_doc]
346 pub fn #push(&mut self, value: #ty) {
347 self.#ident.push(value as i32);
348 }
349 }
350 }
351 })
352 } else if let Kind::Optional(ref default) = self.kind {
353 let ty = self.ty.rust_ref_type();
354
355 let match_some = if self.ty.is_numeric() {
356 quote!(::core::option::Option::Some(val) => val,)
357 } else {
358 quote!(::core::option::Option::Some(ref val) => &val[..],)
359 };
360
361 let get_doc = format!(
362 "Returns the value of `{ident_str}`, or the default value if `{ident_str}` is unset."
363 );
364
365 Some(quote! {
366 #[doc=#get_doc]
367 pub fn #get(&self) -> #ty {
368 match self.#ident {
369 #match_some
370 ::core::option::Option::None => #default,
371 }
372 }
373 })
374 } else {
375 None
376 }
377 }
378}
379
380#[derive(Clone, PartialEq, Eq)]
382pub enum Ty {
383 Double,
384 Float,
385 Int32,
386 Int64,
387 Uint32,
388 Uint64,
389 Sint32,
390 Sint64,
391 Fixed32,
392 Fixed64,
393 Sfixed32,
394 Sfixed64,
395 Bool,
396 String,
397 Bytes(BytesTy),
398 Enumeration(Path),
399}
400
401#[derive(Clone, Debug, PartialEq, Eq)]
402pub enum BytesTy {
403 Vec,
404 Bytes,
405}
406
407impl BytesTy {
408 fn try_from_str(s: &str) -> Result<Self, Error> {
409 match s {
410 "vec" => Ok(BytesTy::Vec),
411 "bytes" => Ok(BytesTy::Bytes),
412 _ => bail!("Invalid bytes type: {s}"),
413 }
414 }
415
416 fn rust_type(&self, prost_path: &Path) -> TokenStream {
417 match self {
418 BytesTy::Vec => quote! { #prost_path::alloc::vec::Vec<u8> },
419 BytesTy::Bytes => quote! { #prost_path::bytes::Bytes },
420 }
421 }
422}
423
424impl Ty {
425 pub fn from_attr(attr: &Meta) -> Result<Option<Ty>, Error> {
426 let ty = match *attr {
427 Meta::Path(ref name) if name.is_ident("float") => Ty::Float,
428 Meta::Path(ref name) if name.is_ident("double") => Ty::Double,
429 Meta::Path(ref name) if name.is_ident("int32") => Ty::Int32,
430 Meta::Path(ref name) if name.is_ident("int64") => Ty::Int64,
431 Meta::Path(ref name) if name.is_ident("uint32") => Ty::Uint32,
432 Meta::Path(ref name) if name.is_ident("uint64") => Ty::Uint64,
433 Meta::Path(ref name) if name.is_ident("sint32") => Ty::Sint32,
434 Meta::Path(ref name) if name.is_ident("sint64") => Ty::Sint64,
435 Meta::Path(ref name) if name.is_ident("fixed32") => Ty::Fixed32,
436 Meta::Path(ref name) if name.is_ident("fixed64") => Ty::Fixed64,
437 Meta::Path(ref name) if name.is_ident("sfixed32") => Ty::Sfixed32,
438 Meta::Path(ref name) if name.is_ident("sfixed64") => Ty::Sfixed64,
439 Meta::Path(ref name) if name.is_ident("bool") => Ty::Bool,
440 Meta::Path(ref name) if name.is_ident("string") => Ty::String,
441 Meta::Path(ref name) if name.is_ident("bytes") => Ty::Bytes(BytesTy::Vec),
442 Meta::NameValue(MetaNameValue {
443 ref path,
444 value:
445 Expr::Lit(ExprLit {
446 lit: Lit::Str(ref l),
447 ..
448 }),
449 ..
450 }) if path.is_ident("bytes") => Ty::Bytes(BytesTy::try_from_str(&l.value())?),
451 Meta::NameValue(MetaNameValue {
452 ref path,
453 value:
454 Expr::Lit(ExprLit {
455 lit: Lit::Str(ref l),
456 ..
457 }),
458 ..
459 }) if path.is_ident("enumeration") => Ty::Enumeration(parse_str::<Path>(&l.value())?),
460 Meta::List(ref meta_list) if meta_list.path.is_ident("enumeration") => {
461 Ty::Enumeration(meta_list.parse_args::<Path>()?)
462 }
463 _ => return Ok(None),
464 };
465 Ok(Some(ty))
466 }
467
468 pub fn from_str(s: &str) -> Result<Ty, Error> {
469 let enumeration_len = "enumeration".len();
470 let error = Err(anyhow!("invalid type: {s}"));
471 let ty = match s.trim() {
472 "float" => Ty::Float,
473 "double" => Ty::Double,
474 "int32" => Ty::Int32,
475 "int64" => Ty::Int64,
476 "uint32" => Ty::Uint32,
477 "uint64" => Ty::Uint64,
478 "sint32" => Ty::Sint32,
479 "sint64" => Ty::Sint64,
480 "fixed32" => Ty::Fixed32,
481 "fixed64" => Ty::Fixed64,
482 "sfixed32" => Ty::Sfixed32,
483 "sfixed64" => Ty::Sfixed64,
484 "bool" => Ty::Bool,
485 "string" => Ty::String,
486 "bytes" => Ty::Bytes(BytesTy::Vec),
487 s if s.len() > enumeration_len && &s[..enumeration_len] == "enumeration" => {
488 let s = &s[enumeration_len..].trim();
489 match s.chars().next() {
490 Some('<') | Some('(') => (),
491 _ => return error,
492 }
493 match s.chars().next_back() {
494 Some('>') | Some(')') => (),
495 _ => return error,
496 }
497
498 Ty::Enumeration(parse_str::<Path>(s[1..s.len() - 1].trim())?)
499 }
500 _ => return error,
501 };
502 Ok(ty)
503 }
504
505 pub fn as_str(&self) -> &'static str {
507 match *self {
508 Ty::Double => "double",
509 Ty::Float => "float",
510 Ty::Int32 => "int32",
511 Ty::Int64 => "int64",
512 Ty::Uint32 => "uint32",
513 Ty::Uint64 => "uint64",
514 Ty::Sint32 => "sint32",
515 Ty::Sint64 => "sint64",
516 Ty::Fixed32 => "fixed32",
517 Ty::Fixed64 => "fixed64",
518 Ty::Sfixed32 => "sfixed32",
519 Ty::Sfixed64 => "sfixed64",
520 Ty::Bool => "bool",
521 Ty::String => "string",
522 Ty::Bytes(..) => "bytes",
523 Ty::Enumeration(..) => "enum",
524 }
525 }
526
527 pub fn rust_type(&self, prost_path: &Path) -> TokenStream {
529 match self {
530 Ty::String => quote!(#prost_path::alloc::string::String),
531 Ty::Bytes(ty) => ty.rust_type(prost_path),
532 _ => self.rust_ref_type(),
533 }
534 }
535
536 pub fn rust_ref_type(&self) -> TokenStream {
538 match *self {
539 Ty::Double => quote!(f64),
540 Ty::Float => quote!(f32),
541 Ty::Int32 => quote!(i32),
542 Ty::Int64 => quote!(i64),
543 Ty::Uint32 => quote!(u32),
544 Ty::Uint64 => quote!(u64),
545 Ty::Sint32 => quote!(i32),
546 Ty::Sint64 => quote!(i64),
547 Ty::Fixed32 => quote!(u32),
548 Ty::Fixed64 => quote!(u64),
549 Ty::Sfixed32 => quote!(i32),
550 Ty::Sfixed64 => quote!(i64),
551 Ty::Bool => quote!(bool),
552 Ty::String => quote!(&str),
553 Ty::Bytes(..) => quote!(&[u8]),
554 Ty::Enumeration(..) => quote!(i32),
555 }
556 }
557
558 pub fn module(&self) -> Ident {
559 match *self {
560 Ty::Enumeration(..) => Ident::new("int32", Span::call_site()),
561 _ => Ident::new(self.as_str(), Span::call_site()),
562 }
563 }
564
565 pub fn is_numeric(&self) -> bool {
567 !matches!(self, Ty::String | Ty::Bytes(..))
568 }
569}
570
571impl fmt::Debug for Ty {
572 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573 f.write_str(self.as_str())
574 }
575}
576
577impl fmt::Display for Ty {
578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579 f.write_str(self.as_str())
580 }
581}
582
583#[derive(Clone)]
585pub enum Kind {
586 Plain(DefaultValue),
588 Optional(DefaultValue),
590 Required(DefaultValue),
592 Repeated,
594 Packed,
596}
597
598#[derive(Clone, Debug)]
600pub enum DefaultValue {
601 F64(f64),
602 F32(f32),
603 I32(i32),
604 I64(i64),
605 U32(u32),
606 U64(u64),
607 Bool(bool),
608 String(String),
609 Bytes(Vec<u8>),
610 Enumeration(TokenStream),
611 Path(Path),
612}
613
614impl DefaultValue {
615 pub fn from_attr(attr: &Meta) -> Result<Option<Lit>, Error> {
616 if !attr.path().is_ident("default") {
617 Ok(None)
618 } else if let Meta::NameValue(MetaNameValue {
619 value: Expr::Lit(ExprLit { ref lit, .. }),
620 ..
621 }) = *attr
622 {
623 Ok(Some(lit.clone()))
624 } else {
625 bail!("invalid default value attribute: {attr:?}")
626 }
627 }
628
629 pub fn from_lit(ty: &Ty, lit: Lit) -> Result<DefaultValue, Error> {
630 let is_i32 = *ty == Ty::Int32 || *ty == Ty::Sint32 || *ty == Ty::Sfixed32;
631 let is_i64 = *ty == Ty::Int64 || *ty == Ty::Sint64 || *ty == Ty::Sfixed64;
632
633 let is_u32 = *ty == Ty::Uint32 || *ty == Ty::Fixed32;
634 let is_u64 = *ty == Ty::Uint64 || *ty == Ty::Fixed64;
635
636 let empty_or_is = |expected, actual: &str| expected == actual || actual.is_empty();
637
638 let default = match lit {
639 Lit::Int(ref lit) if is_i32 && empty_or_is("i32", lit.suffix()) => {
640 DefaultValue::I32(lit.base10_parse()?)
641 }
642 Lit::Int(ref lit) if is_i64 && empty_or_is("i64", lit.suffix()) => {
643 DefaultValue::I64(lit.base10_parse()?)
644 }
645 Lit::Int(ref lit) if is_u32 && empty_or_is("u32", lit.suffix()) => {
646 DefaultValue::U32(lit.base10_parse()?)
647 }
648 Lit::Int(ref lit) if is_u64 && empty_or_is("u64", lit.suffix()) => {
649 DefaultValue::U64(lit.base10_parse()?)
650 }
651
652 Lit::Float(ref lit) if *ty == Ty::Float && empty_or_is("f32", lit.suffix()) => {
653 DefaultValue::F32(lit.base10_parse()?)
654 }
655 Lit::Int(ref lit) if *ty == Ty::Float => DefaultValue::F32(lit.base10_parse()?),
656
657 Lit::Float(ref lit) if *ty == Ty::Double && empty_or_is("f64", lit.suffix()) => {
658 DefaultValue::F64(lit.base10_parse()?)
659 }
660 Lit::Int(ref lit) if *ty == Ty::Double => DefaultValue::F64(lit.base10_parse()?),
661
662 Lit::Bool(ref lit) if *ty == Ty::Bool => DefaultValue::Bool(lit.value),
663 Lit::Str(ref lit) if *ty == Ty::String => DefaultValue::String(lit.value()),
664 Lit::ByteStr(ref lit)
665 if *ty == Ty::Bytes(BytesTy::Bytes) || *ty == Ty::Bytes(BytesTy::Vec) =>
666 {
667 DefaultValue::Bytes(lit.value())
668 }
669
670 Lit::Str(ref lit) => {
671 let value = lit.value();
672 let value = value.trim();
673
674 if let Ty::Enumeration(ref path) = *ty {
675 let variant = Ident::new(value, Span::call_site());
676 return Ok(DefaultValue::Enumeration(quote!(#path::#variant)));
677 }
678
679 if *ty == Ty::Float {
681 match value {
682 "inf" => {
683 return Ok(DefaultValue::Path(parse_str::<Path>(
684 "::core::f32::INFINITY",
685 )?));
686 }
687 "-inf" => {
688 return Ok(DefaultValue::Path(parse_str::<Path>(
689 "::core::f32::NEG_INFINITY",
690 )?));
691 }
692 "nan" => {
693 return Ok(DefaultValue::Path(parse_str::<Path>("::core::f32::NAN")?));
694 }
695 _ => (),
696 }
697 }
698 if *ty == Ty::Double {
699 match value {
700 "inf" => {
701 return Ok(DefaultValue::Path(parse_str::<Path>(
702 "::core::f64::INFINITY",
703 )?));
704 }
705 "-inf" => {
706 return Ok(DefaultValue::Path(parse_str::<Path>(
707 "::core::f64::NEG_INFINITY",
708 )?));
709 }
710 "nan" => {
711 return Ok(DefaultValue::Path(parse_str::<Path>("::core::f64::NAN")?));
712 }
713 _ => (),
714 }
715 }
716
717 if let Some(Ok(lit)) = value.strip_prefix('-').map(syn::parse_str::<Lit>) {
719 match lit {
720 Lit::Int(ref lit) if is_i32 && empty_or_is("i32", lit.suffix()) => {
721 let value: i64 = -lit.base10_parse()?;
723 return Ok(i32::try_from(value).map(DefaultValue::I32)?);
724 }
725 Lit::Int(ref lit) if is_i64 && empty_or_is("i64", lit.suffix()) => {
726 let value: i128 = -lit.base10_parse()?;
728 return Ok(i64::try_from(value).map(DefaultValue::I64)?);
729 }
730 Lit::Float(ref lit)
731 if *ty == Ty::Float && empty_or_is("f32", lit.suffix()) =>
732 {
733 return Ok(DefaultValue::F32(-lit.base10_parse()?));
734 }
735 Lit::Float(ref lit)
736 if *ty == Ty::Double && empty_or_is("f64", lit.suffix()) =>
737 {
738 return Ok(DefaultValue::F64(-lit.base10_parse()?));
739 }
740 Lit::Int(ref lit) if *ty == Ty::Float && lit.suffix().is_empty() => {
741 return Ok(DefaultValue::F32(-lit.base10_parse()?));
742 }
743 Lit::Int(ref lit) if *ty == Ty::Double && lit.suffix().is_empty() => {
744 return Ok(DefaultValue::F64(-lit.base10_parse()?));
745 }
746 _ => (),
747 }
748 }
749 match syn::parse_str::<Lit>(value) {
750 Ok(Lit::Str(_)) => (),
751 Ok(lit) => return DefaultValue::from_lit(ty, lit),
752 _ => (),
753 }
754 bail!("invalid default value: {}", quote!(#value));
755 }
756 _ => bail!("invalid default value: {}", quote!(#lit)),
757 };
758
759 Ok(default)
760 }
761
762 pub fn new(ty: &Ty) -> DefaultValue {
763 match *ty {
764 Ty::Float => DefaultValue::F32(0.0),
765 Ty::Double => DefaultValue::F64(0.0),
766 Ty::Int32 | Ty::Sint32 | Ty::Sfixed32 => DefaultValue::I32(0),
767 Ty::Int64 | Ty::Sint64 | Ty::Sfixed64 => DefaultValue::I64(0),
768 Ty::Uint32 | Ty::Fixed32 => DefaultValue::U32(0),
769 Ty::Uint64 | Ty::Fixed64 => DefaultValue::U64(0),
770
771 Ty::Bool => DefaultValue::Bool(false),
772 Ty::String => DefaultValue::String(String::new()),
773 Ty::Bytes(..) => DefaultValue::Bytes(Vec::new()),
774 Ty::Enumeration(ref path) => DefaultValue::Enumeration(quote!(#path::default())),
775 }
776 }
777
778 pub fn owned(&self, prost_path: &Path) -> TokenStream {
779 match *self {
780 DefaultValue::String(ref value) if value.is_empty() => {
781 quote!(#prost_path::alloc::string::String::new())
782 }
783 DefaultValue::String(ref value) => quote!(#value.into()),
784 DefaultValue::Bytes(ref value) if value.is_empty() => {
785 quote!(::core::default::Default::default())
786 }
787 DefaultValue::Bytes(ref value) => {
788 let lit = LitByteStr::new(value, Span::call_site());
789 quote!(#lit.as_ref().into())
790 }
791
792 ref other => other.typed(),
793 }
794 }
795
796 pub fn typed(&self) -> TokenStream {
797 if let DefaultValue::Enumeration(_) = *self {
798 quote!(#self as i32)
799 } else {
800 quote!(#self)
801 }
802 }
803}
804
805impl ToTokens for DefaultValue {
806 fn to_tokens(&self, tokens: &mut TokenStream) {
807 match *self {
808 DefaultValue::F64(value) => value.to_tokens(tokens),
809 DefaultValue::F32(value) => value.to_tokens(tokens),
810 DefaultValue::I32(value) => value.to_tokens(tokens),
811 DefaultValue::I64(value) => value.to_tokens(tokens),
812 DefaultValue::U32(value) => value.to_tokens(tokens),
813 DefaultValue::U64(value) => value.to_tokens(tokens),
814 DefaultValue::Bool(value) => value.to_tokens(tokens),
815 DefaultValue::String(ref value) => value.to_tokens(tokens),
816 DefaultValue::Bytes(ref value) => {
817 let byte_str = LitByteStr::new(value, Span::call_site());
818 tokens.append_all(quote!(#byte_str as &[u8]));
819 }
820 DefaultValue::Enumeration(ref value) => value.to_tokens(tokens),
821 DefaultValue::Path(ref value) => value.to_tokens(tokens),
822 }
823 }
824}