-- | [Conduit](https://hackage.haskell.org/package/conduit) interface
module Network.GRPC.Client.StreamType.Conduit (
    -- * Run client handlers
    clientStreaming
  , clientStreaming_
  , serverStreaming
  , biDiStreaming
  ) where

import Control.Monad.Reader
import Data.Conduit
import Data.ProtoLens.Service.Types

import Network.GRPC.Client
import Network.GRPC.Client.StreamType.IO qualified as IO
import Network.GRPC.Common
import Network.GRPC.Spec

{-------------------------------------------------------------------------------
  Conduits for different kinds of streaming types (communication patterns)
-------------------------------------------------------------------------------}

clientStreaming ::
     MonadIO m
  => Connection
  -> ClientHandler' ClientStreaming (ReaderT Connection m) rpc
  -> (    ConduitT (Input rpc) Void m ()
       -> m r
     )
  -> m (Output rpc, r)
clientStreaming :: forall {k} (m :: * -> *) (rpc :: k) r.
MonadIO m =>
Connection
-> ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
-> (ConduitT (Input rpc) Void m () -> m r)
-> m (Output rpc, r)
clientStreaming Connection
conn ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
h ConduitT (Input rpc) Void m () -> m r
k =
    Connection
-> ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
-> ((NextElem (Input rpc) -> m ()) -> m r)
-> m (Output rpc, r)
forall {k} (rpc :: k) (m :: * -> *) r.
MonadIO m =>
Connection
-> ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
-> ((NextElem (Input rpc) -> m ()) -> m r)
-> m (Output rpc, r)
IO.clientStreaming Connection
conn ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
h (((NextElem (Input rpc) -> m ()) -> m r) -> m (Output rpc, r))
-> ((NextElem (Input rpc) -> m ()) -> m r) -> m (Output rpc, r)
forall a b. (a -> b) -> a -> b
$ \NextElem (Input rpc) -> m ()
send ->
      ConduitT (Input rpc) Void m () -> m r
k (ConduitT (Input rpc) Void m () -> m r)
-> ConduitT (Input rpc) Void m () -> m r
forall a b. (a -> b) -> a -> b
$ (NextElem (Input rpc) -> m ()) -> ConduitT (Input rpc) Void m ()
forall (m :: * -> *) a.
Monad m =>
(NextElem a -> m ()) -> ConduitT a Void m ()
toSink NextElem (Input rpc) -> m ()
send

clientStreaming_ ::
     MonadIO m
  => Connection
  -> ClientHandler' ClientStreaming (ReaderT Connection m) rpc
  -> (    ConduitT (Input rpc) Void m ()
       -> m ()
     )
  -> m (Output rpc)
clientStreaming_ :: forall {k} (m :: * -> *) (rpc :: k).
MonadIO m =>
Connection
-> ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
-> (ConduitT (Input rpc) Void m () -> m ())
-> m (Output rpc)
clientStreaming_ Connection
conn ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
h ConduitT (Input rpc) Void m () -> m ()
k =
    (Output rpc, ()) -> Output rpc
forall a b. (a, b) -> a
fst ((Output rpc, ()) -> Output rpc)
-> m (Output rpc, ()) -> m (Output rpc)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Connection
-> ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
-> (ConduitT (Input rpc) Void m () -> m ())
-> m (Output rpc, ())
forall {k} (m :: * -> *) (rpc :: k) r.
MonadIO m =>
Connection
-> ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
-> (ConduitT (Input rpc) Void m () -> m r)
-> m (Output rpc, r)
clientStreaming Connection
conn ClientHandler' 'ClientStreaming (ReaderT Connection m) rpc
h ConduitT (Input rpc) Void m () -> m ()
k

serverStreaming ::
     MonadIO m
  => Connection
  -> ClientHandler' ServerStreaming (ReaderT Connection m) rpc
  -> Input rpc
  -> (    ConduitT () (Output rpc) m ()
       -> m r
     )
  -> m r
serverStreaming :: forall {k} (m :: * -> *) (rpc :: k) r.
MonadIO m =>
Connection
-> ClientHandler' 'ServerStreaming (ReaderT Connection m) rpc
-> Input rpc
-> (ConduitT () (Output rpc) m () -> m r)
-> m r
serverStreaming Connection
conn ClientHandler' 'ServerStreaming (ReaderT Connection m) rpc
h Input rpc
input ConduitT () (Output rpc) m () -> m r
k =
    Connection
-> ClientHandler' 'ServerStreaming (ReaderT Connection m) rpc
-> Input rpc
-> (m (NextElem (Output rpc)) -> m r)
-> m r
forall {k} (rpc :: k) (m :: * -> *) r.
MonadIO m =>
Connection
-> ClientHandler' 'ServerStreaming (ReaderT Connection m) rpc
-> Input rpc
-> (m (NextElem (Output rpc)) -> m r)
-> m r
IO.serverStreaming Connection
conn ClientHandler' 'ServerStreaming (ReaderT Connection m) rpc
h Input rpc
input ((m (NextElem (Output rpc)) -> m r) -> m r)
-> (m (NextElem (Output rpc)) -> m r) -> m r
forall a b. (a -> b) -> a -> b
$ \m (NextElem (Output rpc))
recv ->
      ConduitT () (Output rpc) m () -> m r
k (ConduitT () (Output rpc) m () -> m r)
-> ConduitT () (Output rpc) m () -> m r
forall a b. (a -> b) -> a -> b
$ m (NextElem (Output rpc)) -> ConduitT () (Output rpc) m ()
forall (m :: * -> *) a.
Monad m =>
m (NextElem a) -> ConduitT () a m ()
toSource m (NextElem (Output rpc))
recv

biDiStreaming :: forall rpc m r.
     MonadIO m
  => Connection
  -> ClientHandler' BiDiStreaming (ReaderT Connection m) rpc
  -> (    ConduitT (Input rpc) Void         m ()
       -> ConduitT ()          (Output rpc) m ()
       -> m r
     )
  -> m r
biDiStreaming :: forall {k} (rpc :: k) (m :: * -> *) r.
MonadIO m =>
Connection
-> ClientHandler' 'BiDiStreaming (ReaderT Connection m) rpc
-> (ConduitT (Input rpc) Void m ()
    -> ConduitT () (Output rpc) m () -> m r)
-> m r
biDiStreaming Connection
conn ClientHandler' 'BiDiStreaming (ReaderT Connection m) rpc
h ConduitT (Input rpc) Void m ()
-> ConduitT () (Output rpc) m () -> m r
k =
    Connection
-> ClientHandler' 'BiDiStreaming (ReaderT Connection m) rpc
-> ((NextElem (Input rpc) -> m ())
    -> m (NextElem (Output rpc)) -> m r)
-> m r
forall {k} (rpc :: k) (m :: * -> *) r.
MonadIO m =>
Connection
-> ClientHandler' 'BiDiStreaming (ReaderT Connection m) rpc
-> ((NextElem (Input rpc) -> m ())
    -> m (NextElem (Output rpc)) -> m r)
-> m r
IO.biDiStreaming Connection
conn ClientHandler' 'BiDiStreaming (ReaderT Connection m) rpc
h (((NextElem (Input rpc) -> m ())
  -> m (NextElem (Output rpc)) -> m r)
 -> m r)
-> ((NextElem (Input rpc) -> m ())
    -> m (NextElem (Output rpc)) -> m r)
-> m r
forall a b. (a -> b) -> a -> b
$ \NextElem (Input rpc) -> m ()
send m (NextElem (Output rpc))
recv ->
      ConduitT (Input rpc) Void m ()
-> ConduitT () (Output rpc) m () -> m r
k ((NextElem (Input rpc) -> m ()) -> ConduitT (Input rpc) Void m ()
forall (m :: * -> *) a.
Monad m =>
(NextElem a -> m ()) -> ConduitT a Void m ()
toSink NextElem (Input rpc) -> m ()
send) (m (NextElem (Output rpc)) -> ConduitT () (Output rpc) m ()
forall (m :: * -> *) a.
Monad m =>
m (NextElem a) -> ConduitT () a m ()
toSource m (NextElem (Output rpc))
recv)

{-------------------------------------------------------------------------------
  Internal auxiliary: conduit
-------------------------------------------------------------------------------}

toSource :: forall m a. Monad m => m (NextElem a) -> ConduitT () a m ()
toSource :: forall (m :: * -> *) a.
Monad m =>
m (NextElem a) -> ConduitT () a m ()
toSource m (NextElem a)
f = ConduitT () a m ()
loop
  where
    loop :: ConduitT () a m ()
    loop :: ConduitT () a m ()
loop = do
        ma <- m (NextElem a) -> ConduitT () a m (NextElem a)
forall (m :: * -> *) a. Monad m => m a -> ConduitT () a m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m (NextElem a)
f
        case ma of
          NextElem a
NoNextElem -> () -> ConduitT () a m ()
forall a. a -> ConduitT () a m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
          NextElem a
a -> a -> ConduitT () a m ()
forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
yield a
a ConduitT () a m () -> ConduitT () a m () -> ConduitT () a m ()
forall a b.
ConduitT () a m a -> ConduitT () a m b -> ConduitT () a m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ConduitT () a m ()
loop

toSink :: forall m a. Monad m => (NextElem a -> m ()) -> ConduitT a Void m ()
toSink :: forall (m :: * -> *) a.
Monad m =>
(NextElem a -> m ()) -> ConduitT a Void m ()
toSink NextElem a -> m ()
f = ConduitT a Void m ()
loop
  where
    loop :: ConduitT a Void m ()
    loop :: ConduitT a Void m ()
loop = do
        ma <- ConduitT a Void m (Maybe a)
forall (m :: * -> *) i o. Monad m => ConduitT i o m (Maybe i)
await
        case ma of
          Maybe a
Nothing -> m () -> ConduitT a Void m ()
forall (m :: * -> *) a. Monad m => m a -> ConduitT a Void m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NextElem a -> m ()
f (NextElem a -> m ()) -> NextElem a -> m ()
forall a b. (a -> b) -> a -> b
$ NextElem a
forall a. NextElem a
NoNextElem)
          Just a
a  -> m () -> ConduitT a Void m ()
forall (m :: * -> *) a. Monad m => m a -> ConduitT a Void m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NextElem a -> m ()
f (NextElem a -> m ()) -> NextElem a -> m ()
forall a b. (a -> b) -> a -> b
$ a -> NextElem a
forall a. a -> NextElem a
NextElem a
a) ConduitT a Void m ()
-> ConduitT a Void m () -> ConduitT a Void m ()
forall a b.
ConduitT a Void m a -> ConduitT a Void m b -> ConduitT a Void m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ConduitT a Void m ()
loop