git.iko.soy/rowtype-yoga/purescript-protobuf
on master help sign in
WIP
commit689f148a301d97e42c1d84f72daad361df565d5a authorJames Brock <jamesbrock@gmail.com> dateMon 7 Sep 2020, 15:16 (6 years ago) parentc43cbe9
11 files changed+76−58
.gitignore+2 .vscode/settings.json+6 README.md+4−2 packages.dhall+17−1 src/Protobuf/Common.purs+1 src/Protobuf/Decode.purs+10−19 src/Protobuf/Decode32.purs+5−4 src/Protobuf/Decode64.purs+24−18 src/Protobuf/Encode.purs+4−10 src/Protobuf/Encode32.purs−4 src/ProtocPlugin/Main.purs+3
.gitignore+2
@@ -6,3 +6,5 @@ node_modules
66# Generated files
77.psci
88output
9+.spago
10+
.vscode/settings.jsonnew file+6
@@ -0,0 +1,6 @@
1+{
2+ "purescript.addSpagoSources": true,
3+ "purescript.buildCommand": "spago build --purs-args --json-errors ",
4+ "purescript.sourcePath": "purs/",
5+ "purescript.packagePath": ".spago/"
6+}
README.md+4−2
@@ -1,7 +1,9 @@
1−# purescript-protobuf-library
1+# WIP purescript-protobuf
22
3−Purescript library dependencies for Google Protocol Buffers.
3+Purescript support for Google Protocol Buffers.
44
55Only
66[Protocol Buffers Version 3](https://developers.google.com/protocol-buffers/docs/reference/proto3-spec)
77supported.
8+
9+Works with both Node and browser?
packages.dhall+17−1
@@ -108,4 +108,20 @@ in upstream
108108let upstream =
109109 https://github.com/purescript/package-sets/releases/download/psc-0.13.8-20200831/packages.dhall sha256:cdb3529cac2cd8dd780f07c80fd907d5faceae7decfcaa11a12037df68812c83
110110
111−in upstream
111+let additions =
112+ { longs =
113+ { dependencies =
114+ [ "effect"
115+ , "console"
116+ , "prelude"
117+ , "strings"
118+ , "foreign"
119+ , "nullable"
120+ , "functions"
121+ ]
122+ , repo = "https://github.com/zapph/purescript-longs.git"
123+ , version = "v0.1.1"
124+ }
125+ }
126+
127+in upstream // additions
src/Protobuf/Common.purs+1
@@ -1,5 +1,6 @@
11module Protobuf.Common
22( FieldNumber
3+, WireType
34)
45where
56
src/Protobuf/Decode.purs+10−19
@@ -16,33 +16,24 @@ module Protobuf.Decode
1616, string
1717, bytes
1818, tag32
19−)
20−
19+) where
2120
2221import Prelude
2322import Effect (Effect, liftEffect)
2423import Text.Parsing.Parser (ParserT, fail)
2524import Text.Parsing.Parser.DataView as Parse
2625import Data.UInt (UInt)
27−import Data.UInt as UInt (fromInt, toInt)
26+import Data.UInt as UInt
2827import Data.Long.Internal (Long, Signed, Unsigned)
29−import Data.Long.Unsigned as ULong (toSigned, toInt)
28+import Data.Long.Unsigned as ULong
3029import Data.TextEncoding (encodeUtf8)
3130import Data.ArrayBuffer.Types (DataView, Uint8Array)
3231import Data.ArrayBuffer.Typed as AT
33−import Data.ArrayBuffer as AB
32+import Data.ArrayBuffer.Types as AB
3433import Data.ArrayBuffer.DataView as DV
3534import Protobuf.Common (FieldNumber, WireType)
36−
37−import Protobuf.Decode32
38−( varint32
39−, zigzag32
40−, tag32
41−)
42−import Protobuf.Decode64
43−( varint64
44−, zigzag64
45−)
35+import Protobuf.Decode32 (varint32, zigzag32, tag32)
36+import Protobuf.Decode64 (varint64, zigzag64)
4637
4738-- | __double__
4839-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
@@ -131,9 +122,9 @@ sfixed64 = fromLowHighBits <$> Parse.anyInt32le <*> Parse.anyInt32le
131122bool :: forall m. MonadEffect m => ParserT DataView m Boolean
132123bool = do
133124 x <- varint32
134− if x == fromInt 0
135− then pure False
136− else pure True
125+ if x == UInt.fromInt 0
126+ then pure false
127+ else pure true
137128
138129
139130-- | __string__
@@ -143,7 +134,7 @@ string = do
143134 stringview <- varint32 >>= Parse.takeN
144135 stringarray <- liftEffect $ mkTypedArray stringview
145136 case decodeUtf8 stringarray of
146− Left err -> fail "string failed to decode UTF8"
137+ Left err -> fail $ "string decodeUtf8 failed. " <> err
147138 Right s -> pure s
148139 where
149140 mkTypedArray :: DataView -> Effect Uint8Array
src/Protobuf/Decode32.purs+5−4
@@ -3,10 +3,11 @@ module Protobuf.Decode32
33( zigzag32
44, tag32
55, varint32
6−)
6+) where
77
88import Prelude
9−import Effect (Effect, liftEffect)
9+import Effect (Effect)
10+import Effect.Class (liftEffect)
1011import Text.Parsing.Parser (ParserT, fail)
1112import Text.Parsing.Parser.DataView as Parse
1213import Data.UInt (UInt, fromInt, toInt, (.&.), (.|.), (.^.))
@@ -16,11 +17,11 @@ import Protobuf.Common (FieldNumber, WireType)
1617-- | https://stackoverflow.com/questions/2210923/zig-zag-decoding
1718zigzag32 :: UInt -> Int
1819zigzag32 n = toInt $ (n `shr` 1) .^. (unegate (n .&. 1))
19− where unegate = fromInt <<< negate << toInt
20+ where unegate = fromInt <<< negate <<< toInt
2021 -- unegate x = complement x + (fromInt 1) -- TODO switch to this definition?
2122
2223tag32 :: forall m. MonadEffect m => ParserT DataView m (Tuple FieldNumber WireType)
23−tag = do
24+tag32 = do
2425 n <- varint32
2526 pure $ Tuple (n `shr` 3) (toInt $ n .&. 3)
2627
src/Protobuf/Decode64.purs+24−18
@@ -2,25 +2,31 @@
22module Protobuf.Decode64
33( zigzag64
44, varint64
5−)
5+) where
66
77import Prelude
8−import Effect (Effect, liftEffect)
8+import Effect (Effect)
9+import Effect.Class (liftEffect)
910import Text.Parsing.Parser (ParserT, fail)
1011import Text.Parsing.Parser.DataView as Parse
11−import Data.Long.Unsigned (Long, Unsigned, Signed, toUnsigned, fromInt)
1212import Data.Long.Bits((.^.), (.&.), (.|.), complement)
13−import Data.Long as Long (fromInt)
13+import Data.Long.Internal (Long, Unsigned, Signed, signedToUnsigned, unsafeFromInt)
14+import Data.UInt (UInt)
15+import Data.UInt as UInt
1416import Data.ArrayBuffer.Types (DataView)
1517import Protobuf.Common (FieldNumber, WireType)
1618
19+
20+fromInt :: UInt -> Long Unsigned
21+fromInt x = unsafeFromInt <<< UInt.toInt
22+
1723-- | https://stackoverflow.com/questions/2210923/zig-zag-decoding
1824zigzag64 :: Long Signed -> Long Unsigned
19−zigzag64 n = toUnsigned $ (n `shr` 1) .^. (lnegate (n .&. 1))
20− where lnegate x = complement x + (Long.fromInt 1)
25+zigzag64 n = signedToUnsigned $ (n `shr` 1) .^. (lnegate (n .&. 1))
26+ where lnegate x = complement x + (unsafeFromInt 1)
2127
2228-- | https://developers.google.com/protocol-buffers/docs/encoding#varints
23−varint64 :: forall m. MonadEffect m => ParserT DataView m UInt
29+varint64 :: forall m. MonadEffect m => ParserT DataView m (Long Unsigned)
2430varint64 = do
2531 n_0 <- fromInt <$> Parse.anyUInt8
2632 if n_0 < u0x80
@@ -70,15 +76,15 @@ varint64 = do
7076 n_9 <- fromInt <$> Parse.anyUint8
7177 pure $ acc_8 .|. (n_9 `shl` u63)
7278 where
73− u7 = fromInt 7
74− u14 = fromInt 14
75− u21 = fromInt 21
76− u28 = fromInt 28
77− u35 = fromInt 35
78− u42 = fromInt 42
79− u49 = fromInt 49
80− u56 = fromInt 56
81− u63 = fromInt 63
82− u0x7F = fromInt 0x7F
83− u0x80 = fromInt 0x80
79+ u7 = unsafeFromInt 7
80+ u14 = unsafeFromInt 14
81+ u21 = unsafeFromInt 21
82+ u28 = unsafeFromInt 28
83+ u35 = unsafeFromInt 35
84+ u42 = unsafeFromInt 42
85+ u49 = unsafeFromInt 49
86+ u56 = unsafeFromInt 56
87+ u63 = unsafeFromInt 63
88+ u0x7F = unsafeFromInt 0x7F
89+ u0x80 = unsafeFromInt 0x80
8490
src/Protobuf/Encode.purs+4−10
@@ -20,6 +20,7 @@ where
2020
2121import Prelude
2222import Effect (Effect)
23+import Effect.Class (class MonadEffect)
2324import Data.ArrayBuffer.Builder as Builder
2425import Data.UInt (UInt)
2526import Data.Long (toUnsigned, lowBits, highBits)
@@ -27,22 +28,15 @@ import Data.Long.Unsigned as LU
2728import Data.Long.Unsigned (Long, Unsigned)
2829import Data.TextEncoding (encodeUtf8)
2930import Data.ArrayBuffer.Typed as AT
30−import Data.ArrayBuffer as AB
31+import Data.ArrayBuffer.Types as AB
3132import Protobuf.Common (FieldNumber)
3233
3334-- We have a special varint32 for encoding varints which we're just going
3435-- to assume fit in the 32-bit range. There is no "32-bit varint" in protobuf.
3536-- This is a performance optimization, and probably misguided, but we're
3637-- horrified at the thought of using so many Longs in our program.
37−import Protobuf.Encode32
38−( zigzag32
39−, tag32
40−, varint32
41−)
42−import Protobuf.Encode64
43−( zigzag64
44−, varint64
45−)
38+import Protobuf.Encode32 (zigzag32, tag32, varint32)
39+import Protobuf.Encode64 (zigzag64, varint64)
4640
4741-- | __double__
4842-- | [Scalar Value Type](https://developers.google.com/protocol-buffers/docs/proto3#scalar)
src/Protobuf/Encode32.purs−4
@@ -27,28 +27,24 @@ varint32 :: forall m. MonadEffect m => UInt -> Builder.PutM m Unit
2727varint32 n_0 = do
2828 let group_0 = n_0 .&. u0x7F
2929 n_1 = n_0 `zshr` u7
30− in
3130 if n_1 == u0
3231 then Builder.putUint8 group_0
3332 else do
3433 Builder.putUint8 $ u0x80 .|. group_0
3534 let group_1 = n_1 .&. u0x7F
3635 n_2 = n_1 `zshr` u7
37− in
3836 if n_2 == u0
3937 then Builder.putUint8 group_1
4038 else do
4139 Builder.putUint8 $ u0x80 .|. group_1
4240 let group_2 = n_2 .&. u0x7F
4341 n_3 = n_2 `zshr` u7
44− in
4542 if n_3 == u0
4643 then Builder.putUint8 group_2
4744 else do
4845 Builder.putUint8 $ u0x80 .| group_2
4946 let group_3 = n_3 .&. u0x7F
5047 n_4 = n_3 `zshr` u7
51− in
5248 if n_4 == u0
5349 then Builder.putUint8 group_3
5450 else do
src/ProtocPlugin/Main.purs+3
@@ -5,6 +5,9 @@ import Prelude
55import Effect (Effect)
66import Effect.Console (log)
77
8+import Protobuf.Decode as Decode
9+import Protobuf.Encode as Encode
10+
811main :: Effect Unit
912main = do
1013 log "🍝"