Safe Haskell | None |
---|---|
Language | Haskell2010 |
This module provides type classes for encoding and decoding protocol
buffers message, as well as a safer alternative to the raw Wire
library based on Generics
.
Classes
The Primitive
class captures those types which correspond to primitive field
types, as defined by the protocol buffers specification. A Primitive
type is
one which can always be encoded as a single key/value pair in the wire format.
The MessageField
class captures those types which are encoded under a single
key in the wire format, i.e. primitives, packed and unpacked lists, and
embedded messages.
The Message
class captures types which correspond to protocol buffers messages.
Instances of Message
can be written by hand for your types by using the
functions in the Encode
and Decode
modules. In the case where the message format is determined by your Haskell code,
you might prefer to derive your Message
instances using generic deriving.
Generic Instances
Using the Generics
approach, instead of generating Haskell code from a
.proto file, we write our message formats as Haskell types, and generate a
serializer/deserializer pair.
To use this library, simply derive a Generic
instance for your type(s), and
use the default Message
instance.
For generic Message
instances, field numbers are automatically generated,
starting at 1. Therefore, adding new fields is a compatible change only at the
end of a record. Renaming fields is also safe. You should not use the generic
instances if you are starting from an existing .proto file.
Strings
Use Text
instead of String
for string types inside messages.
Example
data MultipleFields = MultipleFields { multiFieldDouble :: Double , multiFieldFloat :: Float , multiFieldInt32 :: Int32 , multiFieldInt64 :: Int64 , multiFieldString :: TL.Text , multiFieldBool :: Bool } deriving (Show, Generic, Eq) instance Message MultipleFields serialized = toLazyByteString $ MultipleFields 1.0 1.0 1 1 "hi" True deserialized :: MultipleFields deserialized = case parse (toStrict serialized) of Left e -> error e Right msg -> msg
Synopsis
- class Primitive a where
- encodePrimitive :: FieldNumber -> a -> MessageBuilder
- decodePrimitive :: Parser RawPrimitive a
- primType :: Proxy# a -> DotProtoPrimType
- class MessageField a where
- encodeMessageField :: FieldNumber -> a -> MessageBuilder
- decodeMessageField :: Parser RawField a
- protoType :: Proxy# a -> DotProtoField
- class Message a where
- encodeMessage :: FieldNumber -> a -> MessageBuilder
- decodeMessage :: FieldNumber -> Parser RawMessage a
- dotProto :: Proxy# a -> [DotProtoField]
- toLazyByteString :: Message a => a -> ByteString
- class HasDefault a where
- fromByteString :: Message a => ByteString -> Either ParseError a
- fromB64 :: Message a => ByteString -> Either ParseError a
- class Named a where
- class ProtoEnum a => Finite a where
- message :: (Message a, Named a) => Proxy# a -> DotProtoDefinition
- enum :: (Finite e, Named e) => Proxy# e -> DotProtoDefinition
- class GenericMessage (f :: * -> *) where
- type GenericFieldCount f :: Nat
- genericEncodeMessage :: FieldNumber -> f a -> MessageBuilder
- genericDecodeMessage :: FieldNumber -> Parser RawMessage (f a)
- genericDotProto :: Proxy# f -> [DotProtoField]
Documentation
class Primitive a where Source #
This class captures those types which correspond to primitives in the protocol buffers specification.
It should be possible to fully reconstruct values of these types from
a single RawPrimitive
. Notably, then, Nested
is not Primitive
even
though it can be embedded
, since a nested message may by split up over
multiple embedded
fields.
encodePrimitive :: FieldNumber -> a -> MessageBuilder Source #
Encode a primitive value
decodePrimitive :: Parser RawPrimitive a Source #
Decode a primitive value
primType :: Proxy# a -> DotProtoPrimType Source #
Get the type which represents this type inside another message.
Instances
class MessageField a where Source #
This class captures those types which can appear as message fields in
the protocol buffers specification, i.e. Primitive
types, or lists of
Primitive
types
Nothing
encodeMessageField :: FieldNumber -> a -> MessageBuilder Source #
Encode a message field
default encodeMessageField :: (HasDefault a, Primitive a) => FieldNumber -> a -> MessageBuilder Source #
decodeMessageField :: Parser RawField a Source #
Decode a message field
default decodeMessageField :: (HasDefault a, Primitive a) => Parser RawField a Source #
protoType :: Proxy# a -> DotProtoField Source #
Get the type which represents this type inside another message.
Instances
class Message a where Source #
This class captures those types which correspond to protocol buffer messages.
Nothing
encodeMessage :: FieldNumber -> a -> MessageBuilder Source #
Encode a message
default encodeMessage :: (Generic a, GenericMessage (Rep a)) => FieldNumber -> a -> MessageBuilder Source #
decodeMessage :: FieldNumber -> Parser RawMessage a Source #
Decode a message
default decodeMessage :: (Generic a, GenericMessage (Rep a)) => FieldNumber -> Parser RawMessage a Source #
dotProto :: Proxy# a -> [DotProtoField] Source #
Generate a .proto message from the type information.
default dotProto :: GenericMessage (Rep a) => Proxy# a -> [DotProtoField] Source #
Instances
Encoding
toLazyByteString :: Message a => a -> ByteString Source #
Serialize a message as a lazy ByteString
.
Decoding
class HasDefault a where Source #
A class for types with default values per the protocol buffers spec.
Nothing
The default value for this type.
Instances
fromByteString :: Message a => ByteString -> Either ParseError a Source #
Parse any message that can be decoded.
fromB64 :: Message a => ByteString -> Either ParseError a Source #
As fromByteString
, except the input bytestring is base64-encoded.
Documentation
This class captures those types whose names need to appear in .proto files.
It has a default implementation for any data type which is an instance of the
Generic
class, which will extract the name of the type constructor.
Nothing
class ProtoEnum a => Finite a where Source #
Enumerable types with finitely many values.
This class can be derived whenever a sum type is an instance of Generic
,
and only consists of zero-argument constructors. The derived instance should
be compatible with ProtoEnum
instances, in the sense that
map (fromJust . toProtoEnumMay . snd) enumerate
should enumerate all values of the type without runtime errors.
Nothing
message :: (Message a, Named a) => Proxy# a -> DotProtoDefinition Source #
Generate metadata for a message type.
enum :: (Finite e, Named e) => Proxy# e -> DotProtoDefinition Source #
Generate metadata for an enum type.
Generic Classes
class GenericMessage (f :: * -> *) where Source #
type GenericFieldCount f :: Nat Source #
genericEncodeMessage :: FieldNumber -> f a -> MessageBuilder Source #
genericDecodeMessage :: FieldNumber -> Parser RawMessage (f a) Source #
genericDotProto :: Proxy# f -> [DotProtoField] Source #