From adfe3d9f2c4da6ee11e8bf8b201e2a748a35072c Mon Sep 17 00:00:00 2001 From: James Hugard Date: Thu, 10 May 2018 12:51:52 -0700 Subject: [PATCH] Parse `oneof` before field, so that 'oneof' isn't considered a message-type in proto3. (#89) Proto3 fields don't have a label qualifier (optional | repeated | required) to distinguish between those and 'oneof', so it was being treated as a field-type identifier. Fixes #88 --- Parser.Test/TestParser.fs | 41 +++++++++++++++++++++++++++++++++++++++ Parser/Parser.fs | 4 ++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Parser.Test/TestParser.fs b/Parser.Test/TestParser.fs index e27ee87..d54eba3 100644 --- a/Parser.Test/TestParser.fs +++ b/Parser.Test/TestParser.fs @@ -480,6 +480,17 @@ module Message = |> should equal <| TOneOf("MyOneof", [ TOneOfField("name",TString,1u,[("foo",TStrLit("bar"))]) ]) + [] + let ``Parse oneof with multiple cases`` () = + Parse.fromStringWithParser (ws >>. pOneOf) """ + oneof test_oneof { + string name = 4; + int32 age = 9; + } + """ + |> should equal + <| TOneOf("test_oneof", [ TOneOfField("name",TString,4u,[]); TOneOfField("age",TInt32,9u,[]) ]) + [] let ``Parse map`` () = Parse.fromStringWithParser (ws >>. pMap) """ @@ -1043,3 +1054,33 @@ module Proto2 = } """ |> ignore |> should not' (throw typeof) + +[] +module RegressionTests = + + [] + let ``proto3 oneof type doesn't parse (#88)`` () = + System.Diagnostics.Debugger.Break() + Parse.fromStringWithParser pProto """ + syntax = "proto3"; + + message SampleMessage { + oneof test_oneof { + string name = 4; + int32 age = 9; + } + } + """ + |> should equal ( + [ + TSyntax TProto3 + TMessage ("SampleMessage", + [ + TOneOf("test_oneof", + [ + TOneOfField("name",TString,4u,[]) + TOneOfField("age",TInt32,9u,[]) + ]) + + ]) + ]) \ No newline at end of file diff --git a/Parser/Parser.fs b/Parser/Parser.fs index 946a7fe..ab86dd1 100644 --- a/Parser/Parser.fs +++ b/Parser/Parser.fs @@ -359,7 +359,7 @@ module Parse = //let todoMsg = "Explicit 'optional' fields are prohibited in proto3 syntax. Since all fields are optional by default, the 'optional' label should simply be removed." (opt (str_ws1 "repeated" >>% TRepeated)) |>> defArg TOptional - /// Parser for proto2 lable + ws + /// Parser for proto2 label + ws let pLabel_ws1 = pLabel .>> ws1 /// Parser for types: double | int32 | etc... @@ -481,13 +481,13 @@ module Parse = choice [ (isProto2 >>. pGroup) // must be parsed first to avoid confusion + pOneOf // must be parsed before pField, so 'oneof' isn't considered a type in Proto3 pField pMessageEnum pMessageMessage (isProto2 >>. pMessageExtend) (isProto2 >>. pExtensions) pMessageOption - pOneOf pMap pReserved ]