Skip to content

Commit 84cfe2f

Browse files
committed
wip parseCodeGeneratorRequestComplete
cd schema/ shopt -s globstar time protoc --purescript_out=./_generated ./**/*.proto
1 parent 545818a commit 84cfe2f

File tree

1 file changed

+93
-9
lines changed

1 file changed

+93
-9
lines changed

plugin/src/Main.purs

+93-9
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ module Main (main) where
55

66
import Prelude
77

8-
import Control.Monad.Rec.Class (tailRecM, Step(..))
8+
import Control.Monad.Rec.Class (class MonadRec, Step(..), tailRecM)
9+
import Control.Monad.Trans.Class (lift)
910
import Data.Array (catMaybes, concat, fold, mapWithIndex)
1011
import Data.Array as Array
1112
import Data.ArrayBuffer.ArrayBuffer as AB
1213
import Data.ArrayBuffer.Builder (execPutM)
1314
import Data.ArrayBuffer.DataView as DV
15+
import Data.ArrayBuffer.Types as ABT
1416
import Data.CodePoint.Unicode as Unicode
1517
import Data.Either (Either(..), either)
18+
import Data.List as List
1619
import Data.Maybe (Maybe(..), fromMaybe, maybe)
1720
import Data.Newtype (unwrap)
1821
import Data.String (Pattern(..))
@@ -22,11 +25,12 @@ import Data.String.Regex as String.Regex
2225
import Data.String.Regex.Flags as String.Regex.Flags
2326
import Data.Traversable (sequence, traverse)
2427
import Data.Tuple (Tuple(..))
28+
import Data.UInt as UInt
2529
import Data.UInt64 (UInt64)
2630
import Data.UInt64 as UInt64
2731
import Effect (Effect)
2832
import Effect.Aff (runAff_, throwError, error)
29-
import Effect.Class (liftEffect)
33+
import Effect.Class (class MonadEffect, liftEffect)
3034
import Effect.Class.Console as Console
3135
import Google.Protobuf.Compiler.Plugin (CodeGeneratorRequest(..), CodeGeneratorResponse, CodeGeneratorResponse_File(..), mkCodeGeneratorResponse, parseCodeGeneratorRequest, putCodeGeneratorResponse)
3236
import Google.Protobuf.Descriptor (DescriptorProto(..), EnumDescriptorProto(..), EnumValueDescriptorProto(..), FieldDescriptorProto(..), FieldDescriptorProto_Label(..), FieldDescriptorProto_Type(..), FieldOptions(..), FileDescriptorProto(..), OneofDescriptorProto(..), SourceCodeInfo(..), SourceCodeInfo_Location(..))
@@ -35,7 +39,13 @@ import Node.Buffer as Buffer
3539
import Node.Path (basenameWithoutExt)
3640
import Node.Process (stdin, stdout)
3741
import Node.Stream.Aff (readSome, write)
38-
import Parsing (runParserT)
42+
import Parsing (ParserT, fail, runParserT)
43+
import Parsing.Combinators (try, many)
44+
import Parsing.DataView (takeN)
45+
import Partial.Unsafe (unsafePartial)
46+
import Protobuf.Internal.Common (label)
47+
import Protobuf.Internal.Decode (decodeString, decodeTag32)
48+
import Protobuf.Internal.Runtime (parseLenDel)
3949
import Unsafe.Coerce (unsafeCoerce)
4050

4151

@@ -51,12 +61,15 @@ main = runAff_ (either (unsafeCoerce >>> Console.error) (\_ -> pure unit)) do
5161
{buffers:b,readagain} <- readSome stdin
5262
let bs' = bs <> b
5363
ab <- liftEffect $ toArrayBuffer =<< Buffer.concat bs'
54-
runParserT (DV.whole ab) (parseCodeGeneratorRequest (AB.byteLength ab)) >>= case _ of
64+
bsize <- unsafePartial $ liftEffect $ Buffer.size $ Array.unsafeIndex b 0
65+
Console.error $ "read " <> show bsize <> " to " <> show (AB.byteLength ab)
66+
runParserT (DV.whole ab) (parseCodeGeneratorRequestComplete (AB.byteLength ab)) >>= case _ of
5567
Left err -> do
5668
if not readagain then do
5769
void $ throwError $ error "stdin is not readable."
5870
pure (Done unit)
5971
else if (Array.length bs') < 10000 then do
72+
Console.error $ show err
6073
-- What we want to do here is detect whether this parsing error was
6174
-- because we read to the end of the buffer and need to read more.
6275
-- But we don't have a good way to do that right now, so we assume
@@ -68,11 +81,82 @@ main = runAff_ (either (unsafeCoerce >>> Console.error) (\_ -> pure unit)) do
6881
else do
6982
void $ throwError $ error $ show err
7083
pure (Done unit)
71-
Right request -> do
72-
responseBuf <- execPutM $ putCodeGeneratorResponse (generate request)
73-
buf :: Buffer <- liftEffect $ fromArrayBuffer responseBuf
74-
write stdout [buf]
75-
pure (Done unit)
84+
Right unit -> do
85+
runParserT (DV.whole ab) (parseCodeGeneratorRequest (AB.byteLength ab)) >>= case _ of
86+
Left err -> do
87+
void $ throwError $ error $ show err
88+
pure (Done unit)
89+
Right request -> do
90+
Console.error $ "parsed request, generating response"
91+
responseBuf <- execPutM $ putCodeGeneratorResponse (generate request)
92+
buf :: Buffer <- liftEffect $ fromArrayBuffer responseBuf
93+
write stdout [buf]
94+
pure (Done unit)
95+
96+
-- | This is a parser which will succeed only if parseCodeGeneratorRequest will succeed.
97+
-- | It is faster than parseCodeGeneratorRequest.
98+
-- | It uses extra assumptions about the order of the CodeGeneratorRequest fields.
99+
-- -- | Returns True if parseCodeGeneratorRequest will succeed.
100+
-- -- | Returns False if parseCodeGeneratorRequest might succeed with more input.
101+
parseCodeGeneratorRequestComplete
102+
:: forall m. MonadEffect m
103+
=> MonadRec m
104+
=> ABT.ByteLength
105+
-> ParserT ABT.DataView m Unit
106+
parseCodeGeneratorRequestComplete length = label "parseCodeGeneratorRequestComplete / " $ do
107+
108+
files_to_generate <- label "file_to_generate / " $ many $ try $ do
109+
Tuple fieldNumber wireType <- decodeTag32
110+
if fieldNumber == UInt.fromInt 1 then do decodeString else fail (show fieldNumber)
111+
-- lift $ Console.error $ "files_to_generate " <> s
112+
113+
if List.length files_to_generate == 0 then do fail "No files_to_generate" else pure unit
114+
115+
_ <- label "compiler_version / " $ do
116+
Tuple fieldNumber wireType <- decodeTag32
117+
if fieldNumber == UInt.fromInt 3 then do parseLenDel takeN else fail (show fieldNumber)
118+
119+
_ <- label "parameter / " $ do
120+
Tuple fieldNumber wireType <- decodeTag32
121+
if fieldNumber == UInt.fromInt 2 then do decodeString else fail (show fieldNumber)
122+
123+
proto_files <- label "proto_file / " $ many $ try $ do
124+
Tuple fieldNumber wireType <- decodeTag32
125+
if fieldNumber == UInt.fromInt 15 then do parseLenDel takeN else fail (show fieldNumber)
126+
127+
if List.length proto_files == 0 then do fail "No proto_files" else pure unit
128+
129+
source_file_descriptors <- label "source_file_descriptors / " $ many $ try $ do
130+
Tuple fieldNumber wireType <- decodeTag32
131+
if fieldNumber == UInt.fromInt 17 then do parseLenDel takeN else fail (show fieldNumber)
132+
133+
-- if Array.length source_file_descriptors == 0 then do fail "No source_file_descriptors" else pure unit
134+
135+
pure unit
136+
137+
-- Prelude.parseMessage CodeGeneratorRequest defaultCodeGeneratorRequest parseField length
138+
-- where
139+
-- parseField
140+
-- :: Prelude.FieldNumberInt
141+
-- -> Prelude.WireType
142+
-- -> Prelude.ParserT Prelude.DataView m (Prelude.Builder CodeGeneratorRequestR CodeGeneratorRequestR)
143+
-- parseField 1 Prelude.LenDel = Prelude.label "file_to_generate / " $ do
144+
-- x <- Prelude.decodeString
145+
-- pure $ Prelude.modify (Prelude.Proxy :: Prelude.Proxy "file_to_generate") $ Prelude.flip Prelude.snoc x
146+
-- parseField 2 Prelude.LenDel = Prelude.label "parameter / " $ do
147+
-- x <- Prelude.decodeString
148+
-- pure $ Prelude.modify (Prelude.Proxy :: Prelude.Proxy "parameter") $ \_ -> Prelude.Just x
149+
-- parseField 15 Prelude.LenDel = Prelude.label "proto_file / " $ do
150+
-- x <- Prelude.parseLenDel Google.Protobuf.parseFileDescriptorProto
151+
-- pure $ Prelude.modify (Prelude.Proxy :: Prelude.Proxy "proto_file") $ Prelude.flip Prelude.snoc x
152+
-- parseField 17 Prelude.LenDel = Prelude.label "source_file_descriptors / " $ do
153+
-- x <- Prelude.parseLenDel Google.Protobuf.parseFileDescriptorProto
154+
-- pure $ Prelude.modify (Prelude.Proxy :: Prelude.Proxy "source_file_descriptors") $ Prelude.flip Prelude.snoc x
155+
-- parseField 3 Prelude.LenDel = Prelude.label "compiler_version / " $ do
156+
-- x <- Prelude.parseLenDel parseVersion
157+
-- pure $ Prelude.modify (Prelude.Proxy :: Prelude.Proxy "compiler_version") $ Prelude.Just Prelude.<<< Prelude.maybe x (mergeVersion x)
158+
-- parseField fieldNumber wireType = Prelude.parseFieldUnknown fieldNumber wireType
159+
76160

77161
generate :: CodeGeneratorRequest -> CodeGeneratorResponse
78162
generate (CodeGeneratorRequest { proto_file }) = do

0 commit comments

Comments
 (0)