power_protobuf_lib/
parse.rs

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    // call_site_path = proc_macro::Span::call_site().source_file().path();
340    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                // The field name is a lowercased version of the type name
1076                // (which has been verified to start with an uppercase letter).
1077                // https://git.io/JvxAP
1078                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}