module Network.GRPC.Server.StreamType.Binary (
    -- * Construct handlers
    mkNonStreaming
  , mkClientStreaming
  , mkServerStreaming
  , mkBiDiStreaming
  ) where

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

import Network.GRPC.Common
import Network.GRPC.Common.Binary (decodeOrThrow)
import Network.GRPC.Common.StreamType
import Network.GRPC.Server.StreamType qualified as StreamType
import Network.GRPC.Spec

{-------------------------------------------------------------------------------
  Handlers for specific streaming types

  It may sometimes be useful to use explicit type applications with these
  functions, which is why the @rpc@ type variable is always first, followed by
  the @inp@ and @out@ parameters, which may also be ambiguous in certain cases.
-------------------------------------------------------------------------------}

mkNonStreaming :: forall rpc inp out m.
     ( SupportsStreamingType rpc NonStreaming
     , Binary inp, Input  rpc ~ Lazy.ByteString
     , Binary out, Output rpc ~ Lazy.ByteString
     , MonadIO m
     )
  => (    inp
       -> m out
     )
  -> ServerHandler' NonStreaming m rpc
mkNonStreaming :: forall {k} (rpc :: k) inp out (m :: * -> *).
(SupportsStreamingType rpc 'NonStreaming, Binary inp,
 Input rpc ~ ByteString, Binary out, Output rpc ~ ByteString,
 MonadIO m) =>
(inp -> m out) -> ServerHandler' 'NonStreaming m rpc
mkNonStreaming inp -> m out
f = (Input rpc -> m (Output rpc)) -> ServerHandler' 'NonStreaming m rpc
forall {k} (rpc :: k) (m :: * -> *).
SupportsStreamingType rpc 'NonStreaming =>
(Input rpc -> m (Output rpc)) -> ServerHandler' 'NonStreaming m rpc
StreamType.mkNonStreaming ((Input rpc -> m (Output rpc))
 -> ServerHandler' 'NonStreaming m rpc)
-> (Input rpc -> m (Output rpc))
-> ServerHandler' 'NonStreaming m rpc
forall a b. (a -> b) -> a -> b
$ \Input rpc
inp -> do
    inp' <- ByteString -> m inp
forall (m :: * -> *) a. (MonadIO m, Binary a) => ByteString -> m a
decodeOrThrow ByteString
Input rpc
inp
    encode <$> f inp'

mkClientStreaming :: forall rpc out m.
     ( SupportsStreamingType rpc ClientStreaming
     , Binary out, Output rpc ~ Lazy.ByteString
     , MonadIO m
     )
  => (    (forall inp.
                (Binary inp, Input rpc ~ Lazy.ByteString)
             => m (NextElem inp)
          )
       -> m out
     )
  -> ServerHandler' ClientStreaming m rpc
mkClientStreaming :: forall {k} (rpc :: k) out (m :: * -> *).
(SupportsStreamingType rpc 'ClientStreaming, Binary out,
 Output rpc ~ ByteString, MonadIO m) =>
((forall inp.
  (Binary inp, Input rpc ~ ByteString) =>
  m (NextElem inp))
 -> m out)
-> ServerHandler' 'ClientStreaming m rpc
mkClientStreaming (forall inp.
 (Binary inp, Input rpc ~ ByteString) =>
 m (NextElem inp))
-> m out
f = (IO (NextElem (Input rpc)) -> m (Output rpc))
-> ServerHandler' 'ClientStreaming m rpc
forall {k} (rpc :: k) (m :: * -> *).
SupportsStreamingType rpc 'ClientStreaming =>
(IO (NextElem (Input rpc)) -> m (Output rpc))
-> ServerHandler' 'ClientStreaming m rpc
StreamType.mkClientStreaming ((IO (NextElem (Input rpc)) -> m (Output rpc))
 -> ServerHandler' 'ClientStreaming m rpc)
-> (IO (NextElem (Input rpc)) -> m (Output rpc))
-> ServerHandler' 'ClientStreaming m rpc
forall a b. (a -> b) -> a -> b
$ \IO (NextElem (Input rpc))
recv -> do
    out <- (forall inp.
 (Binary inp, Input rpc ~ ByteString) =>
 m (NextElem inp))
-> m out
f (IO (NextElem ByteString) -> m (NextElem ByteString)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (NextElem ByteString)
IO (NextElem (Input rpc))
recv m (NextElem ByteString)
-> (NextElem ByteString -> m (NextElem inp)) -> m (NextElem inp)
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 inp) -> NextElem ByteString -> m (NextElem inp)
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) -> NextElem a -> f (NextElem b)
traverse ByteString -> m inp
forall (m :: * -> *) a. (MonadIO m, Binary a) => ByteString -> m a
decodeOrThrow)
    return $ encode out

mkServerStreaming :: forall rpc inp m.
     ( SupportsStreamingType rpc ServerStreaming
     , Binary inp, Input rpc ~ Lazy.ByteString
     , MonadIO m
     )
  => (    inp
       -> (forall out.
                (Binary out, Output rpc ~ Lazy.ByteString)
             => NextElem out -> m ()
          )
       -> m ()
     )
  -> ServerHandler' ServerStreaming m rpc
mkServerStreaming :: forall {k} (rpc :: k) inp (m :: * -> *).
(SupportsStreamingType rpc 'ServerStreaming, Binary inp,
 Input rpc ~ ByteString, MonadIO m) =>
(inp
 -> (forall out.
     (Binary out, Output rpc ~ ByteString) =>
     NextElem out -> m ())
 -> m ())
-> ServerHandler' 'ServerStreaming m rpc
mkServerStreaming inp
-> (forall out.
    (Binary out, Output rpc ~ ByteString) =>
    NextElem out -> m ())
-> m ()
f = (Input rpc -> (NextElem (Output rpc) -> IO ()) -> m ())
-> ServerHandler' 'ServerStreaming m rpc
forall {k} (rpc :: k) (m :: * -> *).
SupportsStreamingType rpc 'ServerStreaming =>
(Input rpc -> (NextElem (Output rpc) -> IO ()) -> m ())
-> ServerHandler' 'ServerStreaming m rpc
StreamType.mkServerStreaming ((Input rpc -> (NextElem (Output rpc) -> IO ()) -> m ())
 -> ServerHandler' 'ServerStreaming m rpc)
-> (Input rpc -> (NextElem (Output rpc) -> IO ()) -> m ())
-> ServerHandler' 'ServerStreaming m rpc
forall a b. (a -> b) -> a -> b
$ \Input rpc
inp NextElem (Output rpc) -> IO ()
send -> do
    inp' <- ByteString -> m inp
forall (m :: * -> *) a. (MonadIO m, Binary a) => ByteString -> m a
decodeOrThrow ByteString
Input rpc
inp
    f inp' (liftIO . send . fmap encode)

mkBiDiStreaming :: forall rpc m.
     ( SupportsStreamingType rpc BiDiStreaming
     , MonadIO m
     )
  => (    (forall inp.
                (Binary inp, Input rpc ~ Lazy.ByteString)
             => m (NextElem inp)
          )
       -> (forall out.
                (Binary out, Output rpc ~ Lazy.ByteString)
             => NextElem out -> m ()
          )
       -> m ()
     )
  -> ServerHandler' BiDiStreaming m rpc
mkBiDiStreaming :: forall {k} (rpc :: k) (m :: * -> *).
(SupportsStreamingType rpc 'BiDiStreaming, MonadIO m) =>
((forall inp.
  (Binary inp, Input rpc ~ ByteString) =>
  m (NextElem inp))
 -> (forall out.
     (Binary out, Output rpc ~ ByteString) =>
     NextElem out -> m ())
 -> m ())
-> ServerHandler' 'BiDiStreaming m rpc
mkBiDiStreaming (forall inp.
 (Binary inp, Input rpc ~ ByteString) =>
 m (NextElem inp))
-> (forall out.
    (Binary out, Output rpc ~ ByteString) =>
    NextElem out -> m ())
-> m ()
f = (IO (NextElem (Input rpc))
 -> (NextElem (Output rpc) -> IO ()) -> m ())
-> ServerHandler' 'BiDiStreaming m rpc
forall {k} (rpc :: k) (m :: * -> *).
SupportsStreamingType rpc 'BiDiStreaming =>
(IO (NextElem (Input rpc))
 -> (NextElem (Output rpc) -> IO ()) -> m ())
-> ServerHandler' 'BiDiStreaming m rpc
StreamType.mkBiDiStreaming ((IO (NextElem (Input rpc))
  -> (NextElem (Output rpc) -> IO ()) -> m ())
 -> ServerHandler' 'BiDiStreaming m rpc)
-> (IO (NextElem (Input rpc))
    -> (NextElem (Output rpc) -> IO ()) -> m ())
-> ServerHandler' 'BiDiStreaming m rpc
forall a b. (a -> b) -> a -> b
$ \IO (NextElem (Input rpc))
recv NextElem (Output rpc) -> IO ()
send ->
    (forall inp.
 (Binary inp, Input rpc ~ ByteString) =>
 m (NextElem inp))
-> (forall out.
    (Binary out, Output rpc ~ ByteString) =>
    NextElem out -> m ())
-> m ()
f (IO (NextElem ByteString) -> m (NextElem ByteString)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (NextElem ByteString)
IO (NextElem (Input rpc))
recv m (NextElem ByteString)
-> (NextElem ByteString -> m (NextElem inp)) -> m (NextElem inp)
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 inp) -> NextElem ByteString -> m (NextElem inp)
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) -> NextElem a -> f (NextElem b)
traverse ByteString -> m inp
forall (m :: * -> *) a. (MonadIO m, Binary a) => ByteString -> m a
decodeOrThrow) (IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (NextElem out -> IO ()) -> NextElem out -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NextElem ByteString -> IO ()
NextElem (Output rpc) -> IO ()
send (NextElem ByteString -> IO ())
-> (NextElem out -> NextElem ByteString) -> NextElem out -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (out -> ByteString) -> NextElem out -> NextElem ByteString
forall a b. (a -> b) -> NextElem a -> NextElem b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap out -> ByteString
forall a. Binary a => a -> ByteString
encode)