protobuf-0.2.1.4: src/Data/ProtocolBuffers/Encode.hs
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
module Data.ProtocolBuffers.Encode
( Encode(..)
, encodeMessage
, encodeLengthPrefixedMessage
, GEncode
) where
import Data.Foldable
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Proxy
import Data.Binary.Builder.Sized
import Data.Monoid
import GHC.Generics
import GHC.TypeLits
import Data.ProtocolBuffers.Types
import Data.ProtocolBuffers.Wire
-- |
-- Encode a Protocol Buffers message.
encodeMessage :: Encode a => a -> Builder
encodeMessage = encode
-- |
-- Encode a Protocol Buffers message prefixed with a varint encoded 32-bit integer describing its length.
encodeLengthPrefixedMessage :: Encode a => a -> Builder
{-# INLINE encodeLengthPrefixedMessage #-}
encodeLengthPrefixedMessage msg = (putVarUInt $ size msg') <> msg'
where
msg' = encodeMessage msg
class Encode (a :: *) where
encode :: a -> Builder
default encode :: (Generic a, GEncode (Rep a)) => a -> Builder
encode = gencode . from
-- | Untyped message encoding
instance Encode (HashMap Tag [WireField]) where
encode = foldMap step . HashMap.toList where
step = uncurry (foldMap . encodeWire)
class GEncode (f :: * -> *) where
gencode :: f a -> Builder
instance GEncode a => GEncode (M1 i c a) where
gencode = gencode . unM1
instance (GEncode a, GEncode b) => GEncode (a :*: b) where
gencode (x :*: y) = gencode x <> gencode y
instance (GEncode a, GEncode b) => GEncode (a :+: b) where
gencode (L1 x) = gencode x
gencode (R1 y) = gencode y
instance (EncodeWire a, KnownNat n, Foldable f) => GEncode (K1 i (Field n (f a))) where
gencode = foldMap (encodeWire tag) . runField . unK1 where
tag = fromIntegral $ natVal (Proxy :: Proxy n)
instance GEncode U1 where
gencode _ = empty