1use std::{
2 collections::{HashMap, HashSet},
3 ops::RangeInclusive,
4 path::PathBuf,
5};
6
7use convert_case::Case;
8use proc_macro2::Span;
9use syn::{
10 parse::{Parse, ParseBuffer, ParseStream},
11 punctuated::Punctuated,
12 token, Ident, LitBool, LitFloat, LitInt, LitStr, Token,
13};
14use syn_prelude::{
15 AmmendSynError, JoinSynErrors, ParseAsIdent, ToErr, ToIdentWithCase, ToLitStr, ToSynError,
16 TryParseAsIdent, TryParseOneOfIdents, WithPrefix, WithSuffix,
17};
18
19use crate::{
20 dep::Deps,
21 model::{
22 AnyTypeUrl, DeclIndex, EnumValue, Enumeration, Extension, Field, FieldType, Group, Import,
23 ImportVis, MapType, Message, MessageElement, Method, Modifier, NestedTypeIndex, OneOf,
24 Package, ProtobufConstant, ProtobufConstantMessage, ProtobufConstantMessageFieldName,
25 ProtobufOption, ProtobufOptionName, ProtobufOptionNameExt, ProtobufOptionNamePart,
26 ProtobufPath, Protocol, Service, Syntax, TagValue, Type,
27 },
28 resolve::{InsideType, PathMod, ResolveContext},
29};
30
31impl Protocol {
32 pub fn parse_from_call_site<BeforeCheck: FnMut(&mut Protocol) -> syn::Result<()>>(
33 input: ParseStream,
34 call_site_path: PathBuf,
35 mut before_check: BeforeCheck,
36 ) -> syn::Result<Self> {
37 let syntax: Syntax = input.parse()?;
38 let mut protocol = Self {
39 imports: Default::default(),
40 syntax,
41 package: None,
42 messages: Default::default(),
43 enums: Default::default(),
44 extensions: Default::default(),
45 services: Default::default(),
46 options: Default::default(),
47 decls: Default::default(),
48 deps: Deps::new(&call_site_path, input)?,
49 };
50
51 let proto_version = syntax.version();
52
53 protocol
54 .imports
55 .push(Import::call_site(&protocol.deps, &call_site_path)?);
56 while !input.is_empty() {
57 if input.peek(Token![;]) {
58 input.parse::<Token![;]>()?;
59 continue;
60 }
61 if let Some(message) = Message::try_parse(input, proto_version)
62 .add_error_suffix("while parsing message")?
63 {
64 protocol
65 .decls
66 .push(DeclIndex::Message(protocol.messages.len()));
67 protocol.messages.push(message);
68 } else if let Some(service) = Service::try_parse(input, proto_version)
69 .add_error_suffix("while parsing service")?
70 {
71 protocol
72 .decls
73 .push(DeclIndex::Service(protocol.services.len()));
74 let messages = service
75 .methods
76 .iter()
77 .map(|s| match (&s.input_message, &s.output_message) {
78 (None, None) => None,
79 (None, Some(o)) => Some(vec![o.clone()]),
80 (Some(i), None) => Some(vec![i.clone()]),
81 (Some(i), Some(o)) => Some(vec![i.clone(), o.clone()]),
82 })
83 .flatten()
84 .flatten()
85 .collect::<Vec<_>>();
86
87 protocol.services.push(service);
88 for message in messages {
89 protocol
90 .decls
91 .push(DeclIndex::Message(protocol.messages.len()));
92 protocol.messages.push(message);
93 }
94 } else if let Some(enumeration) = Enumeration::try_parse(input, proto_version)
95 .add_error_suffix("while parsing enumeration")?
96 {
97 protocol.decls.push(DeclIndex::Enum(protocol.enums.len()));
98 protocol.enums.push(enumeration);
99 } else if let Some(import) = Import::try_parse(&protocol.deps, input)
100 .add_error_suffix("while parsing import clause")?
101 {
102 protocol.imports.push(import);
103 } else if let Some(option) =
104 ProtobufOption::try_parse(input).add_error_prefix("while parsing global option")?
105 {
106 protocol.options.push(option);
107 } else if let Some(package) =
108 Package::try_parse(input).add_error_suffix("while parsing 'package'")?
109 {
110 protocol.package = Some(package);
111 } else if let Some(ext) = Extension::try_parse(input, proto_version)
112 .add_error_suffix("while parsing protobuf syntax version")?
113 {
114 protocol.extensions.extend(ext);
115 } else {
116 input.span().to_syn_error("unexpected token").to_err()?;
117 }
118 }
119
120 protocol.syntax = syntax;
121 before_check(&mut protocol)?;
122
123 for (import_index, import) in protocol.imports.iter().enumerate() {
124 protocol.deps.scan(import_index, import)?;
125 }
126
127 let mut types = protocol
128 .messages
129 .iter()
130 .map(|m| (m.name.clone(), InsideType::Message((&vec![], m).into())))
131 .collect::<HashMap<_, _>>();
132 protocol.enums.iter().for_each(|e| {
133 types.insert(e.name.clone(), InsideType::Enum(e.name.clone()));
134 });
135 protocol.services.iter().for_each(|s| {
136 s.methods.iter().for_each(|m| {
137 if let Some(m) = &m.input_message {
138 types.insert(m.name.clone(), InsideType::Message((&vec![], m).into()));
139 }
140 if let Some(m) = &m.output_message {
141 types.insert(m.name.clone(), InsideType::Message((&vec![], m).into()));
142 }
143 })
144 });
145 let ctx = ResolveContext {
146 package: &protocol.package,
147 types,
148 deps: &protocol.deps,
149 imports: &protocol.imports,
150 };
151
152 let check_result1 = protocol
153 .messages
154 .iter_mut()
155 .map(|m| m.resolve(&ctx))
156 .collect::<Vec<syn::Result<_>>>()
157 .join_errors();
158
159 let check_result2 = protocol
160 .services
161 .iter_mut()
162 .map(|s| {
163 s.methods
164 .iter_mut()
165 .map(|m| {
166 if let Some(message) = &mut m.input_message {
167 message.resolve(&ctx)?;
168 }
169 ctx.resolve_type(None, &mut m.input_type)?;
170 if let Some(message) = &mut m.output_message {
171 message.resolve(&ctx)?;
172 }
173 ctx.resolve_type(None, &mut m.output_type)?;
174 Ok(())
175 })
176 .collect::<Vec<_>>()
177 .join_errors()
178 })
179 .collect::<Vec<_>>()
180 .join_errors();
181
182 (check_result1, check_result2).join_errors()?;
183
184 Ok(protocol)
185 }
186}
187
188impl Parse for ProtobufPath {
189 fn parse(input: ParseStream) -> syn::Result<Self> {
190 let mut segments = Punctuated::new();
191 while !input.is_empty() {
192 segments.push(input.parse_as_ident()?);
193 if input.peek(Token![.]) {
194 segments.push_punct(input.parse::<Token![.]>()?);
195 } else {
196 break;
197 }
198 }
199 Ok(Self { segments })
200 }
201}
202
203impl Parse for ProtobufOptionNamePart {
204 fn parse(input: ParseStream) -> syn::Result<Self> {
205 if input.peek(token::Paren) {
206 let inner: ParseBuffer;
207 syn::parenthesized!(inner in input);
208 Ok(Self::Ext(inner.parse()?))
209 } else {
210 Ok(Self::Direct(input.parse()?))
211 }
212 }
213}
214
215impl Parse for ProtobufOptionName {
216 fn parse(input: ParseStream) -> syn::Result<Self> {
217 let mut components = vec![input.parse()?];
218 while input.peek(Token![.]) {
219 input.parse::<Token![.]>()?;
220 components.push(input.parse()?);
221 }
222 if components.len() == 1 {
223 if let ProtobufOptionNamePart::Direct(n) = &components[0] {
224 return Ok(ProtobufOptionName::Builtin(n.clone()));
225 }
226 }
227 Ok(Self::Ext(ProtobufOptionNameExt(components)))
228 }
229}
230
231impl Parse for ProtobufOption {
232 fn parse(input: ParseStream) -> syn::Result<Self> {
233 input.parse_as_named_ident("option", false)?;
234 Self::continue_to_parse(input)
235 }
236}
237
238impl ProtobufOption {
239 fn try_parse(input: ParseStream) -> syn::Result<Option<Self>> {
240 if input.peek_as_ident("option", false) {
241 Ok(Some(Self::parse(input)?))
242 } else {
243 Ok(None)
244 }
245 }
246}
247
248impl ProtobufOption {
249 fn continue_to_parse(input: ParseStream) -> syn::Result<Self> {
250 let name = input.parse()?;
251 input.parse::<Token![=]>()?;
252 let value = input.parse()?;
253 Ok(Self { name, value })
254 }
255}
256
257impl Parse for ProtobufConstant {
258 fn parse(input: ParseStream) -> syn::Result<Self> {
259 if input.peek(token::Brace) {
260 Ok(Self::Message(input.parse()?))
261 } else if input.peek(LitBool) {
262 Ok(Self::Bool(input.parse()?))
263 } else if input.peek(LitStr) {
264 Ok(Self::String(input.parse()?))
265 } else if input.peek(LitFloat) {
266 Ok(Self::Float(input.parse()?))
267 } else if input.peek(LitInt) {
268 Ok(Self::Int(input.parse()?))
269 } else {
270 Ok(Self::Ident(input.parse()?))
271 }
272 }
273}
274
275impl Parse for ProtobufConstantMessageFieldName {
276 fn parse(input: ParseStream) -> syn::Result<Self> {
277 Ok(if input.peek(token::Bracket) {
278 let inner: ParseBuffer;
279 syn::bracketed!(inner in input);
280 let n = inner.parse()?;
281 if input.peek(Token![/]) {
282 inner.parse::<Token![/]>()?;
283 let fullname = inner.parse()?;
284 Self::AnyTypeUrl(AnyTypeUrl {
285 prefix: n,
286 full_type_name: fullname,
287 })
288 } else {
289 Self::Extension(n)
290 }
291 } else {
292 Self::Regular(input.parse()?)
293 })
294 }
295}
296
297impl Parse for ProtobufConstantMessage {
298 fn parse(input: ParseStream) -> syn::Result<Self> {
299 let mut message = Self {
300 fields: Default::default(),
301 };
302 let inner: ParseBuffer;
303 syn::braced!(inner in input);
304 while !inner.is_empty() {
305 let name = inner.parse()?;
306 let value = if inner.peek(Token![:]) {
307 inner.parse::<Token![:]>()?;
308 inner.parse()?
309 } else {
310 ProtobufConstant::Message(inner.parse()?)
311 };
312 message.fields.insert(name, value);
313 }
314 Ok(message)
315 }
316}
317
318impl Parse for Syntax {
319 fn parse(input: ParseStream) -> syn::Result<Self> {
320 Ok(if let Some(_) = input.try_parse_as_ident("syntax", false) {
321 input.parse::<Token![=]>()?;
322 let lit: LitStr = input.parse()?;
323 let proto = lit.value();
324 let proto = if proto.eq("proto2") {
325 Self::Proto2(lit.span())
326 } else if proto.eq("proto3") {
327 Self::Proto3(Some(lit.span()))
328 } else {
329 lit.to_syn_error("unknown syntax").to_err()?
330 };
331 proto
332 } else {
333 Self::Proto3(None)
334 })
335 }
336}
337
338impl Import {
339 fn call_site(deps: &Deps, call_site_path: &PathBuf) -> syn::Result<Self> {
341 let span = Span::call_site();
342 let path_value = call_site_path.to_string_lossy().to_string();
343 let file_path = deps.resolve_path(&path_value, span)?;
344 let path = (path_value, span).to_lit_str();
345 Ok(Self {
346 import_token: span,
347 path,
348 builtin: false,
349 vis: ImportVis::Default,
350 file_path: Some(file_path),
351 })
352 }
353 fn try_parse(deps: &Deps, input: ParseStream) -> syn::Result<Option<Self>> {
354 if let Some(i) = input.try_parse_as_ident("import", false) {
355 let vis = if let Some(weak) = input.try_parse_as_ident("weak", false) {
356 ImportVis::Weak(weak.span())
357 } else if let Some(public) = input.try_parse_as_ident("public", false) {
358 ImportVis::Public(public.span())
359 } else {
360 ImportVis::Default
361 };
362 let path: LitStr = input.parse()?;
363 let path_value = path.value();
364 let builtin = if path_value.starts_with("google/protobuf/") {
365 true
366 } else if !path_value.ends_with(".rs") {
367 path.span()
368 .to_syn_error("only support for importing '.rs' yet")
369 .to_err()?
370 } else {
371 false
372 };
373 let file_path = if !builtin {
374 Some(deps.resolve_path(&path_value, path.span())?)
375 } else {
376 None
377 };
378
379 Ok(Some(Self {
380 import_token: i.span(),
381 vis,
382 builtin,
383 path,
384 file_path,
385 }))
386 } else {
387 Ok(None)
388 }
389 }
390}
391
392impl Package {
393 fn try_parse(input: ParseStream) -> syn::Result<Option<Self>> {
394 if let Some(_) = input.try_parse_as_ident("package", false) {
395 let package = input.parse::<Ident>()?;
396 Ok(Some(Self { package }))
397 } else {
398 Ok(None)
399 }
400 }
401}
402
403impl Service {
404 fn try_parse(input: ParseStream, proto_version: usize) -> syn::Result<Option<Self>> {
405 if let Some(_) = input.try_parse_as_ident("service", false) {
406 let name = input.parse_as_ident()?;
407 let inner: ParseBuffer;
408 syn::braced!(inner in input);
409 let mut methods = vec![];
410 let mut options = vec![];
411 while !inner.is_empty() {
412 if inner.peek(Token![;]) {
413 inner.parse::<Token![;]>()?;
414 continue;
415 }
416 if let Some(_) = inner.try_parse_as_ident("rpc", false) {
417 methods.push(Method::continue_to_parse(&inner, proto_version)?);
418 } else if let Some(stream) = inner.try_parse_as_ident("stream", false) {
419 if proto_version == 2 {
420 let mut method = Method::continue_to_parse(&inner, proto_version)?;
421 method.client_streaming = Some(stream.span());
422 method.server_streaming = Some(stream.span());
423 methods.push(method);
424 }
425 stream.to_syn_error("unexpect stream in proto3").to_err()?;
426 } else if let Some(_) = inner.try_parse_as_ident("option", false) {
427 let option = ProtobufOption::continue_to_parse(&inner)?;
428 options.push(option);
429 }
430 }
431 Ok(Some(Self {
432 code_name: name.to_ident_with_case(Case::UpperCamel),
433 name,
434 methods,
435 options,
436 }))
437 } else {
438 Ok(None)
439 }
440 }
441}
442
443impl Method {
444 fn parse_param(
445 input: ParseStream,
446 rpc_name: &Ident,
447 proto_version: usize,
448 suffix: &'static str,
449 ) -> syn::Result<(Option<Span>, Type, Option<Message>)> {
450 let inner: ParseBuffer;
451 syn::parenthesized!(inner in input);
452 let stream = if proto_version != 2 {
453 inner.try_parse_as_ident("stream", false)
454 } else {
455 None
456 };
457 let (message, param_type) = if cfg!(feature = "simplize_rpc_params") {
458 if inner.is_empty() {
459 (None, ProtobufPath::new_empty(rpc_name.span()))
460 } else if inner.peek(token::Brace) {
461 let MessageBody {
462 fields,
463 options,
464 reserved_names,
465 reserved_nums,
466 extension_ranges,
467 extensions,
468 messages,
469 enums,
470 nested_types,
471 ..
472 } = MessageBody::parse(
473 &inner,
474 proto_version,
475 MessageBodyParseMode::parse_message(proto_version),
476 None,
477 false,
478 )?;
479 let message_name = rpc_name
480 .to_ident_with_case(Case::UpperCamel)
481 .with_suffix(suffix);
482 let message = Message {
483 struct_name: message_name.clone(),
484 name: message_name.clone(),
485 fields,
486 options,
487 reserved_names,
488 reserved_nums,
489 extension_ranges,
490 extensions,
491 messages,
492 enums,
493 nested_types,
494 };
495 (Some(message), ProtobufPath::from_ident(message_name))
496 } else if inner.peek(Ident) && inner.peek2(token::Brace) {
497 let message_name: Ident = inner.parse()?;
498 let MessageBody {
499 fields,
500 options,
501 reserved_names,
502 reserved_nums,
503 extension_ranges,
504 extensions,
505 messages,
506 enums,
507 nested_types,
508 ..
509 } = MessageBody::parse(
510 &inner,
511 proto_version,
512 MessageBodyParseMode::parse_message(proto_version),
513 None,
514 false,
515 )?;
516 let message = Message {
517 struct_name: message_name.clone(),
518 name: message_name.clone(),
519 fields,
520 options,
521 reserved_names,
522 reserved_nums,
523 extension_ranges,
524 extensions,
525 messages,
526 enums,
527 nested_types,
528 };
529 (Some(message), ProtobufPath::from_ident(message_name))
530 } else {
531 (None, inner.parse()?)
532 }
533 } else {
534 (None, inner.parse()?)
535 };
536 if !inner.is_empty() {
537 inner.span().to_syn_error("expect ')'").to_err()?;
538 }
539 Ok((
540 stream.map(|i| i.span()),
541 Type {
542 type_path: param_type,
543 target_is_message: true,
544 ty: syn::Type::new(),
545 },
546 message,
547 ))
548 }
549
550 fn continue_to_parse(input: ParseStream, proto_version: usize) -> syn::Result<Self> {
551 let name = input.parse_as_ident()?;
552 let (client_streaming, input_type, input_message) =
553 Self::parse_param(input, &name, proto_version, "Request")?;
554 input.parse_as_named_ident("returns", false)?;
555 let (server_streaming, output_type, output_message) =
556 Self::parse_param(input, &name, proto_version, "Response")?;
557
558 let options = input.parse::<TryAsOptions>()?.0;
559
560 Ok(Self {
561 method_name: name.to_ident_with_case(Case::Snake),
562 name,
563 client_streaming,
564 input_message,
565 input_type,
566 server_streaming,
567 output_message,
568 output_type,
569 options,
570 })
571 }
572}
573
574struct TryAsOptions(Punctuated<ProtobufOption, Token![;]>);
575impl Parse for TryAsOptions {
576 fn parse(input: ParseStream) -> syn::Result<Self> {
577 if input.peek(token::Brace) {
578 let inner: ParseBuffer;
579 syn::braced!(inner in input);
580 inner
581 .parse_terminated(ProtobufOption::parse, Token![;])
582 .map(|options| Self(options))
583 } else {
584 Ok(Self(Punctuated::new()))
585 }
586 }
587}
588
589impl Message {
590 fn try_parse(input: ParseStream, proto_version: usize) -> syn::Result<Option<Self>> {
591 if let Some(_) = input.try_parse_as_ident("message", false) {
592 let name = input.parse_as_ident()?;
593 let MessageBody {
594 fields,
595 reserved_nums,
596 reserved_names,
597 messages,
598 enums,
599 options,
600 extension_ranges,
601 extensions,
602 nested_types,
603 } = MessageBody::parse(
604 input,
605 proto_version,
606 MessageBodyParseMode::parse_message(proto_version),
607 Some(&name),
608 false,
609 )?;
610
611 Ok(Some(Self {
612 nested_types,
613 struct_name: name.to_ident_with_case(Case::UpperCamel),
614 name,
615 fields,
616 reserved_nums,
617 reserved_names,
618 messages,
619 enums,
620 options,
621 extension_ranges,
622 extensions,
623 }))
624 } else {
625 Ok(None)
626 }
627 }
628}
629
630#[derive(Copy, Clone, PartialEq, Eq)]
631enum MessageBodyParseMode {
632 MessageProto2,
633 MessageProto3,
634 Oneof,
635 ExtendProto2,
636 ExtendProto3,
637}
638
639impl MessageBodyParseMode {
640 fn parse_message(version: usize) -> Self {
641 if version == 2 {
642 Self::MessageProto2
643 } else {
644 Self::MessageProto3
645 }
646 }
647
648 fn parse_extension(version: usize) -> Self {
649 if version == 2 {
650 Self::ExtendProto2
651 } else {
652 Self::ExtendProto3
653 }
654 }
655
656 fn to_str(&self) -> &'static str {
657 match self {
658 Self::MessageProto2 => "parsing message in proto2",
659 Self::MessageProto3 => "parsing message in proto3",
660 Self::Oneof => "parsing oneof",
661 Self::ExtendProto2 => "parsing extension in proto2",
662 Self::ExtendProto3 => "parsing extension in proto3",
663 }
664 }
665}
666
667#[allow(unused)]
668impl MessageBodyParseMode {
669 fn label_allowed(&self, label: Modifier) -> bool {
670 match label {
671 Modifier::Repeated => match *self {
672 MessageBodyParseMode::MessageProto2
673 | MessageBodyParseMode::MessageProto3
674 | MessageBodyParseMode::ExtendProto2
675 | MessageBodyParseMode::ExtendProto3 => true,
676 MessageBodyParseMode::Oneof => false,
677 },
678 Modifier::Optional => match *self {
679 MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::ExtendProto2 => true,
680 MessageBodyParseMode::MessageProto3 | MessageBodyParseMode::ExtendProto3 => true,
681 MessageBodyParseMode::Oneof => false,
682 },
683 Modifier::Required => match *self {
684 MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::ExtendProto2 => true,
685 MessageBodyParseMode::MessageProto3 | MessageBodyParseMode::ExtendProto3 => false,
686 MessageBodyParseMode::Oneof => false,
687 },
688 }
689 }
690
691 fn some_label_required(&self) -> bool {
692 match *self {
693 MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::ExtendProto2 => true,
694 MessageBodyParseMode::MessageProto3
695 | MessageBodyParseMode::ExtendProto3
696 | MessageBodyParseMode::Oneof => false,
697 }
698 }
699
700 fn map_allowed(&self) -> bool {
701 match *self {
702 MessageBodyParseMode::MessageProto2
703 | MessageBodyParseMode::MessageProto3
704 | MessageBodyParseMode::ExtendProto2
705 | MessageBodyParseMode::ExtendProto3 => true,
706 MessageBodyParseMode::Oneof => false,
707 }
708 }
709
710 fn is_most_non_fields_allowed(&self) -> bool {
711 match *self {
712 MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::MessageProto3 => true,
713 MessageBodyParseMode::ExtendProto2
714 | MessageBodyParseMode::ExtendProto3
715 | MessageBodyParseMode::Oneof => false,
716 }
717 }
718
719 fn is_option_allowed(&self) -> bool {
720 match *self {
721 MessageBodyParseMode::MessageProto2
722 | MessageBodyParseMode::MessageProto3
723 | MessageBodyParseMode::Oneof => true,
724 MessageBodyParseMode::ExtendProto2 | MessageBodyParseMode::ExtendProto3 => false,
725 }
726 }
727
728 fn is_extensions_allowed(&self) -> bool {
729 match self {
730 MessageBodyParseMode::MessageProto2 => true,
731 _ => false,
732 }
733 }
734}
735
736#[derive(Default)]
737pub(crate) struct MessageBody {
738 pub fields: Vec<MessageElement>,
739 pub reserved_nums: Vec<RangeInclusive<i32>>,
740 pub reserved_names: Vec<Ident>,
741 pub messages: Vec<Message>,
742 pub enums: Vec<Enumeration>,
743 pub options: Vec<ProtobufOption>,
744 pub extension_ranges: Vec<RangeInclusive<i32>>,
745 pub extensions: Vec<Extension>,
746 pub nested_types: Vec<NestedTypeIndex>,
747}
748
749fn parse_range(input: ParseStream) -> syn::Result<RangeInclusive<i32>> {
750 let from = input.parse::<LitInt>()?.base10_parse::<i32>()?;
751 let to = if let Some(_) = input.try_parse_as_ident("to", false) {
752 if let Some(_) = input.try_parse_as_ident("max", false) {
753 0x20000000 - 1
754 } else {
755 input.parse::<LitInt>()?.base10_parse::<i32>()?
756 }
757 } else {
758 from
759 };
760 Ok(from..=to)
761}
762
763fn parse_ranges(input: ParseStream) -> syn::Result<Vec<RangeInclusive<i32>>> {
764 let mut ranges = vec![parse_range(input)?];
765 while input.peek(Token![,]) {
766 input.parse::<Token![,]>()?;
767 ranges.push(parse_range(input)?);
768 }
769 Ok(ranges)
770}
771
772impl MessageBody {
773 fn parse(
774 input: ParseStream,
775 proto_version: usize,
776 mode: MessageBodyParseMode,
777 parent_name: Option<&Ident>,
778 enum_flag: bool,
779 ) -> syn::Result<Self> {
780 let mut r = MessageBody::default();
781 let inner: ParseBuffer;
782 syn::braced!(inner in input);
783 while !inner.is_empty() {
784 if inner.peek(Token![;]) {
785 inner.parse::<Token![;]>()?;
786 continue;
787 }
788 if mode.is_most_non_fields_allowed() {
789 if let Some((field_nums, field_names)) = Self::try_parse_reserved(&inner)? {
790 r.reserved_nums.extend(field_nums);
791 r.reserved_names.extend(field_names);
792 continue;
793 }
794 if let Some(oneof) = OneOf::try_parse(&inner, proto_version, parent_name)? {
795 r.nested_types.push(NestedTypeIndex::Oneof(r.fields.len()));
796 r.fields.push(MessageElement::OneOf(oneof));
797 continue;
798 }
799 if let Some(extensions) = Extension::try_parse(&inner, proto_version)? {
800 r.extensions.extend(extensions);
801 continue;
802 }
803 if let Some(nested) = Message::try_parse(&inner, proto_version)? {
804 r.nested_types
805 .push(NestedTypeIndex::Message(r.messages.len()));
806 r.messages.push(nested);
807 continue;
808 }
809 if let Some(nested) = Enumeration::try_parse(&inner, proto_version)? {
810 r.nested_types.push(NestedTypeIndex::Enum(r.enums.len()));
811 r.enums.push(nested);
812 continue;
813 }
814 } else {
815 if let Some(ident) = inner
816 .try_parse_one_of_idents(vec!["reserved", "oneof", "extend", "message", "enum"])
817 {
818 ident
819 .to_syn_error(format!("not allowed while {}", mode.to_str()))
820 .to_err()?;
821 }
822 }
823
824 if mode.is_extensions_allowed() {
825 if let Some(extensions) = Extension::try_parse(&inner, proto_version)? {
826 r.extensions.extend(extensions);
827 continue;
828 }
829 } else {
830 if let Some(ident) = inner.try_parse_as_ident("extensions", false) {
831 ident
832 .to_syn_error(format!("not allowed while {}", mode.to_str()))
833 .to_err()?;
834 }
835 }
836
837 if mode.is_option_allowed() {
838 if let Some(_) = inner.try_parse_as_ident("option", false) {
839 r.options.push(ProtobufOption::continue_to_parse(&inner)?);
840 inner.parse::<Token![;]>()?;
841 continue;
842 }
843 } else {
844 if let Some(ident) = inner.try_parse_as_ident("option", false) {
845 ident
846 .to_syn_error(format!("not allowed while {}", mode.to_str()))
847 .to_err()?;
848 }
849 }
850
851 r.fields.push(MessageElement::Field(Field::parse(
852 &inner,
853 proto_version,
854 mode,
855 parent_name,
856 enum_flag,
857 )?));
858 }
859
860 if mode != MessageBodyParseMode::Oneof {
861 r.check_tags()?;
862 }
863
864 Ok(r)
865 }
866
867 fn try_parse_reserved(
868 input: ParseStream,
869 ) -> syn::Result<Option<(Vec<RangeInclusive<i32>>, Vec<Ident>)>> {
870 Ok(
871 if let Some(_) = input.try_parse_as_ident("reserved", false) {
872 Some(if input.peek(LitStr) {
873 let mut names = vec![input.parse_as_ident()?];
874 while input.peek(Token![,]) {
875 input.parse::<Token![,]>()?;
876 names.push(input.parse_as_ident()?);
877 }
878 (vec![], names)
879 } else {
880 (parse_ranges(input)?, vec![])
881 })
882 } else {
883 None
884 },
885 )
886 }
887
888 fn check_tags(&mut self) -> syn::Result<()> {
889 let mut tag_used = HashMap::<i32, Span>::new();
890 let mut ref_tag_span = None;
891 let mut next_tag = 1;
892
893 fn check_field(
894 field: &mut Field,
895 reserved_nums: &Vec<RangeInclusive<i32>>,
896 tag_used: &mut HashMap<i32, Span>,
897 mut next_tag: i32,
898 ref_tag_span: Option<Span>,
899 ) -> syn::Result<(i32, Option<Span>)> {
900 match &field.tag {
901 TagValue::Value(span, value) => {
902 for range in reserved_nums.iter() {
903 if range.contains(value) {
904 return span.to_syn_error("tag number is reserved").to_err();
905 }
906 }
907 if let Some(_) = tag_used.get(value) {
908 return span.to_syn_error("tag number is used").to_err();
909 }
910 tag_used.insert(*value, *span);
911 Ok((*value + 1, Some(*span)))
912 }
913 TagValue::AutoIncr => {
914 while next_tag < i32::MAX {
915 for range in reserved_nums.iter() {
916 if range.contains(&next_tag) {
917 next_tag = range.end() + 1;
918 continue;
919 }
920 }
921 if tag_used.contains_key(&next_tag) {
922 next_tag += 1;
923 } else {
924 break;
925 }
926 }
927 tag_used.insert(next_tag, field.field_name.span());
928 field.tag =
929 TagValue::Value(ref_tag_span.unwrap_or(field.field_name.span()), next_tag);
930 Ok((next_tag + 1, ref_tag_span))
931 }
932 }
933 }
934
935 for field in self.fields.iter_mut() {
936 match field {
937 MessageElement::Field(field) => {
938 (next_tag, ref_tag_span) = check_field(
939 field,
940 &self.reserved_nums,
941 &mut tag_used,
942 next_tag,
943 ref_tag_span,
944 )?;
945 }
946 MessageElement::OneOf(oneof) => {
947 for field in oneof.fields.iter_mut() {
948 (next_tag, ref_tag_span) = check_field(
949 field,
950 &self.reserved_nums,
951 &mut tag_used,
952 next_tag,
953 ref_tag_span,
954 )?;
955 }
956 oneof.tags = LitStr::new(
957 &oneof
958 .fields
959 .iter()
960 .map(|f| f.tag.to_lit_str().value())
961 .collect::<Vec<_>>()
962 .join(", "),
963 oneof.tags.span(),
964 );
965 }
966 }
967 }
968 Ok(())
969 }
970}
971
972impl Modifier {
973 fn try_parse(input: ParseStream, mode: MessageBodyParseMode) -> syn::Result<Option<Self>> {
974 if let Some(label) = input.try_parse_as_ident("optional", false) {
975 if !mode.label_allowed(Modifier::Optional) {
976 label
977 .to_syn_error(format!("not allowed in {}", mode.to_str()))
978 .to_err()
979 } else {
980 Ok(Some(Self::Optional))
981 }
982 } else if let Some(label) = input.try_parse_as_ident("repeated", false) {
983 if !mode.label_allowed(Modifier::Repeated) {
984 label
985 .to_syn_error(format!("not allowed in {}", mode.to_str()))
986 .to_err()
987 } else {
988 Ok(Some(Self::Repeated))
989 }
990 } else if let Some(label) = input.try_parse_as_ident("required", false) {
991 if !mode.label_allowed(Modifier::Required) {
992 label
993 .to_syn_error(format!("not allowed in {}", mode.to_str()))
994 .to_err()
995 } else {
996 Ok(Some(Self::Required))
997 }
998 } else {
999 Ok(None)
1000 }
1001 }
1002}
1003
1004impl TagValue {
1005 fn parse(input: ParseStream, error_span: Span) -> syn::Result<Self> {
1006 if input.peek(Token![=]) {
1007 input.parse::<Token![=]>()?;
1008 let value = input.parse::<LitInt>()?;
1009 let span = value.span();
1010 let value: i32 = value.base10_parse()?;
1011 Ok(Self::Value(span, value))
1012 } else {
1013 if cfg!(not(feature = "tagless")) {
1014 return Err(syn::Error::new(
1015 error_span,
1016 "missing tag number here, you can enable 'tagless' feature to omit the tag.",
1017 ));
1018 }
1019 Ok(Self::AutoIncr)
1020 }
1021 }
1022}
1023
1024impl Field {
1025 fn parse(
1026 input: ParseStream,
1027 proto_version: usize,
1028 mode: MessageBodyParseMode,
1029 parent_name: Option<&Ident>,
1030 enum_field: bool,
1031 ) -> syn::Result<Self> {
1032 let rule = if input.peek_as_ident("map", false) {
1033 if !mode.map_allowed() {
1034 let ident = input.parse_as_named_ident("map", false)?;
1035 ident
1036 .to_syn_error(format!("not allowed in {}", mode.to_str()))
1037 .to_err()?;
1038 }
1039 None
1040 } else {
1041 Modifier::try_parse(input, mode)?
1042 };
1043
1044 if let Some(_) = input.try_parse_as_ident("group", false) {
1045 let name = input.parse_as_ident()?;
1046 if !name
1047 .to_string()
1048 .chars()
1049 .next()
1050 .unwrap()
1051 .is_ascii_uppercase()
1052 {
1053 name.to_syn_error("expect Upper case group name").to_err()?;
1054 }
1055 let tag = TagValue::parse(input, name.span())?;
1056 let MessageBody { fields, .. } = MessageBody::parse(
1057 input,
1058 proto_version,
1059 MessageBodyParseMode::parse_message(proto_version),
1060 parent_name,
1061 enum_field,
1062 )?;
1063 let fields = fields
1064 .into_iter()
1065 .map(|fo| match fo {
1066 MessageElement::Field(f) => Ok(f),
1067 MessageElement::OneOf(o) => o
1068 .name
1069 .to_syn_error("unexpected 'oneof' in 'group'")
1070 .to_err(),
1071 })
1072 .collect::<syn::Result<_>>()?;
1073 Ok(Self {
1074 field_name: name.to_ident_with_case(Case::Snake),
1075 name: name.to_ident_with_case(Case::Lower),
1079 modifier: rule,
1080 typ: FieldType::Group(Group { name, fields }),
1081 tag,
1082 options: Vec::new(),
1083 enum_field,
1084 })
1085 } else {
1086 let typ = FieldType::parse(input)?;
1087 let name = input.parse_as_ident()?;
1088 let tag = TagValue::parse(input, name.span())?;
1089 let mut options = vec![];
1090 if input.peek(token::Brace) {
1091 let inner: ParseBuffer;
1092 syn::braced!(inner in input);
1093 while !inner.is_empty() {
1094 if inner.peek(Token![;]) {
1095 inner.parse::<Token![;]>()?;
1096 continue;
1097 }
1098 options.push(inner.parse()?);
1099 }
1100 } else if input.peek(token::Bracket) {
1101 let inner: ParseBuffer;
1102 syn::bracketed!(inner in input);
1103 while !inner.is_empty() {
1104 if inner.peek(Token![;]) {
1105 inner.parse::<Token![;]>()?;
1106 continue;
1107 }
1108 options.push(inner.parse()?);
1109 }
1110 }
1111 Ok(Self {
1112 field_name: name.to_ident_with_case(Case::Snake),
1113 name,
1114 modifier: rule,
1115 typ,
1116 tag,
1117 options,
1118 enum_field,
1119 })
1120 }
1121 }
1122}
1123
1124impl Parse for FieldType {
1125 fn parse(input: ParseStream) -> syn::Result<Self> {
1126 if let Some(ty) = input.try_parse_one_of_idents(vec![
1127 "int32", "int64", "uint32", "uint64", "sint32", "sint64", "fixed32", "sfixed32",
1128 "fixed64", "sfixed64", "bool", "string", "bytes", "float", "double",
1129 ]) {
1130 Ok(match ty.to_string().as_str() {
1131 "int32" => Self::Int32(ty.span()),
1132 "int64" => Self::Int64(ty.span()),
1133 "uint32" => Self::Uint32(ty.span()),
1134 "uint64" => Self::Uint64(ty.span()),
1135 "sint32" => Self::Sint32(ty.span()),
1136 "sint64" => Self::Sint64(ty.span()),
1137 "fixed32" => Self::Fixed32(ty.span()),
1138 "sfixed32" => Self::Sfixed32(ty.span()),
1139 "fixed64" => Self::Fixed64(ty.span()),
1140 "sfixed64" => Self::Sfixed64(ty.span()),
1141 "bool" => Self::Bool(ty.span()),
1142 "string" => Self::String(ty.span()),
1143 "bytes" => Self::Bytes(ty.span()),
1144 "float" => Self::Float(ty.span()),
1145 "double" => Self::Double(ty.span()),
1146 _ => {
1147 unreachable!()
1148 }
1149 })
1150 } else if let Some(ident) = input.try_parse_as_ident("map", false) {
1151 input.parse::<Token![<]>()?;
1152
1153 let key = FieldType::parse(input)?;
1154
1155 input.parse::<Token![,]>()?;
1156 let value = FieldType::parse(input)?;
1157
1158 let a = input.parse::<Token![>]>()?;
1159 let span = ident.span().join(a.span).unwrap_or(ident.span());
1160 Ok(Self::Map(MapType {
1161 span,
1162 key: Box::new(key),
1163 value: Box::new(value),
1164 }))
1165 } else {
1166 let type_path: ProtobufPath = input.parse()?;
1167 Ok(Self::MessageOrEnum(Type {
1168 type_path,
1169 target_is_message: true,
1170 ty: syn::Type::new(),
1171 }))
1172 }
1173 }
1174}
1175
1176impl OneOf {
1177 fn try_parse(
1178 input: ParseStream,
1179 proto_version: usize,
1180 parent_name: Option<&Ident>,
1181 ) -> syn::Result<Option<Self>> {
1182 if let Some(_) = input.try_parse_as_ident("oneof", false) {
1183 let name = input.parse_as_ident()?;
1184 let MessageBody {
1185 fields, options, ..
1186 } = MessageBody::parse(
1187 input,
1188 proto_version,
1189 MessageBodyParseMode::Oneof,
1190 parent_name,
1191 true,
1192 )?;
1193 let fields = fields
1194 .into_iter()
1195 .map(|fo| match fo {
1196 MessageElement::Field(f) => Ok(f),
1197 MessageElement::OneOf(o) => o.name.to_syn_error("oneof in oneof").to_err(),
1198 })
1199 .collect::<syn::Result<Vec<_>>>()?;
1200
1201 if fields.len() == 0 {
1202 name.to_syn_error("missing fields").to_err()?;
1203 }
1204
1205 let mut span = fields.first().unwrap().name.span();
1206 if let Some(last) = fields.last() {
1207 if let Some(s) = span.join(last.name.span()) {
1208 span = s;
1209 }
1210 }
1211
1212 let nested_mod_name = parent_name
1213 .ok_or(syn::Error::new(name.span(), "missing parent message"))?
1214 .to_ident_with_case(Case::Snake);
1215
1216 let enum_name = name.to_ident_with_case(Case::UpperCamel);
1217
1218 Ok(Some(OneOf {
1219 field_name: name.clone(),
1220 field_lit: enum_name
1221 .to_lit_str()
1222 .with_prefix(format!("{}::", nested_mod_name.to_string())),
1223 enum_name,
1224 tags: ("", span).to_lit_str(),
1225 name,
1226 fields,
1227 options,
1228 }))
1229 } else {
1230 Ok(None)
1231 }
1232 }
1233}
1234
1235impl Extension {
1236 fn try_parse(input: ParseStream, proto_version: usize) -> syn::Result<Option<Vec<Extension>>> {
1237 if let Some(_) = input.try_parse_as_ident("extend", false) {
1238 let extendee: ProtobufPath = input.parse()?;
1239 let MessageBody { fields, .. } = MessageBody::parse(
1240 input,
1241 proto_version,
1242 MessageBodyParseMode::parse_extension(proto_version),
1243 None,
1244 false,
1245 )?;
1246
1247 let fields: Vec<Field> = fields
1248 .into_iter()
1249 .map(|fo| match fo {
1250 MessageElement::Field(f) => Ok(f),
1251 MessageElement::OneOf(o) => o.name.to_syn_error("oneof in extend").to_err(),
1252 })
1253 .collect::<syn::Result<_>>()?;
1254
1255 let extensions = fields
1256 .into_iter()
1257 .map(|field| {
1258 let extendee = extendee.clone();
1259 let extension = Extension { extendee, field };
1260 extension
1261 })
1262 .collect();
1263 Ok(Some(extensions))
1264 } else {
1265 Ok(None)
1266 }
1267 }
1268}
1269
1270impl Enumeration {
1271 fn try_parse(input: ParseStream, _proto_version: usize) -> syn::Result<Option<Self>> {
1272 if let Some(_) = input.try_parse_as_ident("enum", false) {
1273 let name = input.parse_as_ident()?;
1274 let mut values: Vec<EnumValue> = Vec::new();
1275 let mut options = Vec::new();
1276 let mut reserved_nums = Vec::new();
1277 let mut reserved_names = Vec::new();
1278
1279 let inner: ParseBuffer;
1280 syn::braced!(inner in input);
1281 while !inner.is_empty() {
1282 if inner.peek(Token![;]) {
1283 inner.parse::<Token![;]>()?;
1284 continue;
1285 }
1286 if let Some((field_nums, field_names)) = MessageBody::try_parse_reserved(&inner)? {
1287 reserved_nums.extend(field_nums);
1288 reserved_names.extend(field_names);
1289 continue;
1290 }
1291 if let Some(_) = inner.try_parse_as_ident("option", false) {
1292 options.push(ProtobufOption::continue_to_parse(&inner)?);
1293 continue;
1294 }
1295 values.push(inner.parse()?);
1296 }
1297
1298 let mut next_tag = 0;
1299 let used_map = values.iter().map(|v| v.tag_value).collect::<HashSet<_>>();
1300 for value in values.iter_mut() {
1301 if value.tag_value >= 0 {
1302 for reserved in reserved_nums.iter() {
1303 if reserved.contains(&value.tag_value) {
1304 value
1305 .tag
1306 .as_ref()
1307 .unwrap()
1308 .span()
1309 .to_syn_error("tag number is reserved")
1310 .to_err()?;
1311 }
1312 }
1313 next_tag = value.tag_value;
1314 } else {
1315 while next_tag < i32::MAX {
1316 for reserved in reserved_nums.iter() {
1317 if reserved.contains(&next_tag) {
1318 next_tag = reserved.end() + 1;
1319 continue;
1320 }
1321 }
1322 if used_map.contains(&next_tag) {
1323 next_tag += 1;
1324 } else {
1325 value.tag = Some(LitInt::new(&next_tag.to_string(), value.name.span()));
1326 value.tag_value = next_tag;
1327 next_tag += 1;
1328 break;
1329 }
1330 }
1331 }
1332 }
1333
1334 Ok(Some(Self {
1335 name,
1336 values,
1337 options,
1338 reserved_names,
1339 reserved_nums,
1340 }))
1341 } else {
1342 Ok(None)
1343 }
1344 }
1345}
1346
1347impl Parse for EnumValue {
1348 fn parse(input: ParseStream) -> syn::Result<Self> {
1349 let name = input.parse_as_ident()?;
1350 let (tag, tag_value) = if input.peek(Token![=]) {
1351 input.parse::<Token![=]>()?;
1352 let tag_number = input.parse::<LitInt>()?;
1353 let tag_value: i32 = tag_number.base10_parse().map_err(|err| {
1354 tag_number
1355 .span()
1356 .to_syn_error(format!("illegal tag value: {err}"))
1357 })?;
1358 if tag_value < 0 {
1359 tag_number
1360 .span()
1361 .to_syn_error("enumeration tag value should be >= 0")
1362 .to_err()?;
1363 }
1364 (Some(tag_number), tag_value)
1365 } else {
1366 (None, -1)
1367 };
1368 let options = if input.peek(token::Bracket) {
1369 let inner: ParseBuffer;
1370 syn::bracketed!(inner in input);
1371 Some(
1372 inner
1373 .parse_terminated(ProtobufOption::parse_enum_option, Token![;])?
1374 .into_iter()
1375 .collect(),
1376 )
1377 } else if input.peek(token::Brace) {
1378 let inner: ParseBuffer;
1379 syn::braced!(inner in input);
1380 Some(
1381 inner
1382 .parse_terminated(ProtobufOption::parse_enum_option, Token![;])?
1383 .into_iter()
1384 .collect(),
1385 )
1386 } else {
1387 None
1388 };
1389 Ok(Self {
1390 proto_name: name.to_lit_str(),
1391 variant_name: name.to_ident_with_case(Case::UpperCamel),
1392 name,
1393 tag,
1394 tag_value,
1395 options,
1396 })
1397 }
1398}
1399
1400impl ProtobufOption {
1401 fn parse_enum_option(input: ParseStream) -> syn::Result<Self> {
1402 let name = input.parse()?;
1403 input.parse::<Token![=]>()?;
1404 let value = input.parse()?;
1405 Ok(Self { name, value })
1406 }
1407}