-- | Convenience functions for working with binary RPC
--
-- Intended for qualified import.
--
-- import Network.GRPC.Client.Binary qualified as Binary
module Network.GRPC.Client.Binary (
    -- * Convenience wrappers using @binary@ for serialization/deserialization
    sendInput
  , sendNextInput
  , sendFinalInput
  , recvOutput
  , recvNextOutput
  , recvFinalOutput
  ) where

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

import Network.GRPC.Client (Call)
import Network.GRPC.Client qualified as Client
import Network.GRPC.Common
import Network.GRPC.Common.Binary (decodeOrThrow)

{-------------------------------------------------------------------------------
  Convenience wrappers using @binary@ for serialization/deserialization
-------------------------------------------------------------------------------}

sendInput :: forall inp rpc m.
     (Binary inp, Input rpc ~ Lazy.ByteString, MonadIO m)
  => Call rpc
  -> StreamElem NoMetadata inp
  -> m ()
sendInput :: forall {k} inp (rpc :: k) (m :: * -> *).
(Binary inp, Input rpc ~ ByteString, MonadIO m) =>
Call rpc -> StreamElem NoMetadata inp -> m ()
sendInput Call rpc
call StreamElem NoMetadata inp
inp = Call rpc -> StreamElem NoMetadata (Input rpc) -> m ()
forall {k} (m :: * -> *) (rpc :: k).
(HasCallStack, MonadIO m) =>
Call rpc -> StreamElem NoMetadata (Input rpc) -> m ()
Client.sendInput Call rpc
call (inp -> ByteString
forall a. Binary a => a -> ByteString
encode (inp -> ByteString)
-> StreamElem NoMetadata inp -> StreamElem NoMetadata ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StreamElem NoMetadata inp
inp)

sendNextInput ::
     (Binary inp, Input rpc ~ Lazy.ByteString, MonadIO m)
  => Call rpc
  -> inp
  -> m ()
sendNextInput :: forall {k} inp (rpc :: k) (m :: * -> *).
(Binary inp, Input rpc ~ ByteString, MonadIO m) =>
Call rpc -> inp -> m ()
sendNextInput Call rpc
call inp
inp = Call rpc -> Input rpc -> m ()
forall {k} (m :: * -> *) (rpc :: k).
MonadIO m =>
Call rpc -> Input rpc -> m ()
Client.sendNextInput Call rpc
call (inp -> ByteString
forall a. Binary a => a -> ByteString
encode inp
inp)

sendFinalInput :: forall inp rpc m.
     (Binary inp, Input rpc ~ Lazy.ByteString, MonadIO m)
  => Call rpc
  -> inp
  -> m ()
sendFinalInput :: forall {k} inp (rpc :: k) (m :: * -> *).
(Binary inp, Input rpc ~ ByteString, MonadIO m) =>
Call rpc -> inp -> m ()
sendFinalInput Call rpc
call inp
inp =
   Call rpc -> Input rpc -> m ()
forall {k} (m :: * -> *) (rpc :: k).
MonadIO m =>
Call rpc -> Input rpc -> m ()
Client.sendFinalInput Call rpc
call (inp -> ByteString
forall a. Binary a => a -> ByteString
encode inp
inp)

recvOutput :: forall out rpc m.
     (Binary out, Output rpc ~ Lazy.ByteString, MonadIO m)
  => Call rpc
  -> m (StreamElem (ResponseTrailingMetadata rpc) out)
recvOutput :: forall {k} out (rpc :: k) (m :: * -> *).
(Binary out, Output rpc ~ ByteString, MonadIO m) =>
Call rpc -> m (StreamElem (ResponseTrailingMetadata rpc) out)
recvOutput Call rpc
call =
     Call rpc
-> m (StreamElem (ResponseTrailingMetadata rpc) (Output rpc))
forall {k} (rpc :: k) (m :: * -> *).
(MonadIO m, HasCallStack) =>
Call rpc
-> m (StreamElem (ResponseTrailingMetadata rpc) (Output rpc))
Client.recvOutput Call rpc
call m (StreamElem (ResponseTrailingMetadata rpc) ByteString)
-> (StreamElem (ResponseTrailingMetadata rpc) ByteString
    -> m (StreamElem (ResponseTrailingMetadata rpc) out))
-> m (StreamElem (ResponseTrailingMetadata rpc) out)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (ByteString -> m out)
-> StreamElem (ResponseTrailingMetadata rpc) ByteString
-> m (StreamElem (ResponseTrailingMetadata rpc) out)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b)
-> StreamElem (ResponseTrailingMetadata rpc) a
-> f (StreamElem (ResponseTrailingMetadata rpc) b)
traverse ByteString -> m out
forall (m :: * -> *) a. (MonadIO m, Binary a) => ByteString -> m a
decodeOrThrow

recvNextOutput ::
     (Binary out, Output rpc ~ Lazy.ByteString, MonadIO m)
  => Call rpc
  -> m out
recvNextOutput :: forall {k} out (rpc :: k) (m :: * -> *).
(Binary out, Output rpc ~ ByteString, MonadIO m) =>
Call rpc -> m out
recvNextOutput Call rpc
call = Call rpc -> m (Output rpc)
forall {k} (rpc :: k) (m :: * -> *).
(MonadIO m, HasCallStack) =>
Call rpc -> m (Output rpc)
Client.recvNextOutput Call rpc
call m ByteString -> (ByteString -> m out) -> m out
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> m out
forall (m :: * -> *) a. (MonadIO m, Binary a) => ByteString -> m a
decodeOrThrow

recvFinalOutput :: forall out rpc m.
     (Binary out, Output rpc ~ Lazy.ByteString, MonadIO m)
  => Call rpc
  -> m (out, ResponseTrailingMetadata rpc)
recvFinalOutput :: forall {k} out (rpc :: k) (m :: * -> *).
(Binary out, Output rpc ~ ByteString, MonadIO m) =>
Call rpc -> m (out, ResponseTrailingMetadata rpc)
recvFinalOutput Call rpc
call = do
    (out, md) <- Call rpc -> m (Output rpc, ResponseTrailingMetadata rpc)
forall {k} (rpc :: k) (m :: * -> *).
(MonadIO m, HasCallStack) =>
Call rpc -> m (Output rpc, ResponseTrailingMetadata rpc)
Client.recvFinalOutput Call rpc
call
    (, md) <$> decodeOrThrow out