{-# LANGUAGE OverloadedStrings #-}

module Network.GRPC.Spec.RPC.Raw (RawRpc) where

import Data.ByteString.Char8 qualified as BS.Char8
import Data.ByteString.Lazy qualified as Lazy (ByteString)
import Data.Proxy
import GHC.TypeLits

import Network.GRPC.Spec.CustomMetadata.Typed
import Network.GRPC.Spec.RPC
import Network.GRPC.Spec.RPC.StreamType

{-------------------------------------------------------------------------------
  Raw format
-------------------------------------------------------------------------------}

-- | Custom gRPC format
--
-- Usually @gRPC@ runs over Protobuf, but it does not have to. 'RawRpc' provides
-- an alternative format, which does not use serialization/deserialization at
-- all, just using raw bytestrings for messages. This is a non-standard format
-- (which the gRPC specification explicitly permits).
data RawRpc (serv :: Symbol) (meth :: Symbol)

type instance Input  (RawRpc serv meth) = Lazy.ByteString
type instance Output (RawRpc serv meth) = Lazy.ByteString

instance ( KnownSymbol serv
         , KnownSymbol meth

           -- Metadata constraints
         , Show (RequestMetadata (RawRpc serv meth))
         , Show (ResponseInitialMetadata (RawRpc serv meth))
         , Show (ResponseTrailingMetadata (RawRpc serv meth))
         ) => IsRPC (RawRpc serv meth) where
  rpcContentType :: Proxy (RawRpc serv meth) -> ByteString
rpcContentType Proxy (RawRpc serv meth)
_ = ByteString -> ByteString
defaultRpcContentType ByteString
"raw"
  rpcServiceName :: HasCallStack => Proxy (RawRpc serv meth) -> ByteString
rpcServiceName Proxy (RawRpc serv meth)
_ = String -> ByteString
BS.Char8.pack (String -> ByteString) -> String -> ByteString
forall a b. (a -> b) -> a -> b
$ Proxy serv -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @serv)
  rpcMethodName :: HasCallStack => Proxy (RawRpc serv meth) -> ByteString
rpcMethodName  Proxy (RawRpc serv meth)
_ = String -> ByteString
BS.Char8.pack (String -> ByteString) -> String -> ByteString
forall a b. (a -> b) -> a -> b
$ Proxy meth -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @meth)
  rpcMessageType :: HasCallStack => Proxy (RawRpc serv meth) -> Maybe ByteString
rpcMessageType Proxy (RawRpc serv meth)
_ = Maybe ByteString
forall a. Maybe a
Nothing

instance ( IsRPC (RawRpc serv meth)

           -- Metadata constraints
         , BuildMetadata (RequestMetadata (RawRpc serv meth))
         , ParseMetadata (ResponseInitialMetadata (RawRpc serv meth))
         , ParseMetadata (ResponseTrailingMetadata (RawRpc serv meth))
         ) => SupportsClientRpc (RawRpc serv meth) where
  rpcSerializeInput :: Proxy (RawRpc serv meth) -> Input (RawRpc serv meth) -> ByteString
rpcSerializeInput    Proxy (RawRpc serv meth)
_ = ByteString -> ByteString
Input (RawRpc serv meth) -> ByteString
forall a. a -> a
id
  rpcDeserializeOutput :: Proxy (RawRpc serv meth)
-> ByteString -> Either String (Output (RawRpc serv meth))
rpcDeserializeOutput Proxy (RawRpc serv meth)
_ = ByteString -> Either String ByteString
ByteString -> Either String (Output (RawRpc serv meth))
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return

instance ( IsRPC (RawRpc serv meth)

           -- Metadata constraints
         , ParseMetadata (RequestMetadata (RawRpc serv meth))
         , BuildMetadata (ResponseInitialMetadata (RawRpc serv meth))
         , StaticMetadata (ResponseTrailingMetadata (RawRpc serv meth))
         ) => SupportsServerRpc (RawRpc serv meth) where
  rpcDeserializeInput :: Proxy (RawRpc serv meth)
-> ByteString -> Either String (Input (RawRpc serv meth))
rpcDeserializeInput Proxy (RawRpc serv meth)
_ = ByteString -> Either String ByteString
ByteString -> Either String (Input (RawRpc serv meth))
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return
  rpcSerializeOutput :: Proxy (RawRpc serv meth) -> Output (RawRpc serv meth) -> ByteString
rpcSerializeOutput  Proxy (RawRpc serv meth)
_ = ByteString -> ByteString
Output (RawRpc serv meth) -> ByteString
forall a. a -> a
id

-- | For the raw protocol we do not check communication protocols
instance ValidStreamingType styp
      => SupportsStreamingType (RawRpc serv meth) styp