packages feed

grapesy-1.0.0: src/Network/GRPC/Common/Binary.hs

-- | Binary RPC
--
-- Intended for unqualified import.
module Network.GRPC.Common.Binary (
    RawRpc
    -- * Encoding and decoding
  , encode
  , decodeOrThrow
  , DecodeException(..)
  ) where

import Control.Exception
import Control.Monad.IO.Class
import Data.Binary
import Data.Binary.Get qualified as Binary
import Data.ByteString.Lazy qualified as BS.Lazy
import Data.ByteString.Lazy qualified as Lazy (ByteString)

import Network.GRPC.Spec

{-------------------------------------------------------------------------------
  Decoding
-------------------------------------------------------------------------------}

decodeOrThrow :: (MonadIO m, Binary a) => Lazy.ByteString -> m a
decodeOrThrow bs = liftIO $
    case decodeOrFail bs of
      Left (unconsumed, consumed, errorMessage) ->
        throwIO $ DecodeException{unconsumed, consumed, errorMessage}
      Right (unconsumed, consumed, a) ->
        if BS.Lazy.null unconsumed then
          return a
        else do
          let errorMessage = "Not all bytes consumed"
          throwIO $ DecodeException{unconsumed, consumed, errorMessage}

data DecodeException =
    DecodeException {
        unconsumed   :: Lazy.ByteString
      , consumed     :: Binary.ByteOffset
      , errorMessage :: String
      }
  deriving stock (Show)
  deriving anyclass (Exception)