@@ -5,14 +5,17 @@ module Main (main) where
5
5
6
6
import Prelude
7
7
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 )
9
10
import Data.Array (catMaybes , concat , fold , mapWithIndex )
10
11
import Data.Array as Array
11
12
import Data.ArrayBuffer.ArrayBuffer as AB
12
13
import Data.ArrayBuffer.Builder (execPutM )
13
14
import Data.ArrayBuffer.DataView as DV
15
+ import Data.ArrayBuffer.Types as ABT
14
16
import Data.CodePoint.Unicode as Unicode
15
17
import Data.Either (Either (..), either )
18
+ import Data.List as List
16
19
import Data.Maybe (Maybe (..), fromMaybe , maybe )
17
20
import Data.Newtype (unwrap )
18
21
import Data.String (Pattern (..))
@@ -22,11 +25,12 @@ import Data.String.Regex as String.Regex
22
25
import Data.String.Regex.Flags as String.Regex.Flags
23
26
import Data.Traversable (sequence , traverse )
24
27
import Data.Tuple (Tuple (..))
28
+ import Data.UInt as UInt
25
29
import Data.UInt64 (UInt64 )
26
30
import Data.UInt64 as UInt64
27
31
import Effect (Effect )
28
32
import Effect.Aff (runAff_ , throwError , error )
29
- import Effect.Class (liftEffect )
33
+ import Effect.Class (class MonadEffect , liftEffect )
30
34
import Effect.Class.Console as Console
31
35
import Google.Protobuf.Compiler.Plugin (CodeGeneratorRequest (..), CodeGeneratorResponse , CodeGeneratorResponse_File (..), mkCodeGeneratorResponse , parseCodeGeneratorRequest , putCodeGeneratorResponse )
32
36
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
35
39
import Node.Path (basenameWithoutExt )
36
40
import Node.Process (stdin , stdout )
37
41
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 )
39
49
import Unsafe.Coerce (unsafeCoerce )
40
50
41
51
@@ -51,12 +61,15 @@ main = runAff_ (either (unsafeCoerce >>> Console.error) (\_ -> pure unit)) do
51
61
{buffers:b,readagain} <- readSome stdin
52
62
let bs' = bs <> b
53
63
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
55
67
Left err -> do
56
68
if not readagain then do
57
69
void $ throwError $ error " stdin is not readable."
58
70
pure (Done unit)
59
71
else if (Array .length bs') < 10000 then do
72
+ Console .error $ show err
60
73
-- What we want to do here is detect whether this parsing error was
61
74
-- because we read to the end of the buffer and need to read more.
62
75
-- 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
68
81
else do
69
82
void $ throwError $ error $ show err
70
83
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
+
76
160
77
161
generate :: CodeGeneratorRequest -> CodeGeneratorResponse
78
162
generate (CodeGeneratorRequest { proto_file }) = do
0 commit comments