protobuf_parse/pure/
parser.rs

1use std::ops::RangeInclusive;
2use std::str;
3
4use protobuf_support::lexer::int;
5use protobuf_support::lexer::lexer_impl::LexerError;
6use protobuf_support::lexer::num_lit::NumLit;
7use protobuf_support::lexer::parser_language::ParserLanguage;
8use protobuf_support::lexer::str_lit::StrLitDecodeError;
9use protobuf_support::lexer::token::Token;
10use protobuf_support::lexer::tokenizer::Tokenizer;
11use protobuf_support::lexer::tokenizer::TokenizerError;
12
13use crate::model::AnyTypeUrl;
14use crate::model::ProtobufConstantMessageFieldName;
15use crate::proto_path::ProtoPathBuf;
16use crate::protobuf_abs_path::ProtobufAbsPath;
17use crate::protobuf_ident::ProtobufIdent;
18use crate::protobuf_path::ProtobufPath;
19use crate::protobuf_rel_path::ProtobufRelPath;
20use crate::pure::model;
21use crate::pure::model::EnumValue;
22use crate::pure::model::Enumeration;
23use crate::pure::model::Extension;
24use crate::pure::model::Field;
25use crate::pure::model::FieldOrOneOf;
26use crate::pure::model::FieldType;
27use crate::pure::model::FileDescriptor;
28use crate::pure::model::Group;
29use crate::pure::model::ImportVis;
30use crate::pure::model::Message;
31use crate::pure::model::Method;
32use crate::pure::model::OneOf;
33use crate::pure::model::ProtobufConstant;
34use crate::pure::model::ProtobufConstantMessage;
35use crate::pure::model::ProtobufOption;
36use crate::pure::model::ProtobufOptionName;
37use crate::pure::model::ProtobufOptionNameExt;
38use crate::pure::model::ProtobufOptionNamePart;
39use crate::pure::model::Rule;
40use crate::pure::model::Service;
41use crate::pure::model::Syntax;
42use crate::pure::model::WithLoc;
43
44/// Basic information about parsing error.
45#[derive(Debug, thiserror::Error)]
46pub(crate) enum ParserError {
47    #[error("{0}")]
48    TokenizerError(#[source] TokenizerError),
49    // TODO
50    #[error("incorrect input")]
51    IncorrectInput,
52    #[error("expecting a constant")]
53    ExpectConstant,
54    #[error("unknown syntax")]
55    UnknownSyntax,
56    #[error("integer overflow")]
57    IntegerOverflow,
58    #[error("label not allowed")]
59    LabelNotAllowed,
60    #[error("label required")]
61    LabelRequired,
62    #[error("group name should start with upper case")]
63    GroupNameShouldStartWithUpperCase,
64    #[error("map field not allowed")]
65    MapFieldNotAllowed,
66    #[error("string literal decode error: {0}")]
67    StrLitDecodeError(#[source] StrLitDecodeError),
68    #[error("lexer error: {0}")]
69    LexerError(#[source] LexerError),
70    #[error("oneof in group")]
71    OneOfInGroup,
72    #[error("oneof in oneof")]
73    OneOfInOneOf,
74    #[error("oneof in extend")]
75    OneOfInExtend,
76}
77
78impl From<TokenizerError> for ParserError {
79    fn from(e: TokenizerError) -> Self {
80        ParserError::TokenizerError(e)
81    }
82}
83
84impl From<StrLitDecodeError> for ParserError {
85    fn from(e: StrLitDecodeError) -> Self {
86        ParserError::StrLitDecodeError(e)
87    }
88}
89
90impl From<LexerError> for ParserError {
91    fn from(e: LexerError) -> Self {
92        ParserError::LexerError(e)
93    }
94}
95
96impl From<int::Overflow> for ParserError {
97    fn from(_: int::Overflow) -> Self {
98        ParserError::IntegerOverflow
99    }
100}
101
102#[derive(Debug, thiserror::Error)]
103#[error("at {line}:{col}: {error}")]
104pub struct ParserErrorWithLocation {
105    #[source]
106    pub error: anyhow::Error,
107    /// 1-based
108    pub line: u32,
109    /// 1-based
110    pub col: u32,
111}
112
113trait ToI32 {
114    fn to_i32(&self) -> anyhow::Result<i32>;
115}
116
117trait ToI64 {
118    fn to_i64(&self) -> anyhow::Result<i64>;
119}
120
121impl ToI32 for u64 {
122    fn to_i32(&self) -> anyhow::Result<i32> {
123        if *self <= i32::max_value() as u64 {
124            Ok(*self as i32)
125        } else {
126            Err(ParserError::IntegerOverflow.into())
127        }
128    }
129}
130
131impl ToI32 for i64 {
132    fn to_i32(&self) -> anyhow::Result<i32> {
133        if *self <= i32::max_value() as i64 && *self >= i32::min_value() as i64 {
134            Ok(*self as i32)
135        } else {
136            Err(ParserError::IntegerOverflow.into())
137        }
138    }
139}
140
141impl ToI64 for u64 {
142    fn to_i64(&self) -> anyhow::Result<i64> {
143        if *self <= i64::max_value() as u64 {
144            Ok(*self as i64)
145        } else {
146            Err(ParserError::IntegerOverflow.into())
147        }
148    }
149}
150
151#[derive(Clone)]
152pub(crate) struct Parser<'a> {
153    pub tokenizer: Tokenizer<'a>,
154    syntax: Syntax,
155}
156
157#[derive(Copy, Clone)]
158enum MessageBodyParseMode {
159    MessageProto2,
160    MessageProto3,
161    Oneof,
162    ExtendProto2,
163    ExtendProto3,
164}
165
166impl MessageBodyParseMode {
167    fn label_allowed(&self, label: Rule) -> bool {
168        match label {
169            Rule::Repeated => match *self {
170                MessageBodyParseMode::MessageProto2
171                | MessageBodyParseMode::MessageProto3
172                | MessageBodyParseMode::ExtendProto2
173                | MessageBodyParseMode::ExtendProto3 => true,
174                MessageBodyParseMode::Oneof => false,
175            },
176            Rule::Optional => match *self {
177                MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::ExtendProto2 => true,
178                MessageBodyParseMode::MessageProto3 | MessageBodyParseMode::ExtendProto3 => true,
179                MessageBodyParseMode::Oneof => false,
180            },
181            Rule::Required => match *self {
182                MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::ExtendProto2 => true,
183                MessageBodyParseMode::MessageProto3 | MessageBodyParseMode::ExtendProto3 => false,
184                MessageBodyParseMode::Oneof => false,
185            },
186        }
187    }
188
189    fn some_label_required(&self) -> bool {
190        match *self {
191            MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::ExtendProto2 => true,
192            MessageBodyParseMode::MessageProto3
193            | MessageBodyParseMode::ExtendProto3
194            | MessageBodyParseMode::Oneof => false,
195        }
196    }
197
198    fn map_allowed(&self) -> bool {
199        match *self {
200            MessageBodyParseMode::MessageProto2
201            | MessageBodyParseMode::MessageProto3
202            | MessageBodyParseMode::ExtendProto2
203            | MessageBodyParseMode::ExtendProto3 => true,
204            MessageBodyParseMode::Oneof => false,
205        }
206    }
207
208    fn is_most_non_fields_allowed(&self) -> bool {
209        match *self {
210            MessageBodyParseMode::MessageProto2 | MessageBodyParseMode::MessageProto3 => true,
211            MessageBodyParseMode::ExtendProto2
212            | MessageBodyParseMode::ExtendProto3
213            | MessageBodyParseMode::Oneof => false,
214        }
215    }
216
217    fn is_option_allowed(&self) -> bool {
218        match *self {
219            MessageBodyParseMode::MessageProto2
220            | MessageBodyParseMode::MessageProto3
221            | MessageBodyParseMode::Oneof => true,
222            MessageBodyParseMode::ExtendProto2 | MessageBodyParseMode::ExtendProto3 => false,
223        }
224    }
225
226    fn is_extensions_allowed(&self) -> bool {
227        match self {
228            MessageBodyParseMode::MessageProto2 => true,
229            _ => false,
230        }
231    }
232}
233
234#[derive(Default)]
235pub(crate) struct MessageBody {
236    pub fields: Vec<WithLoc<FieldOrOneOf>>,
237    pub reserved_nums: Vec<RangeInclusive<i32>>,
238    pub reserved_names: Vec<String>,
239    pub messages: Vec<WithLoc<Message>>,
240    pub enums: Vec<WithLoc<Enumeration>>,
241    pub options: Vec<ProtobufOption>,
242    pub extension_ranges: Vec<RangeInclusive<i32>>,
243    pub extensions: Vec<WithLoc<Extension>>,
244}
245
246trait NumLitEx {
247    fn to_option_value(&self, sign_is_plus: bool) -> anyhow::Result<ProtobufConstant>;
248}
249
250impl NumLitEx for NumLit {
251    fn to_option_value(&self, sign_is_plus: bool) -> anyhow::Result<ProtobufConstant> {
252        Ok(match (*self, sign_is_plus) {
253            (NumLit::U64(u), true) => ProtobufConstant::U64(u),
254            (NumLit::F64(f), true) => ProtobufConstant::F64(f),
255            (NumLit::U64(u), false) => {
256                ProtobufConstant::I64(int::neg(u).map_err(|_| ParserError::IntegerOverflow)?)
257            }
258            (NumLit::F64(f), false) => ProtobufConstant::F64(-f),
259        })
260    }
261}
262
263impl<'a> Parser<'a> {
264    pub(crate) fn new(input: &'a str) -> Parser<'a> {
265        Parser {
266            tokenizer: Tokenizer::new(input, ParserLanguage::Proto),
267            syntax: Syntax::Proto2,
268        }
269    }
270
271    // Protobuf grammar
272
273    // fullIdent = ident { "." ident }
274    fn next_full_ident(&mut self) -> anyhow::Result<ProtobufPath> {
275        let mut full_ident = String::new();
276        // https://github.com/google/protobuf/issues/4563
277        if self.tokenizer.next_symbol_if_eq('.')? {
278            full_ident.push('.');
279        }
280        full_ident.push_str(&self.tokenizer.next_ident()?);
281        while self.tokenizer.next_symbol_if_eq('.')? {
282            full_ident.push('.');
283            full_ident.push_str(&self.tokenizer.next_ident()?);
284        }
285        Ok(ProtobufPath::new(full_ident))
286    }
287
288    // fullIdent = ident { "." ident }
289    fn next_full_ident_rel(&mut self) -> anyhow::Result<ProtobufRelPath> {
290        let mut full_ident = String::new();
291        full_ident.push_str(&self.tokenizer.next_ident()?);
292        while self.tokenizer.next_symbol_if_eq('.')? {
293            full_ident.push('.');
294            full_ident.push_str(&self.tokenizer.next_ident()?);
295        }
296        Ok(ProtobufRelPath::new(full_ident))
297    }
298
299    // emptyStatement = ";"
300    fn next_empty_statement_opt(&mut self) -> anyhow::Result<Option<()>> {
301        if self.tokenizer.next_symbol_if_eq(';')? {
302            Ok(Some(()))
303        } else {
304            Ok(None)
305        }
306    }
307
308    // messageName = ident
309    // enumName = ident
310    // messageType = [ "." ] { ident "." } messageName
311    // enumType = [ "." ] { ident "." } enumName
312    fn next_message_or_enum_type(&mut self) -> anyhow::Result<ProtobufPath> {
313        self.next_full_ident()
314    }
315
316    // groupName = capitalLetter { letter | decimalDigit | "_" }
317    fn next_group_name(&mut self) -> anyhow::Result<String> {
318        // lexer cannot distinguish between group name and other ident
319        let mut clone = self.clone();
320        let ident = clone.tokenizer.next_ident()?;
321        if !ident.chars().next().unwrap().is_ascii_uppercase() {
322            return Err(ParserError::GroupNameShouldStartWithUpperCase.into());
323        }
324        *self = clone;
325        Ok(ident)
326    }
327
328    // Boolean
329
330    // boolLit = "true" | "false"
331    fn next_bool_lit_opt(&mut self) -> anyhow::Result<Option<bool>> {
332        Ok(if self.tokenizer.next_ident_if_eq("true")? {
333            Some(true)
334        } else if self.tokenizer.next_ident_if_eq("false")? {
335            Some(false)
336        } else {
337            None
338        })
339    }
340
341    // Constant
342
343    fn next_num_lit(&mut self) -> anyhow::Result<NumLit> {
344        self.tokenizer
345            .next_token_check_map(|token| Ok(token.to_num_lit()?))
346    }
347
348    fn next_message_constant_field_name(
349        &mut self,
350    ) -> anyhow::Result<ProtobufConstantMessageFieldName> {
351        if self.tokenizer.next_symbol_if_eq('[')? {
352            let n = self.next_full_ident()?;
353            if self.tokenizer.next_symbol_if_eq('/')? {
354                let prefix = format!("{}", n);
355                let full_type_name = self.next_full_ident()?;
356                self.tokenizer
357                    .next_symbol_expect_eq(']', "message constant")?;
358                Ok(ProtobufConstantMessageFieldName::AnyTypeUrl(AnyTypeUrl {
359                    prefix,
360                    full_type_name,
361                }))
362            } else {
363                self.tokenizer
364                    .next_symbol_expect_eq(']', "message constant")?;
365                Ok(ProtobufConstantMessageFieldName::Extension(n))
366            }
367        } else {
368            let n = self.tokenizer.next_ident()?;
369            Ok(ProtobufConstantMessageFieldName::Regular(n))
370        }
371    }
372
373    fn next_message_constant(&mut self) -> anyhow::Result<ProtobufConstantMessage> {
374        let mut r = ProtobufConstantMessage::default();
375        self.tokenizer
376            .next_symbol_expect_eq('{', "message constant")?;
377        while !self.tokenizer.lookahead_is_symbol('}')? {
378            let n = self.next_message_constant_field_name()?;
379            let v = self.next_field_value()?;
380
381            // Consume the comma or semicolon if present. Commas and semicolons
382            // between message fields are optional, all these are valid:
383            //
384            //    {foo: 1,bar: 2,baz: 3,}
385            //    {foo: 1;bar: 2;baz: 3;}
386            //    {foo: 1 bar: 2 baz: 3}
387            //    {foo: 1,bar: 2;baz: 3}
388            //    {foo: 1,bar: 2 baz: 3}
389            //
390            self.tokenizer.next_symbol_if_in(&[',', ';'])?;
391
392            r.fields.insert(n, v);
393        }
394        self.tokenizer
395            .next_symbol_expect_eq('}', "message constant")?;
396        Ok(r)
397    }
398
399    fn next_list_constant(&mut self) -> anyhow::Result<Vec<ProtobufConstant>> {
400        self.tokenizer.next_symbol_expect_eq('[', "list constant")?;
401
402        let mut list = Vec::new();
403
404        // The list may be empty.
405        if self.tokenizer.next_symbol_if_eq(']')? {
406            return Ok(list);
407        }
408
409        list.push(self.next_constant()?);
410        while self.tokenizer.next_symbol_if_eq(',')? {
411            list.push(self.next_constant()?);
412        }
413
414        self.tokenizer.next_symbol_expect_eq(']', "list constant")?;
415
416        Ok(list)
417    }
418
419    // constant = fullIdent | ( [ "-" | "+" ] intLit ) | ( [ "-" | "+" ] floatLit ) |
420    //            strLit | boolLit | MessageValue
421    fn next_constant(&mut self) -> anyhow::Result<ProtobufConstant> {
422        // https://github.com/google/protobuf/blob/a21f225824e994ebd35e8447382ea4e0cd165b3c/src/google/protobuf/unittest_custom_options.proto#L350
423        if self.tokenizer.lookahead_is_symbol('{')? {
424            return Ok(ProtobufConstant::Message(self.next_message_constant()?));
425        }
426
427        if self.tokenizer.lookahead_is_symbol('[')? {
428            return Ok(ProtobufConstant::Repeated(self.next_list_constant()?));
429        }
430
431        if let Some(b) = self.next_bool_lit_opt()? {
432            return Ok(ProtobufConstant::Bool(b));
433        }
434
435        if let &Token::Symbol(c) = self.tokenizer.lookahead_some()? {
436            if c == '+' || c == '-' {
437                self.tokenizer.advance()?;
438                let sign = c == '+';
439                return Ok(self.next_num_lit()?.to_option_value(sign)?);
440            }
441        }
442
443        if let Some(r) = self.tokenizer.next_token_if_map(|token| match token {
444            &Token::StrLit(ref s) => Some(ProtobufConstant::String(s.clone())),
445            _ => None,
446        })? {
447            return Ok(r);
448        }
449
450        match self.tokenizer.lookahead_some()? {
451            &Token::IntLit(..) | &Token::FloatLit(..) => {
452                return self.next_num_lit()?.to_option_value(true);
453            }
454            &Token::Ident(..) => {
455                return Ok(ProtobufConstant::Ident(self.next_full_ident()?));
456            }
457            _ => {}
458        }
459
460        Err(ParserError::ExpectConstant.into())
461    }
462
463    fn next_field_value(&mut self) -> anyhow::Result<ProtobufConstant> {
464        if self.tokenizer.next_symbol_if_eq(':')? {
465            // Colon is optional when reading message constant.
466            self.next_constant()
467        } else {
468            Ok(ProtobufConstant::Message(self.next_message_constant()?))
469        }
470    }
471
472    fn next_int_lit(&mut self) -> anyhow::Result<u64> {
473        self.tokenizer.next_token_check_map(|token| match token {
474            &Token::IntLit(i) => Ok(i),
475            _ => Err(ParserError::IncorrectInput.into()),
476        })
477    }
478
479    // Syntax
480
481    // syntax = "syntax" "=" quote "proto2" quote ";"
482    // syntax = "syntax" "=" quote "proto3" quote ";"
483    fn next_syntax(&mut self) -> anyhow::Result<Option<Syntax>> {
484        if self.tokenizer.next_ident_if_eq("syntax")? {
485            self.tokenizer.next_symbol_expect_eq('=', "syntax")?;
486            let syntax_str = self.tokenizer.next_str_lit()?.decode_utf8()?;
487            let syntax = if syntax_str == "proto2" {
488                Syntax::Proto2
489            } else if syntax_str == "proto3" {
490                Syntax::Proto3
491            } else {
492                return Err(ParserError::UnknownSyntax.into());
493            };
494            self.tokenizer.next_symbol_expect_eq(';', "syntax")?;
495            Ok(Some(syntax))
496        } else {
497            Ok(None)
498        }
499    }
500
501    // Import Statement
502
503    // import = "import" [ "weak" | "public" ] strLit ";"
504    fn next_import_opt(&mut self) -> anyhow::Result<Option<model::Import>> {
505        if self.tokenizer.next_ident_if_eq("import")? {
506            let vis = if self.tokenizer.next_ident_if_eq("weak")? {
507                ImportVis::Weak
508            } else if self.tokenizer.next_ident_if_eq("public")? {
509                ImportVis::Public
510            } else {
511                ImportVis::Default
512            };
513            let path = self.tokenizer.next_str_lit()?.decode_utf8()?;
514            self.tokenizer.next_symbol_expect_eq(';', "import")?;
515            let path = ProtoPathBuf::new(path)?;
516            Ok(Some(model::Import { path, vis }))
517        } else {
518            Ok(None)
519        }
520    }
521
522    // Package
523
524    // package = "package" fullIdent ";"
525    fn next_package_opt(&mut self) -> anyhow::Result<Option<ProtobufAbsPath>> {
526        if self.tokenizer.next_ident_if_eq("package")? {
527            let package = self.next_full_ident_rel()?;
528            self.tokenizer.next_symbol_expect_eq(';', "package")?;
529            Ok(Some(package.into_absolute()))
530        } else {
531            Ok(None)
532        }
533    }
534
535    // Option
536
537    fn next_ident(&mut self) -> anyhow::Result<ProtobufIdent> {
538        Ok(ProtobufIdent::from(self.tokenizer.next_ident()?))
539    }
540
541    fn next_option_name_component(&mut self) -> anyhow::Result<ProtobufOptionNamePart> {
542        if self.tokenizer.next_symbol_if_eq('(')? {
543            let comp = self.next_full_ident()?;
544            self.tokenizer
545                .next_symbol_expect_eq(')', "option name component")?;
546            Ok(ProtobufOptionNamePart::Ext(comp))
547        } else {
548            Ok(ProtobufOptionNamePart::Direct(self.next_ident()?))
549        }
550    }
551
552    // https://github.com/google/protobuf/issues/4563
553    // optionName = ( ident | "(" fullIdent ")" ) { "." ident }
554    fn next_option_name(&mut self) -> anyhow::Result<ProtobufOptionName> {
555        let mut components = Vec::new();
556        components.push(self.next_option_name_component()?);
557        while self.tokenizer.next_symbol_if_eq('.')? {
558            components.push(self.next_option_name_component()?);
559        }
560        if components.len() == 1 {
561            if let ProtobufOptionNamePart::Direct(n) = &components[0] {
562                return Ok(ProtobufOptionName::Builtin(n.clone()));
563            }
564        }
565        Ok(ProtobufOptionName::Ext(ProtobufOptionNameExt(components)))
566    }
567
568    // option = "option" optionName  "=" constant ";"
569    fn next_option_opt(&mut self) -> anyhow::Result<Option<ProtobufOption>> {
570        if self.tokenizer.next_ident_if_eq("option")? {
571            let name = self.next_option_name()?;
572            self.tokenizer.next_symbol_expect_eq('=', "option")?;
573            let value = self.next_constant()?;
574            self.tokenizer.next_symbol_expect_eq(';', "option")?;
575            Ok(Some(ProtobufOption { name, value }))
576        } else {
577            Ok(None)
578        }
579    }
580
581    // Fields
582
583    // label = "required" | "optional" | "repeated"
584    fn next_label(&mut self, mode: MessageBodyParseMode) -> anyhow::Result<Option<Rule>> {
585        for rule in Rule::ALL {
586            let mut clone = self.clone();
587            if clone.tokenizer.next_ident_if_eq(rule.as_str())? {
588                if !mode.label_allowed(rule) {
589                    return Err(ParserError::LabelNotAllowed.into());
590                }
591
592                *self = clone;
593                return Ok(Some(rule));
594            }
595        }
596
597        if mode.some_label_required() {
598            Err(ParserError::LabelRequired.into())
599        } else {
600            Ok(None)
601        }
602    }
603
604    fn next_field_type(&mut self) -> anyhow::Result<FieldType> {
605        let simple = &[
606            ("int32", FieldType::Int32),
607            ("int64", FieldType::Int64),
608            ("uint32", FieldType::Uint32),
609            ("uint64", FieldType::Uint64),
610            ("sint32", FieldType::Sint32),
611            ("sint64", FieldType::Sint64),
612            ("fixed32", FieldType::Fixed32),
613            ("sfixed32", FieldType::Sfixed32),
614            ("fixed64", FieldType::Fixed64),
615            ("sfixed64", FieldType::Sfixed64),
616            ("bool", FieldType::Bool),
617            ("string", FieldType::String),
618            ("bytes", FieldType::Bytes),
619            ("float", FieldType::Float),
620            ("double", FieldType::Double),
621        ];
622        for &(ref n, ref t) in simple {
623            if self.tokenizer.next_ident_if_eq(n)? {
624                return Ok(t.clone());
625            }
626        }
627
628        if let Some(t) = self.next_map_field_type_opt()? {
629            return Ok(t);
630        }
631
632        let message_or_enum = self.next_message_or_enum_type()?;
633        Ok(FieldType::MessageOrEnum(message_or_enum))
634    }
635
636    fn next_field_number(&mut self) -> anyhow::Result<i32> {
637        // TODO: not all integers are valid field numbers
638        self.tokenizer.next_token_check_map(|token| match token {
639            &Token::IntLit(i) => i.to_i32(),
640            _ => Err(ParserError::IncorrectInput.into()),
641        })
642    }
643
644    // fieldOption = optionName "=" constant
645    fn next_field_option(&mut self) -> anyhow::Result<ProtobufOption> {
646        let name = self.next_option_name()?;
647        self.tokenizer.next_symbol_expect_eq('=', "field option")?;
648        let value = self.next_constant()?;
649        Ok(ProtobufOption { name, value })
650    }
651
652    // fieldOptions = fieldOption { ","  fieldOption }
653    fn next_field_options(&mut self) -> anyhow::Result<Vec<ProtobufOption>> {
654        let mut options = Vec::new();
655
656        options.push(self.next_field_option()?);
657
658        while self.tokenizer.next_symbol_if_eq(',')? {
659            options.push(self.next_field_option()?);
660        }
661
662        Ok(options)
663    }
664
665    // field = label type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
666    // group = label "group" groupName "=" fieldNumber messageBody
667    fn next_field(&mut self, mode: MessageBodyParseMode) -> anyhow::Result<WithLoc<Field>> {
668        let loc = self.tokenizer.lookahead_loc();
669        let rule = if self.clone().tokenizer.next_ident_if_eq("map")? {
670            if !mode.map_allowed() {
671                return Err(ParserError::MapFieldNotAllowed.into());
672            }
673            None
674        } else {
675            self.next_label(mode)?
676        };
677        if self.tokenizer.next_ident_if_eq("group")? {
678            let name = self.next_group_name()?.to_owned();
679            self.tokenizer.next_symbol_expect_eq('=', "group")?;
680            let number = self.next_field_number()?;
681
682            let mode = match self.syntax {
683                Syntax::Proto2 => MessageBodyParseMode::MessageProto2,
684                Syntax::Proto3 => MessageBodyParseMode::MessageProto3,
685            };
686
687            let MessageBody { fields, .. } = self.next_message_body(mode)?;
688
689            let fields = fields
690                .into_iter()
691                .map(|fo| match fo.t {
692                    FieldOrOneOf::Field(f) => Ok(f),
693                    FieldOrOneOf::OneOf(_) => Err(ParserError::OneOfInGroup),
694                })
695                .collect::<Result<_, ParserError>>()?;
696
697            let field = Field {
698                // The field name is a lowercased version of the type name
699                // (which has been verified to start with an uppercase letter).
700                // https://git.io/JvxAP
701                name: name.to_ascii_lowercase(),
702                rule,
703                typ: FieldType::Group(Group { name, fields }),
704                number,
705                options: Vec::new(),
706            };
707            Ok(WithLoc { t: field, loc })
708        } else {
709            let typ = self.next_field_type()?;
710            let name = self.tokenizer.next_ident()?.to_owned();
711            self.tokenizer.next_symbol_expect_eq('=', "field")?;
712            let number = self.next_field_number()?;
713
714            let mut options = Vec::new();
715
716            if self.tokenizer.next_symbol_if_eq('[')? {
717                for o in self.next_field_options()? {
718                    options.push(o);
719                }
720                self.tokenizer.next_symbol_expect_eq(']', "field")?;
721            }
722            self.tokenizer.next_symbol_expect_eq(';', "field")?;
723            let field = Field {
724                name,
725                rule,
726                typ,
727                number,
728                options,
729            };
730            Ok(WithLoc { t: field, loc })
731        }
732    }
733
734    // oneof = "oneof" oneofName "{" { oneofField | emptyStatement } "}"
735    // oneofField = type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
736    fn next_oneof_opt(&mut self) -> anyhow::Result<Option<OneOf>> {
737        if self.tokenizer.next_ident_if_eq("oneof")? {
738            let name = self.tokenizer.next_ident()?.to_owned();
739            let MessageBody {
740                fields, options, ..
741            } = self.next_message_body(MessageBodyParseMode::Oneof)?;
742            let fields = fields
743                .into_iter()
744                .map(|fo| match fo.t {
745                    FieldOrOneOf::Field(f) => Ok(f),
746                    FieldOrOneOf::OneOf(_) => Err(ParserError::OneOfInOneOf),
747                })
748                .collect::<Result<_, ParserError>>()?;
749            Ok(Some(OneOf {
750                name,
751                fields,
752                options,
753            }))
754        } else {
755            Ok(None)
756        }
757    }
758
759    // mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
760    // keyType = "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" |
761    //           "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string"
762    fn next_map_field_type_opt(&mut self) -> anyhow::Result<Option<FieldType>> {
763        if self.tokenizer.next_ident_if_eq("map")? {
764            self.tokenizer
765                .next_symbol_expect_eq('<', "map field type")?;
766            // TODO: restrict key types
767            let key = self.next_field_type()?;
768            self.tokenizer
769                .next_symbol_expect_eq(',', "map field type")?;
770            let value = self.next_field_type()?;
771            self.tokenizer
772                .next_symbol_expect_eq('>', "map field type")?;
773            Ok(Some(FieldType::Map(Box::new((key, value)))))
774        } else {
775            Ok(None)
776        }
777    }
778
779    // Extensions and Reserved
780
781    // Extensions
782
783    // range =  intLit [ "to" ( intLit | "max" ) ]
784    fn next_range(&mut self) -> anyhow::Result<RangeInclusive<i32>> {
785        let from = self.next_field_number()?;
786        let to = if self.tokenizer.next_ident_if_eq("to")? {
787            if self.tokenizer.next_ident_if_eq("max")? {
788                0x20000000 - 1
789            } else {
790                self.next_field_number()?
791            }
792        } else {
793            from
794        };
795        Ok(from..=to)
796    }
797
798    // ranges = range { "," range }
799    fn next_ranges(&mut self) -> anyhow::Result<Vec<RangeInclusive<i32>>> {
800        let mut ranges = Vec::new();
801        ranges.push(self.next_range()?);
802        while self.tokenizer.next_symbol_if_eq(',')? {
803            ranges.push(self.next_range()?);
804        }
805        Ok(ranges)
806    }
807
808    // extensions = "extensions" ranges ";"
809    fn next_extensions_opt(&mut self) -> anyhow::Result<Option<Vec<RangeInclusive<i32>>>> {
810        if self.tokenizer.next_ident_if_eq("extensions")? {
811            Ok(Some(self.next_ranges()?))
812        } else {
813            Ok(None)
814        }
815    }
816
817    // Reserved
818
819    // Grammar is incorrect: https://github.com/google/protobuf/issues/4558
820    // reserved = "reserved" ( ranges | fieldNames ) ";"
821    // fieldNames = fieldName { "," fieldName }
822    fn next_reserved_opt(
823        &mut self,
824    ) -> anyhow::Result<Option<(Vec<RangeInclusive<i32>>, Vec<String>)>> {
825        if self.tokenizer.next_ident_if_eq("reserved")? {
826            let (ranges, names) = if let &Token::StrLit(..) = self.tokenizer.lookahead_some()? {
827                let mut names = Vec::new();
828                names.push(self.tokenizer.next_str_lit()?.decode_utf8()?);
829                while self.tokenizer.next_symbol_if_eq(',')? {
830                    names.push(self.tokenizer.next_str_lit()?.decode_utf8()?);
831                }
832                (Vec::new(), names)
833            } else {
834                (self.next_ranges()?, Vec::new())
835            };
836
837            self.tokenizer.next_symbol_expect_eq(';', "reserved")?;
838
839            Ok(Some((ranges, names)))
840        } else {
841            Ok(None)
842        }
843    }
844
845    // Top Level definitions
846
847    // Enum definition
848
849    // enumValueOption = optionName "=" constant
850    fn next_enum_value_option(&mut self) -> anyhow::Result<ProtobufOption> {
851        let name = self.next_option_name()?;
852        self.tokenizer
853            .next_symbol_expect_eq('=', "enum value option")?;
854        let value = self.next_constant()?;
855        Ok(ProtobufOption { name, value })
856    }
857
858    // https://github.com/google/protobuf/issues/4561
859    fn next_enum_value(&mut self) -> anyhow::Result<i32> {
860        let minus = self.tokenizer.next_symbol_if_eq('-')?;
861        let lit = self.next_int_lit()?;
862        Ok(if minus {
863            let unsigned = lit.to_i64()?;
864            match unsigned.checked_neg() {
865                Some(neg) => neg.to_i32()?,
866                None => return Err(ParserError::IntegerOverflow.into()),
867            }
868        } else {
869            lit.to_i32()?
870        })
871    }
872
873    // enumField = ident "=" intLit [ "[" enumValueOption { ","  enumValueOption } "]" ]";"
874    fn next_enum_field(&mut self) -> anyhow::Result<EnumValue> {
875        let name = self.tokenizer.next_ident()?.to_owned();
876        self.tokenizer.next_symbol_expect_eq('=', "enum field")?;
877        let number = self.next_enum_value()?;
878        let mut options = Vec::new();
879        if self.tokenizer.next_symbol_if_eq('[')? {
880            options.push(self.next_enum_value_option()?);
881            while self.tokenizer.next_symbol_if_eq(',')? {
882                options.push(self.next_enum_value_option()?);
883            }
884            self.tokenizer.next_symbol_expect_eq(']', "enum field")?;
885        }
886
887        Ok(EnumValue {
888            name,
889            number,
890            options,
891        })
892    }
893
894    // enum = "enum" enumName enumBody
895    // enumBody = "{" { option | enumField | emptyStatement | reserved } "}"
896    fn next_enum_opt(&mut self) -> anyhow::Result<Option<WithLoc<Enumeration>>> {
897        let loc = self.tokenizer.lookahead_loc();
898
899        if self.tokenizer.next_ident_if_eq("enum")? {
900            let name = self.tokenizer.next_ident()?.to_owned();
901
902            let mut values = Vec::new();
903            let mut options = Vec::new();
904            let mut reserved_nums = Vec::new();
905            let mut reserved_names = Vec::new();
906
907            self.tokenizer.next_symbol_expect_eq('{', "enum")?;
908            while self.tokenizer.lookahead_if_symbol()? != Some('}') {
909                // emptyStatement
910                if self.tokenizer.next_symbol_if_eq(';')? {
911                    continue;
912                }
913
914                if let Some((field_nums, field_names)) = self.next_reserved_opt()? {
915                    reserved_nums.extend(field_nums);
916                    reserved_names.extend(field_names);
917                    continue;
918                }
919
920                if let Some(o) = self.next_option_opt()? {
921                    options.push(o);
922                    continue;
923                }
924
925                values.push(self.next_enum_field()?);
926            }
927            self.tokenizer.next_symbol_expect_eq('}', "enum")?;
928            let enumeration = Enumeration {
929                name,
930                values,
931                options,
932                reserved_nums,
933                reserved_names,
934            };
935            Ok(Some(WithLoc {
936                loc,
937                t: enumeration,
938            }))
939        } else {
940            Ok(None)
941        }
942    }
943
944    // Message definition
945
946    // messageBody = "{" { field | enum | message | extend | extensions | group |
947    //               option | oneof | mapField | reserved | emptyStatement } "}"
948    fn next_message_body(&mut self, mode: MessageBodyParseMode) -> anyhow::Result<MessageBody> {
949        self.tokenizer.next_symbol_expect_eq('{', "message body")?;
950
951        let mut r = MessageBody::default();
952
953        while self.tokenizer.lookahead_if_symbol()? != Some('}') {
954            let loc = self.tokenizer.lookahead_loc();
955
956            // emptyStatement
957            if self.tokenizer.next_symbol_if_eq(';')? {
958                continue;
959            }
960
961            if mode.is_most_non_fields_allowed() {
962                if let Some((field_nums, field_names)) = self.next_reserved_opt()? {
963                    r.reserved_nums.extend(field_nums);
964                    r.reserved_names.extend(field_names);
965                    continue;
966                }
967
968                if let Some(oneof) = self.next_oneof_opt()? {
969                    let one_of = FieldOrOneOf::OneOf(oneof);
970                    r.fields.push(WithLoc { t: one_of, loc });
971                    continue;
972                }
973
974                if let Some(extensions) = self.next_extend_opt()? {
975                    r.extensions.extend(extensions);
976                    continue;
977                }
978
979                if let Some(nested_message) = self.next_message_opt()? {
980                    r.messages.push(nested_message);
981                    continue;
982                }
983
984                if let Some(nested_enum) = self.next_enum_opt()? {
985                    r.enums.push(nested_enum);
986                    continue;
987                }
988            } else {
989                self.tokenizer.next_ident_if_eq_error("reserved")?;
990                self.tokenizer.next_ident_if_eq_error("oneof")?;
991                self.tokenizer.next_ident_if_eq_error("extend")?;
992                self.tokenizer.next_ident_if_eq_error("message")?;
993                self.tokenizer.next_ident_if_eq_error("enum")?;
994            }
995
996            if mode.is_extensions_allowed() {
997                if let Some(extension_ranges) = self.next_extensions_opt()? {
998                    r.extension_ranges.extend(extension_ranges);
999                    continue;
1000                }
1001            } else {
1002                self.tokenizer.next_ident_if_eq_error("extensions")?;
1003            }
1004
1005            if mode.is_option_allowed() {
1006                if let Some(option) = self.next_option_opt()? {
1007                    r.options.push(option);
1008                    continue;
1009                }
1010            } else {
1011                self.tokenizer.next_ident_if_eq_error("option")?;
1012            }
1013
1014            let field = FieldOrOneOf::Field(self.next_field(mode)?);
1015            r.fields.push(WithLoc { t: field, loc });
1016        }
1017
1018        self.tokenizer.next_symbol_expect_eq('}', "message body")?;
1019
1020        Ok(r)
1021    }
1022
1023    // message = "message" messageName messageBody
1024    fn next_message_opt(&mut self) -> anyhow::Result<Option<WithLoc<Message>>> {
1025        let loc = self.tokenizer.lookahead_loc();
1026
1027        if self.tokenizer.next_ident_if_eq("message")? {
1028            let name = self.tokenizer.next_ident()?.to_owned();
1029
1030            let mode = match self.syntax {
1031                Syntax::Proto2 => MessageBodyParseMode::MessageProto2,
1032                Syntax::Proto3 => MessageBodyParseMode::MessageProto3,
1033            };
1034
1035            let MessageBody {
1036                fields,
1037                reserved_nums,
1038                reserved_names,
1039                messages,
1040                enums,
1041                options,
1042                extensions,
1043                extension_ranges,
1044            } = self.next_message_body(mode)?;
1045
1046            let message = Message {
1047                name,
1048                fields,
1049                reserved_nums,
1050                reserved_names,
1051                messages,
1052                enums,
1053                options,
1054                extensions,
1055                extension_ranges,
1056            };
1057            Ok(Some(WithLoc { t: message, loc }))
1058        } else {
1059            Ok(None)
1060        }
1061    }
1062
1063    // Extend
1064
1065    // extend = "extend" messageType "{" {field | group | emptyStatement} "}"
1066    fn next_extend_opt(&mut self) -> anyhow::Result<Option<Vec<WithLoc<Extension>>>> {
1067        let mut clone = self.clone();
1068        if clone.tokenizer.next_ident_if_eq("extend")? {
1069            // According to spec `extend` is only for `proto2`, but it is used in `proto3`
1070            // https://github.com/google/protobuf/issues/4610
1071
1072            *self = clone;
1073
1074            let extendee = self.next_message_or_enum_type()?;
1075
1076            let mode = match self.syntax {
1077                Syntax::Proto2 => MessageBodyParseMode::ExtendProto2,
1078                Syntax::Proto3 => MessageBodyParseMode::ExtendProto3,
1079            };
1080
1081            let MessageBody { fields, .. } = self.next_message_body(mode)?;
1082
1083            // TODO: is oneof allowed in extend?
1084            let fields: Vec<WithLoc<Field>> = fields
1085                .into_iter()
1086                .map(|fo| match fo.t {
1087                    FieldOrOneOf::Field(f) => Ok(f),
1088                    FieldOrOneOf::OneOf(_) => Err(ParserError::OneOfInExtend),
1089                })
1090                .collect::<Result<_, ParserError>>()?;
1091
1092            let extensions = fields
1093                .into_iter()
1094                .map(|field| {
1095                    let extendee = extendee.clone();
1096                    let loc = field.loc;
1097                    let extension = Extension { extendee, field };
1098                    WithLoc { t: extension, loc }
1099                })
1100                .collect();
1101
1102            Ok(Some(extensions))
1103        } else {
1104            Ok(None)
1105        }
1106    }
1107
1108    // Service definition
1109
1110    fn next_options_or_colon(&mut self) -> anyhow::Result<Vec<ProtobufOption>> {
1111        let mut options = Vec::new();
1112        if self.tokenizer.next_symbol_if_eq('{')? {
1113            while self.tokenizer.lookahead_if_symbol()? != Some('}') {
1114                if let Some(option) = self.next_option_opt()? {
1115                    options.push(option);
1116                    continue;
1117                }
1118
1119                if let Some(()) = self.next_empty_statement_opt()? {
1120                    continue;
1121                }
1122
1123                return Err(ParserError::IncorrectInput.into());
1124            }
1125            self.tokenizer.next_symbol_expect_eq('}', "option")?;
1126        } else {
1127            self.tokenizer.next_symbol_expect_eq(';', "option")?;
1128        }
1129
1130        Ok(options)
1131    }
1132
1133    // stream = "stream" streamName "(" messageType "," messageType ")"
1134    //        (( "{" { option | emptyStatement } "}") | ";" )
1135    fn next_stream_opt(&mut self) -> anyhow::Result<Option<Method>> {
1136        assert_eq!(Syntax::Proto2, self.syntax);
1137        if self.tokenizer.next_ident_if_eq("stream")? {
1138            let name = self.tokenizer.next_ident()?;
1139            self.tokenizer.next_symbol_expect_eq('(', "stream")?;
1140            let input_type = self.next_message_or_enum_type()?;
1141            self.tokenizer.next_symbol_expect_eq(',', "stream")?;
1142            let output_type = self.next_message_or_enum_type()?;
1143            self.tokenizer.next_symbol_expect_eq(')', "stream")?;
1144            let options = self.next_options_or_colon()?;
1145            Ok(Some(Method {
1146                name,
1147                input_type,
1148                output_type,
1149                client_streaming: true,
1150                server_streaming: true,
1151                options,
1152            }))
1153        } else {
1154            Ok(None)
1155        }
1156    }
1157
1158    // rpc = "rpc" rpcName "(" [ "stream" ] messageType ")"
1159    //     "returns" "(" [ "stream" ] messageType ")"
1160    //     (( "{" { option | emptyStatement } "}" ) | ";" )
1161    fn next_rpc_opt(&mut self) -> anyhow::Result<Option<Method>> {
1162        if self.tokenizer.next_ident_if_eq("rpc")? {
1163            let name = self.tokenizer.next_ident()?;
1164            self.tokenizer.next_symbol_expect_eq('(', "rpc")?;
1165            let client_streaming = self.tokenizer.next_ident_if_eq("stream")?;
1166            let input_type = self.next_message_or_enum_type()?;
1167            self.tokenizer.next_symbol_expect_eq(')', "rpc")?;
1168            self.tokenizer.next_ident_expect_eq("returns")?;
1169            self.tokenizer.next_symbol_expect_eq('(', "rpc")?;
1170            let server_streaming = self.tokenizer.next_ident_if_eq("stream")?;
1171            let output_type = self.next_message_or_enum_type()?;
1172            self.tokenizer.next_symbol_expect_eq(')', "rpc")?;
1173            let options = self.next_options_or_colon()?;
1174            Ok(Some(Method {
1175                name,
1176                input_type,
1177                output_type,
1178                client_streaming,
1179                server_streaming,
1180                options,
1181            }))
1182        } else {
1183            Ok(None)
1184        }
1185    }
1186
1187    // proto2:
1188    // service = "service" serviceName "{" { option | rpc | stream | emptyStatement } "}"
1189    //
1190    // proto3:
1191    // service = "service" serviceName "{" { option | rpc | emptyStatement } "}"
1192    fn next_service_opt(&mut self) -> anyhow::Result<Option<WithLoc<Service>>> {
1193        let loc = self.tokenizer.lookahead_loc();
1194
1195        if self.tokenizer.next_ident_if_eq("service")? {
1196            let name = self.tokenizer.next_ident()?;
1197            let mut methods = Vec::new();
1198            let mut options = Vec::new();
1199            self.tokenizer.next_symbol_expect_eq('{', "service")?;
1200            while self.tokenizer.lookahead_if_symbol()? != Some('}') {
1201                if let Some(method) = self.next_rpc_opt()? {
1202                    methods.push(method);
1203                    continue;
1204                }
1205
1206                if self.syntax == Syntax::Proto2 {
1207                    if let Some(method) = self.next_stream_opt()? {
1208                        methods.push(method);
1209                        continue;
1210                    }
1211                }
1212
1213                if let Some(o) = self.next_option_opt()? {
1214                    options.push(o);
1215                    continue;
1216                }
1217
1218                if let Some(()) = self.next_empty_statement_opt()? {
1219                    continue;
1220                }
1221
1222                return Err(ParserError::IncorrectInput.into());
1223            }
1224            self.tokenizer.next_symbol_expect_eq('}', "service")?;
1225            Ok(Some(WithLoc {
1226                loc,
1227                t: Service {
1228                    name,
1229                    methods,
1230                    options,
1231                },
1232            }))
1233        } else {
1234            Ok(None)
1235        }
1236    }
1237
1238    // Proto file
1239
1240    // proto = syntax { import | package | option | topLevelDef | emptyStatement }
1241    // topLevelDef = message | enum | extend | service
1242    pub fn next_proto(&mut self) -> anyhow::Result<FileDescriptor> {
1243        let syntax = self.next_syntax()?.unwrap_or(Syntax::Proto2);
1244        self.syntax = syntax;
1245
1246        let mut imports = Vec::new();
1247        let mut package = ProtobufAbsPath::root();
1248        let mut messages = Vec::new();
1249        let mut enums = Vec::new();
1250        let mut extensions = Vec::new();
1251        let mut options = Vec::new();
1252        let mut services = Vec::new();
1253
1254        while !self.tokenizer.syntax_eof()? {
1255            if let Some(import) = self.next_import_opt()? {
1256                imports.push(import);
1257                continue;
1258            }
1259
1260            if let Some(next_package) = self.next_package_opt()? {
1261                package = next_package;
1262                continue;
1263            }
1264
1265            if let Some(option) = self.next_option_opt()? {
1266                options.push(option);
1267                continue;
1268            }
1269
1270            if let Some(message) = self.next_message_opt()? {
1271                messages.push(message);
1272                continue;
1273            }
1274
1275            if let Some(enumeration) = self.next_enum_opt()? {
1276                enums.push(enumeration);
1277                continue;
1278            }
1279
1280            if let Some(more_extensions) = self.next_extend_opt()? {
1281                extensions.extend(more_extensions);
1282                continue;
1283            }
1284
1285            if let Some(service) = self.next_service_opt()? {
1286                services.push(service);
1287                continue;
1288            }
1289
1290            if self.tokenizer.next_symbol_if_eq(';')? {
1291                continue;
1292            }
1293
1294            return Err(ParserError::IncorrectInput.into());
1295        }
1296
1297        Ok(FileDescriptor {
1298            imports,
1299            package,
1300            syntax,
1301            messages,
1302            enums,
1303            extensions,
1304            services,
1305            options,
1306        })
1307    }
1308}
1309
1310#[cfg(test)]
1311mod test {
1312    use super::*;
1313
1314    fn parse<P, R>(input: &str, parse_what: P) -> R
1315    where
1316        P: FnOnce(&mut Parser) -> anyhow::Result<R>,
1317    {
1318        let mut parser = Parser::new(input);
1319        let r =
1320            parse_what(&mut parser).expect(&format!("parse failed at {}", parser.tokenizer.loc()));
1321        let eof = parser
1322            .tokenizer
1323            .syntax_eof()
1324            .expect(&format!("check eof failed at {}", parser.tokenizer.loc()));
1325        assert!(eof, "{}", parser.tokenizer.loc());
1326        r
1327    }
1328
1329    fn parse_opt<P, R>(input: &str, parse_what: P) -> R
1330    where
1331        P: FnOnce(&mut Parser) -> anyhow::Result<Option<R>>,
1332    {
1333        let mut parser = Parser::new(input);
1334        let o =
1335            parse_what(&mut parser).expect(&format!("parse failed at {}", parser.tokenizer.loc()));
1336        let r = o.expect(&format!(
1337            "parser returned none at {}",
1338            parser.tokenizer.loc()
1339        ));
1340        assert!(parser.tokenizer.syntax_eof().unwrap());
1341        r
1342    }
1343
1344    #[test]
1345    fn test_syntax() {
1346        let msg = r#"  syntax = "proto3";  "#;
1347        let mess = parse_opt(msg, |p| p.next_syntax());
1348        assert_eq!(Syntax::Proto3, mess);
1349    }
1350
1351    #[test]
1352    fn test_field_default_value_int() {
1353        let msg = r#"  optional int64 f = 4 [default = 12];  "#;
1354        let mess = parse(msg, |p| p.next_field(MessageBodyParseMode::MessageProto2));
1355        assert_eq!("f", mess.t.name);
1356        assert_eq!(
1357            ProtobufOptionName::simple("default"),
1358            mess.t.options[0].name
1359        );
1360        assert_eq!("12", mess.t.options[0].value.format());
1361    }
1362
1363    #[test]
1364    fn test_field_default_value_float() {
1365        let msg = r#"  optional float f = 2 [default = 10.0];  "#;
1366        let mess = parse(msg, |p| p.next_field(MessageBodyParseMode::MessageProto2));
1367        assert_eq!("f", mess.t.name);
1368        assert_eq!(
1369            ProtobufOptionName::simple("default"),
1370            mess.t.options[0].name
1371        );
1372        assert_eq!("10", mess.t.options[0].value.format());
1373    }
1374
1375    #[test]
1376    fn test_field_options() {
1377        let msg = r#" (my_opt).my_field = {foo: 1 bar: 2} "#;
1378        let opt = parse(msg, |p| p.next_field_option());
1379        assert_eq!(r#"{ foo: 1 bar: 2 }"#, opt.value.format());
1380
1381        let msg = r#" (my_opt).my_field = {foo: 1; bar:2;} "#;
1382        let opt = parse(msg, |p| p.next_field_option());
1383        assert_eq!(r#"{ foo: 1 bar: 2 }"#, opt.value.format());
1384
1385        let msg = r#" (my_opt).my_field = {foo: 1, bar: 2} "#;
1386        let opt = parse(msg, |p| p.next_field_option());
1387        assert_eq!(r#"{ foo: 1 bar: 2 }"#, opt.value.format());
1388
1389        let msg = r#" (my_opt).my_field = "foo" "#;
1390        let opt = parse(msg, |p| p.next_field_option());
1391        assert_eq!(r#""foo""#, opt.value.format());
1392
1393        let msg = r#" (my_opt) = { my_field: "foo"} "#;
1394        let opt = parse(msg, |p| p.next_field_option());
1395        assert_eq!(r#"{ my_field: "foo" }"#, opt.value.format());
1396
1397        let msg = r#" (my_opt) = { my_field: [] } "#;
1398        let opt = parse(msg, |p| p.next_field_option());
1399        assert_eq!(r#"{ my_field: [] }"#, opt.value.format());
1400
1401        let msg = r#" (my_opt) = { my_field: ["foo", "bar"] } "#;
1402        let opt = parse(msg, |p| p.next_field_option());
1403        assert_eq!(r#"{ my_field: ["foo","bar"] }"#, opt.value.format());
1404
1405        let msg = r#" (my_opt) = { my_field: [1, 2] } "#;
1406        let opt = parse(msg, |p| p.next_field_option());
1407        assert_eq!(r#"{ my_field: [1,2] }"#, opt.value.format());
1408    }
1409
1410    #[test]
1411    fn test_message() {
1412        let msg = r#"message ReferenceData
1413    {
1414        repeated ScenarioInfo  scenarioSet = 1;
1415        repeated CalculatedObjectInfo calculatedObjectSet = 2;
1416        repeated RiskFactorList riskFactorListSet = 3;
1417        repeated RiskMaturityInfo riskMaturitySet = 4;
1418        repeated IndicatorInfo indicatorSet = 5;
1419        repeated RiskStrikeInfo riskStrikeSet = 6;
1420        repeated FreeProjectionList freeProjectionListSet = 7;
1421        repeated ValidationProperty ValidationSet = 8;
1422        repeated CalcProperties calcPropertiesSet = 9;
1423        repeated MaturityInfo maturitySet = 10;
1424    }"#;
1425
1426        let mess = parse_opt(msg, |p| p.next_message_opt());
1427        assert_eq!(10, mess.t.fields.len());
1428    }
1429
1430    #[test]
1431    fn test_enum() {
1432        let msg = r#"enum PairingStatus {
1433                DEALPAIRED        = 0;
1434                INVENTORYORPHAN   = 1;
1435                CALCULATEDORPHAN  = 2;
1436                CANCELED          = 3;
1437    }"#;
1438
1439        let enumeration = parse_opt(msg, |p| p.next_enum_opt());
1440        assert_eq!(4, enumeration.values.len());
1441    }
1442
1443    #[test]
1444    fn test_ignore() {
1445        let msg = r#"option optimize_for = SPEED;"#;
1446
1447        parse_opt(msg, |p| p.next_option_opt());
1448    }
1449
1450    #[test]
1451    fn test_import() {
1452        let msg = r#"syntax = "proto3";
1453
1454    import "test_import_nested_imported_pb.proto";
1455
1456    message ContainsImportedNested {
1457        ContainerForNested.NestedMessage m = 1;
1458        ContainerForNested.NestedEnum e = 2;
1459    }
1460    "#;
1461        let desc = parse(msg, |p| p.next_proto());
1462
1463        assert_eq!(
1464            vec!["test_import_nested_imported_pb.proto"],
1465            desc.imports
1466                .into_iter()
1467                .map(|i| i.path.to_str().to_owned())
1468                .collect::<Vec<_>>()
1469        );
1470    }
1471
1472    #[test]
1473    fn test_nested_message() {
1474        let msg = r#"message A
1475    {
1476        message B {
1477            repeated int32 a = 1;
1478            optional string b = 2;
1479        }
1480        optional string b = 1;
1481    }"#;
1482
1483        let mess = parse_opt(msg, |p| p.next_message_opt());
1484        assert_eq!(1, mess.t.messages.len());
1485    }
1486
1487    #[test]
1488    fn test_map() {
1489        let msg = r#"message A
1490    {
1491        optional map<string, int32> b = 1;
1492    }"#;
1493
1494        let mess = parse_opt(msg, |p| p.next_message_opt());
1495        assert_eq!(1, mess.t.fields.len());
1496        match mess.t.regular_fields_for_test()[0].typ {
1497            FieldType::Map(ref f) => match &**f {
1498                &(FieldType::String, FieldType::Int32) => (),
1499                ref f => panic!("Expecting Map<String, Int32> found {:?}", f),
1500            },
1501            ref f => panic!("Expecting map, got {:?}", f),
1502        }
1503    }
1504
1505    #[test]
1506    fn test_oneof() {
1507        let msg = r#"message A
1508    {
1509        optional int32 a1 = 1;
1510        oneof a_oneof {
1511            string a2 = 2;
1512            int32 a3 = 3;
1513            bytes a4 = 4;
1514        }
1515        repeated bool a5 = 5;
1516    }"#;
1517
1518        let mess = parse_opt(msg, |p| p.next_message_opt());
1519        assert_eq!(1, mess.t.oneofs().len());
1520        assert_eq!(3, mess.t.oneofs()[0].fields.len());
1521    }
1522
1523    #[test]
1524    fn test_reserved_in_message() {
1525        let msg = r#"message Sample {
1526       reserved 4, 15, 17 to 20, 30;
1527       reserved "foo", "bar";
1528       optional uint64 age =1;
1529       required bytes name =2;
1530    }"#;
1531
1532        let mess = parse_opt(msg, |p| p.next_message_opt());
1533        assert_eq!(
1534            vec![4..=4, 15..=15, 17..=20, 30..=30,],
1535            mess.t.reserved_nums
1536        );
1537        assert_eq!(
1538            vec!["foo".to_string(), "bar".to_string()],
1539            mess.t.reserved_names
1540        );
1541        assert_eq!(2, mess.t.fields.len());
1542    }
1543
1544    #[test]
1545    fn test_reserved_in_enum() {
1546        let msg = r#"enum Sample {
1547       reserved 4, 15, 17 to 20, 30;
1548       reserved "foo", "bar";
1549    }"#;
1550
1551        let enum_ = parse_opt(msg, |p| p.next_enum_opt());
1552        assert_eq!(
1553            vec![4..=4, 15..=15, 17..=20, 30..=30,],
1554            enum_.t.reserved_nums
1555        );
1556        assert_eq!(
1557            vec!["foo".to_string(), "bar".to_string()],
1558            enum_.t.reserved_names
1559        );
1560    }
1561
1562    #[test]
1563    fn test_default_value_int() {
1564        let msg = r#"message Sample {
1565            optional int32 x = 1 [default = 17];
1566        }"#;
1567
1568        let mess = parse_opt(msg, |p| p.next_message_opt());
1569        assert_eq!(
1570            ProtobufOptionName::simple("default"),
1571            mess.t.regular_fields_for_test()[0].options[0].name
1572        );
1573        assert_eq!(
1574            "17",
1575            mess.t.regular_fields_for_test()[0].options[0]
1576                .value
1577                .format()
1578        );
1579    }
1580
1581    #[test]
1582    fn test_default_value_string() {
1583        let msg = r#"message Sample {
1584            optional string x = 1 [default = "ab\nc d\"g\'h\0\"z"];
1585        }"#;
1586
1587        let mess = parse_opt(msg, |p| p.next_message_opt());
1588        assert_eq!(
1589            r#""ab\nc d\"g\'h\0\"z""#,
1590            mess.t.regular_fields_for_test()[0].options[0]
1591                .value
1592                .format()
1593        );
1594    }
1595
1596    #[test]
1597    fn test_default_value_bytes() {
1598        let msg = r#"message Sample {
1599            optional bytes x = 1 [default = "ab\nc d\xfeE\"g\'h\0\"z"];
1600        }"#;
1601
1602        let mess = parse_opt(msg, |p| p.next_message_opt());
1603        assert_eq!(
1604            r#""ab\nc d\xfeE\"g\'h\0\"z""#,
1605            mess.t.regular_fields_for_test()[0].options[0]
1606                .value
1607                .format()
1608        );
1609    }
1610
1611    #[test]
1612    fn test_group() {
1613        let msg = r#"message MessageWithGroup {
1614            optional string aaa = 1;
1615
1616            repeated group Identifier = 18 {
1617                optional int32 iii = 19;
1618                optional string sss = 20;
1619            }
1620
1621            required int bbb = 3;
1622        }"#;
1623        let mess = parse_opt(msg, |p| p.next_message_opt());
1624
1625        assert_eq!("identifier", mess.t.regular_fields_for_test()[1].name);
1626        if let FieldType::Group(Group { fields, .. }) = &mess.t.regular_fields_for_test()[1].typ {
1627            assert_eq!(2, fields.len());
1628        } else {
1629            panic!("expecting group");
1630        }
1631
1632        assert_eq!("bbb", mess.t.regular_fields_for_test()[2].name);
1633    }
1634
1635    #[test]
1636    fn test_incorrect_file_descriptor() {
1637        let msg = r#"
1638            message Foo {}
1639
1640            dfgdg
1641        "#;
1642
1643        let err = FileDescriptor::parse(msg).err().expect("err");
1644        assert_eq!(4, err.line);
1645    }
1646}