proto3-wire 1.0.0 → 1.1.0
raw patch · 6 files changed
+94/−18 lines, 6 filesdep ~hashablePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hashable
API changes (from Hackage documentation)
+ Proto3.Wire: class ProtoEnum a
+ Proto3.Wire: fromProtoEnum :: (ProtoEnum a, Enum a) => a -> Int32
+ Proto3.Wire: toProtoEnumMay :: (ProtoEnum a, Bounded a, Enum a) => Int32 -> Maybe a
+ Proto3.Wire.Class: class ProtoEnum a
+ Proto3.Wire.Class: fromProtoEnum :: (ProtoEnum a, Enum a) => a -> Int32
+ Proto3.Wire.Class: toProtoEnumMay :: (ProtoEnum a, Bounded a, Enum a) => Int32 -> Maybe a
+ Proto3.Wire.Encode: bool :: FieldNumber -> Bool -> MessageBuilder
- Proto3.Wire.Decode: enum :: forall e. (Enum e, Bounded e) => Parser RawPrimitive (Either Int e)
+ Proto3.Wire.Decode: enum :: forall e. ProtoEnum e => Parser RawPrimitive (Either Int32 e)
- Proto3.Wire.Encode: enum :: Enum e => FieldNumber -> e -> MessageBuilder
+ Proto3.Wire.Encode: enum :: ProtoEnum e => FieldNumber -> e -> MessageBuilder
Files
- proto3-wire.cabal +2/−1
- src/Proto3/Wire.hs +5/−2
- src/Proto3/Wire/Class.hs +44/−0
- src/Proto3/Wire/Decode.hs +10/−7
- src/Proto3/Wire/Encode.hs +32/−7
- test/Main.hs +1/−1
proto3-wire.cabal view
@@ -1,5 +1,5 @@ name: proto3-wire-version: 1.0.0+version: 1.1.0 synopsis: A low-level implementation of the Protocol Buffers (version 3) wire format license: Apache-2.0 license-file: LICENSE@@ -13,6 +13,7 @@ library exposed-modules: Proto3.Wire Proto3.Wire.Builder+ Proto3.Wire.Class Proto3.Wire.Decode Proto3.Wire.Encode Proto3.Wire.Tutorial
src/Proto3/Wire.hs view
@@ -17,8 +17,10 @@ -- | See the "Proto3.Wire.Tutorial" module. module Proto3.Wire- ( -- * Message Structure- FieldNumber(..)+ ( -- * Support Classes+ ProtoEnum(..)+ -- * Message Structure+ , FieldNumber(..) , fieldNumber -- * Decoding Messages , at@@ -27,5 +29,6 @@ , repeated ) where +import Proto3.Wire.Class import Proto3.Wire.Types import Proto3.Wire.Decode
+ src/Proto3/Wire/Class.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DefaultSignatures #-}+{-+ Copyright 2019 Awake Networks++ Licensed under the Apache License, Version 2.0 (the "License");+ you may not use this file except in compliance with the License.+ You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ See the License for the specific language governing permissions and+ limitations under the License.+-}++-- | This module defines classes which are shared by the encoding and decoding+-- modules.++module Proto3.Wire.Class+ ( ProtoEnum(..)+ ) where++import Data.Int (Int32)+import qualified Safe++-- | Similar to 'Enum', but allows gaps in the sequence of numeric codes,+-- and uses 'Int32' in order to match the proto3 specification.+--+-- Absent gaps, you can use an automatic derivation of 'Bounded' and 'Enum',+-- then use the default implementations for all methods of this class. But+-- if gaps are involved, then you must instantiate this class directly and+-- supply the specific numeric codes desired for each constructor.+class ProtoEnum a where+ -- | Default implementation: `Safe.toEnumMay`.+ toProtoEnumMay :: Int32 -> Maybe a+ default toProtoEnumMay :: (Bounded a, Enum a) => Int32 -> Maybe a+ toProtoEnumMay = Safe.toEnumMay . fromIntegral++ -- | Default implementation: 'fromEnum'.+ fromProtoEnum :: a -> Int32+ default fromProtoEnum :: Enum a => a -> Int32+ fromProtoEnum = fromIntegral . fromEnum
src/Proto3/Wire/Decode.hs view
@@ -94,8 +94,8 @@ import qualified Data.Traversable as T import Data.Int ( Int32, Int64 ) import Data.Word ( Word8, Word32, Word64 )+import Proto3.Wire.Class import Proto3.Wire.Types-import qualified Safe -- | Decode a zigzag-encoded numeric type. -- See: http://stackoverflow.com/questions/2210923/zig-zag-decoding@@ -348,7 +348,10 @@ -- | Parse a Boolean value. bool :: Parser RawPrimitive Bool-bool = fmap (Safe.toEnumDef False) parseVarInt+bool = Parser $+ \case+ VarintField i -> return $! i /= 0+ wrong -> throwWireTypeError "bool" wrong -- | Parse a primitive with the @int32@ wire type. int32 :: Parser RawPrimitive Int32@@ -395,14 +398,14 @@ -- | Parse a primitive with an enumerated type. ----- This parser will return 'Left' if the encoded integer value is outside the--- acceptable range of the 'Bounded' instance.-enum :: forall e. (Enum e, Bounded e) => Parser RawPrimitive (Either Int e)+-- This parser will return 'Left' if the encoded integer value+-- is not a code for a known enumerator.+enum :: forall e. ProtoEnum e => Parser RawPrimitive (Either Int32 e) enum = fmap toEither parseVarInt where- toEither :: Int -> Either Int e+ toEither :: Int32 -> Either Int32 e toEither i- | Just e <- Safe.toEnumMay i = Right e+ | Just e <- toProtoEnumMay i = Right e | otherwise = Left i -- | Parse a packed collection of variable-width integer values (any of @int32@,
src/Proto3/Wire/Encode.hs view
@@ -66,6 +66,7 @@ , float , double , enum+ , bool -- * Strings , bytes , string@@ -94,6 +95,7 @@ import qualified Data.Text.Lazy.Encoding as Text.Lazy.Encoding import Data.Word ( Word8, Word32, Word64 ) import qualified Proto3.Wire.Builder as WB+import Proto3.Wire.Class import Proto3.Wire.Types -- $setup@@ -265,16 +267,39 @@ -- | Encode a value with an enumerable type. ----- It can be useful to derive an 'Enum' instance for a type in order to--- emulate enums appearing in .proto files.+-- You should instantiate 'ProtoEnum' for a type in+-- order to emulate enums appearing in .proto files. -- -- For example: ----- >>> data Shape = Circle | Square | Triangle deriving (Enum)--- >>> 1 `enum` True <> 2 `enum` Circle--- Proto3.Wire.Encode.unsafeFromLazyByteString "\b\SOH\DLE\NUL"-enum :: Enum e => FieldNumber -> e -> MessageBuilder-enum num e = fieldHeader num Varint <> base128Varint (fromIntegral (fromEnum e))+-- >>> :{+-- data Shape = Circle | Square | Triangle deriving (Bounded, Enum)+-- instance ProtoEnum Shape+-- data Gap = Gap0 | Gap3+-- instance ProtoEnum Gap where+-- toProtoEnumMay i = case i of+-- 0 -> Just Gap0+-- 3 -> Just Gap3+-- _ -> Nothing+-- fromProtoEnum g = case g of+-- Gap0 -> 0+-- Gap3 -> 3+-- :}+--+-- >>> 1 `enum` Triangle <> 2 `enum` Gap3+-- Proto3.Wire.Encode.unsafeFromLazyByteString "\b\STX\DLE\ETX"+enum :: ProtoEnum e => FieldNumber -> e -> MessageBuilder+enum num e =+ fieldHeader num Varint <> base128Varint (fromIntegral (fromProtoEnum e))++-- | Encode a boolean value+--+-- For example:+--+-- >>> 1 `bool` True+-- Proto3.Wire.Encode.unsafeFromLazyByteString "\b\SOH"+bool :: FieldNumber -> Bool -> MessageBuilder+bool num i = fieldHeader num Varint <> base128Varint (fromIntegral (fromEnum i)) -- | Encode a sequence of octets as a field of type 'bytes'. --
test/Main.hs view
@@ -109,7 +109,7 @@ (Encode.double (fieldNumber 1)) (one Decode.double 0 `at` fieldNumber 1) , roundTrip "bool"- (Encode.enum (fieldNumber 1))+ (Encode.bool (fieldNumber 1)) (one Decode.bool False `at` fieldNumber 1) , roundTrip "text" (Encode.text (fieldNumber 1) . T.pack)