/
Encode.purs
246 lines (214 loc) · 8.11 KB
/
Encode.purs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
-- | Primitive builders for encoding Google Protocol Buffers.
-- |
-- | Do not import this module.
-- | See package README for explanation.
-- |
-- | Primed (') encoder functions encode without the tag, for packed
-- | repeating fields.
module Protobuf.Encode
( double
, double'
, float
, float'
, int32
, int32'
, int64
, int64'
, uint32
, uint32'
, uint64
, uint64'
, sint32
, sint32'
, sint64
, sint64'
, fixed32
, fixed32'
, fixed64
, fixed64'
, sfixed32
, sfixed32'
, sfixed64
, sfixed64'
, bool
, bool'
, string
, bytes
, builder
, module Protobuf.Encode32
, module Protobuf.Encode64
)
where
import Prelude
import Effect.Class (class MonadEffect)
import Control.Monad.Writer.Trans (tell)
import Data.Float32 (Float32)
import Data.ArrayBuffer.Builder as Builder
import Data.UInt (UInt)
import Data.UInt as UInt
import Data.Long (toUnsigned, lowBits, highBits)
import Data.Long.Unsigned as LU
import Data.Long.Internal (Long, Unsigned, Signed, signedLongFromInt, signedToUnsigned)
import Data.TextEncoding (encodeUtf8)
import Data.ArrayBuffer.Typed as AT
import Data.ArrayBuffer.ArrayBuffer as AB
import Protobuf.Common (FieldNumber, WireType(..), Bytes(..))
import Protobuf.Encode32 (zigzag32, tag32, varint32)
import Protobuf.Encode64 (zigzag64, varint64)
-- | __double__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
double :: forall m. MonadEffect m => FieldNumber -> Number -> Builder.PutM m Unit
-- https://developers.google.com/protocol-buffers/docs/encoding#non-varint_numbers
double fieldNumber n = do
tag32 fieldNumber Bits64
double' n
double' :: forall m. MonadEffect m => Number -> Builder.PutM m Unit
-- https://developers.google.com/protocol-buffers/docs/encoding#non-varint_numbers
double' n = do
Builder.putFloat64le n
-- | __float__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
float :: forall m. MonadEffect m => FieldNumber -> Float32 -> Builder.PutM m Unit
float fieldNumber n = do
tag32 fieldNumber Bits32
float' n
float' :: forall m. MonadEffect m => Float32 -> Builder.PutM m Unit
float' n = do
Builder.putFloat32le n
-- | __int32__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
int32 :: forall m. MonadEffect m => FieldNumber -> Int -> Builder.PutM m Unit
-- “If you use int32 or int64 as the type for a negative number, the resulting
-- varint is always ten bytes long”
-- https://developers.google.com/protocol-buffers/docs/encoding#signed_integers
int32 fieldNumber n = do
tag32 fieldNumber VarInt
int32' n
int32' :: forall m. MonadEffect m => Int -> Builder.PutM m Unit
-- “If you use int32 or int64 as the type for a negative number, the resulting
-- varint is always ten bytes long”
-- https://developers.google.com/protocol-buffers/docs/encoding#signed_integers
int32' n = do
varint64 $ signedToUnsigned $ signedLongFromInt n
-- | __int64__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
int64 :: forall m. MonadEffect m => FieldNumber -> Long Signed -> Builder.PutM m Unit
-- “If you use int32 or int64 as the type for a negative number, the resulting
-- varint is always ten bytes long”
-- https://developers.google.com/protocol-buffers/docs/encoding#signed_integers
int64 fieldNumber n = do
tag32 fieldNumber VarInt
int64' n
int64' :: forall m. MonadEffect m => Long Signed -> Builder.PutM m Unit
-- “If you use int32 or int64 as the type for a negative number, the resulting
-- varint is always ten bytes long”
-- https://developers.google.com/protocol-buffers/docs/encoding#signed_integers
int64' n = do
varint64 $ toUnsigned n
-- | __uint32__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
uint32 :: forall m. MonadEffect m => FieldNumber -> UInt -> Builder.PutM m Unit
uint32 fieldNumber n = do
tag32 fieldNumber VarInt
uint32' n
uint32' :: forall m. MonadEffect m => UInt -> Builder.PutM m Unit
uint32' n = do
varint32 n
-- | __uint64__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
uint64 :: forall m. MonadEffect m => FieldNumber -> Long Unsigned -> Builder.PutM m Unit
uint64 fieldNumber n = do
tag32 fieldNumber VarInt
uint64' n
uint64' :: forall m. MonadEffect m => Long Unsigned -> Builder.PutM m Unit
uint64' n = do
varint64 n
-- | __sint32__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
sint32 :: forall m. MonadEffect m => FieldNumber -> Int -> Builder.PutM m Unit
sint32 fieldNumber n = do
tag32 fieldNumber VarInt
sint32' n
sint32' :: forall m. MonadEffect m => Int -> Builder.PutM m Unit
sint32' n = do
varint32 $ zigzag32 n
-- | __sint64__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
sint64 :: forall m. MonadEffect m => FieldNumber -> Long Signed -> Builder.PutM m Unit
sint64 fieldNumber n = do
tag32 fieldNumber VarInt
sint64' n
sint64' :: forall m. MonadEffect m => Long Signed -> Builder.PutM m Unit
sint64' n = do
varint64 $ zigzag64 n
-- | __fixed32__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
fixed32 :: forall m. MonadEffect m => FieldNumber -> UInt -> Builder.PutM m Unit
-- https://developers.google.com/protocol-buffers/docs/encoding#non-varint_numbers
fixed32 fieldNumber n = do
tag32 fieldNumber Bits32
fixed32' n
fixed32' :: forall m. MonadEffect m => UInt -> Builder.PutM m Unit
-- https://developers.google.com/protocol-buffers/docs/encoding#non-varint_numbers
fixed32' n = do
Builder.putUint32le n
-- | __fixed64__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
fixed64 :: forall m. MonadEffect m => FieldNumber -> Long Unsigned -> Builder.PutM m Unit
fixed64 fieldNumber n = do
tag32 fieldNumber Bits64
fixed64' n
fixed64' :: forall m. MonadEffect m => Long Unsigned -> Builder.PutM m Unit
fixed64' n = do
Builder.putInt32le $ LU.lowBits n
Builder.putInt32le $ LU.highBits n
-- | __sfixed32__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
sfixed32 :: forall m. MonadEffect m => FieldNumber -> Int -> Builder.PutM m Unit
sfixed32 fieldNumber n = do
tag32 fieldNumber Bits32
sfixed32' n
sfixed32' :: forall m. MonadEffect m => Int -> Builder.PutM m Unit
sfixed32' n = do
Builder.putInt32le n
-- | __sfixed64__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
sfixed64 :: forall m. MonadEffect m => FieldNumber -> Long Signed -> Builder.PutM m Unit
sfixed64 fieldNumber n = do
tag32 fieldNumber Bits64
sfixed64' n
sfixed64' :: forall m. MonadEffect m => Long Signed -> Builder.PutM m Unit
sfixed64' n = do
Builder.putInt32le $ lowBits n
Builder.putInt32le $ highBits n
-- | __bool__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
bool :: forall m. MonadEffect m => FieldNumber -> Boolean -> Builder.PutM m Unit
bool fieldNumber n = do
tag32 fieldNumber VarInt
bool' n
bool' :: forall m. MonadEffect m => Boolean -> Builder.PutM m Unit
bool' n = do
if n then Builder.putInt8 1 else Builder.putInt8 0
-- | __string__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
string :: forall m. MonadEffect m => FieldNumber -> String -> Builder.PutM m Unit
-- https://developers.google.com/protocol-buffers/docs/encoding#strings
string fieldNumber s = do
tag32 fieldNumber LenDel
let stringbuf = AT.buffer $ encodeUtf8 s
varint32 $ UInt.fromInt $ AB.byteLength stringbuf
Builder.putArrayBuffer stringbuf
-- | __bytes__
-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
bytes :: forall m. MonadEffect m => FieldNumber -> Bytes -> Builder.PutM m Unit
bytes fieldNumber (Bytes s) = do
tag32 fieldNumber LenDel
varint32 $ UInt.fromInt $ AB.byteLength s
Builder.putArrayBuffer s
-- | `tell` with a tag and a length delimit.
builder :: forall m. MonadEffect m => FieldNumber -> Builder.Builder -> Builder.PutM m Unit
builder fieldNumber s = do
tag32 fieldNumber LenDel
varint32 $ UInt.fromInt $ Builder.length s
tell s