{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Network.GRPC.HTTP2.Encoding (
GRPCInput(..)
, GRPCOutput(..)
, Builder
, Decoder
, fromBuilder
, fromDecoder
, Compression(..)
, Encoding(..)
, Decoding(..)
, grpcCompressionHV
, uncompressed
, gzip
) where
import qualified Codec.Compression.GZip as GZip
import Data.Binary.Builder (toLazyByteString, Builder)
import Data.Binary.Get (Decoder(..), Get)
import Data.ByteString.Char8 (ByteString)
import Data.ByteString.Lazy (fromStrict, toStrict)
import Network.GRPC.HTTP2.Types
class IsRPC r => GRPCInput r i where
encodeInput :: r -> Compression -> i -> Builder
decodeInput :: r -> Compression -> Decoder (Either String i)
class IsRPC r => GRPCOutput r o where
encodeOutput :: r -> Compression -> o -> Builder
decodeOutput :: r -> Compression -> Decoder (Either String o)
fromBuilder :: Builder -> ByteString
fromBuilder = toStrict . toLazyByteString
fromDecoder :: Decoder (Either String a) -> Either String a
fromDecoder (Fail _ _ msg) = Left msg
fromDecoder (Partial _) = Left "got only a subet of the message"
fromDecoder (Done _ _ val) = val
data Compression = Compression {
_compressionName :: ByteString
, _compressionByteSet :: Bool
, _compressionFunction :: ByteString -> ByteString
, _decompressionFunction :: ByteString -> Get ByteString
}
newtype Encoding = Encoding { _getEncodingCompression :: Compression }
newtype Decoding = Decoding { _getDecodingCompression :: Compression }
grpcCompressionHV :: Compression -> HeaderValue
grpcCompressionHV = _compressionName
uncompressed :: Compression
uncompressed = Compression "identity" False id (\_ -> fail "decoder uninstalled")
gzip :: Compression
gzip = Compression "gzip" True
(toStrict . GZip.compress . fromStrict)
(pure . toStrict . GZip.decompress . fromStrict)