@@ -316,11 +316,19 @@ function parse(source, root, options) {
316316 break ;
317317
318318 case "required" :
319- case "optional" :
320319 case "repeated" :
321320 parseField ( type , token ) ;
322321 break ;
323322
323+ case "optional" :
324+ /* istanbul ignore if */
325+ if ( isProto3 ) {
326+ parseField ( type , "proto3_optional" ) ;
327+ } else {
328+ parseField ( type , "optional" ) ;
329+ }
330+ break ;
331+
324332 case "oneof" :
325333 parseOneOf ( type , token ) ;
326334 break ;
@@ -379,7 +387,16 @@ function parse(source, root, options) {
379387 } , function parseField_line ( ) {
380388 parseInlineOptions ( field ) ;
381389 } ) ;
382- parent . add ( field ) ;
390+
391+ if ( rule === "proto3_optional" ) {
392+ // for proto3 optional fields, we create a single-member Oneof to mimic "optional" behavior
393+ var oneof = new OneOf ( "_" + name ) ;
394+ field . setOption ( "proto3_optional" , true ) ;
395+ oneof . add ( field ) ;
396+ parent . add ( oneof ) ;
397+ } else {
398+ parent . add ( field ) ;
399+ }
383400
384401 // JSON defaults to packed=true if not set so we have to set packed=false explicity when
385402 // parsing proto2 descriptors without the option, where applicable. This must be done for
@@ -413,11 +430,19 @@ function parse(source, root, options) {
413430 break ;
414431
415432 case "required" :
416- case "optional" :
417433 case "repeated" :
418434 parseField ( type , token ) ;
419435 break ;
420436
437+ case "optional" :
438+ /* istanbul ignore if */
439+ if ( isProto3 ) {
440+ parseField ( type , "proto3_optional" ) ;
441+ } else {
442+ parseField ( type , "optional" ) ;
443+ }
444+ break ;
445+
421446 /* istanbul ignore next */
422447 default :
423448 throw illegal ( token ) ; // there are no groups with proto3 semantics
@@ -699,10 +724,18 @@ function parse(source, root, options) {
699724
700725 case "required" :
701726 case "repeated" :
702- case "optional" :
703727 parseField ( parent , token , reference ) ;
704728 break ;
705729
730+ case "optional" :
731+ /* istanbul ignore if */
732+ if ( isProto3 ) {
733+ parseField ( parent , "proto3_optional" , reference ) ;
734+ } else {
735+ parseField ( parent , "optional" , reference ) ;
736+ }
737+ break ;
738+
706739 default :
707740 /* istanbul ignore if */
708741 if ( ! isProto3 || ! typeRefRe . test ( token ) )
0 commit comments