{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes                 #-}
{-# LANGUAGE StandaloneDeriving         #-}

module Ouroboros.Network.Protocol.LocalStateQuery.Codec.CDDL where

import Codec.CBOR.Decoding qualified as CBOR
import Codec.CBOR.Encoding qualified as CBOR
import Codec.CBOR.Read qualified as CBOR
import Codec.Serialise (Serialise)
import Codec.Serialise.Class qualified as Serialise
import Control.DeepSeq (NFData (..))
import Data.ByteString.Lazy qualified as BL
import GHC.Generics (Generic)
import Network.TypedProtocol.Codec
import Ouroboros.Network.Protocol.BlockFetch.Codec.CDDL (Block, BlockPoint)
import Ouroboros.Network.Protocol.LocalStateQuery.Codec
import Ouroboros.Network.Protocol.LocalStateQuery.Type
import Test.Data.CDDL (Any)
import Test.QuickCheck (Arbitrary (..))

newtype Result = Result Any
  deriving (Result -> Result -> Bool
(Result -> Result -> Bool)
-> (Result -> Result -> Bool) -> Eq Result
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Result -> Result -> Bool
== :: Result -> Result -> Bool
$c/= :: Result -> Result -> Bool
/= :: Result -> Result -> Bool
Eq, Int -> Result -> ShowS
[Result] -> ShowS
Result -> String
(Int -> Result -> ShowS)
-> (Result -> String) -> ([Result] -> ShowS) -> Show Result
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Result -> ShowS
showsPrec :: Int -> Result -> ShowS
$cshow :: Result -> String
show :: Result -> String
$cshowList :: [Result] -> ShowS
showList :: [Result] -> ShowS
Show, Gen Result
Gen Result -> (Result -> [Result]) -> Arbitrary Result
Result -> [Result]
forall a. Gen a -> (a -> [a]) -> Arbitrary a
$carbitrary :: Gen Result
arbitrary :: Gen Result
$cshrink :: Result -> [Result]
shrink :: Result -> [Result]
Arbitrary, [Result] -> Encoding
Result -> Encoding
(Result -> Encoding)
-> (forall s. Decoder s Result)
-> ([Result] -> Encoding)
-> (forall s. Decoder s [Result])
-> Serialise Result
forall s. Decoder s [Result]
forall s. Decoder s Result
forall a.
(a -> Encoding)
-> (forall s. Decoder s a)
-> ([a] -> Encoding)
-> (forall s. Decoder s [a])
-> Serialise a
$cencode :: Result -> Encoding
encode :: Result -> Encoding
$cdecode :: forall s. Decoder s Result
decode :: forall s. Decoder s Result
$cencodeList :: [Result] -> Encoding
encodeList :: [Result] -> Encoding
$cdecodeList :: forall s. Decoder s [Result]
decodeList :: forall s. Decoder s [Result]
Serialise, (forall x. Result -> Rep Result x)
-> (forall x. Rep Result x -> Result) -> Generic Result
forall x. Rep Result x -> Result
forall x. Result -> Rep Result x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Result -> Rep Result x
from :: forall x. Result -> Rep Result x
$cto :: forall x. Rep Result x -> Result
to :: forall x. Rep Result x -> Result
Generic, Result -> ()
(Result -> ()) -> NFData Result
forall a. (a -> ()) -> NFData a
$crnf :: Result -> ()
rnf :: Result -> ()
NFData)

-- TODO: add payload to the query
data Query result where
    Query :: Any -> Query Result

instance NFData (Query result) where
  rnf :: Query result -> ()
rnf (Query Any
a) = Any -> ()
forall a. NFData a => a -> ()
rnf Any
a

encodeQuery :: Query result -> CBOR.Encoding
encodeQuery :: forall result. Query result -> Encoding
encodeQuery (Query Any
a) = Any -> Encoding
forall a. Serialise a => a -> Encoding
Serialise.encode Any
a

decodeQuery :: forall s. CBOR.Decoder s (Some Query)
decodeQuery :: forall s. Decoder s (Some Query)
decodeQuery = Query Result -> Some Query
forall {k} (f :: k -> *) (a :: k). f a -> Some f
Some (Query Result -> Some Query)
-> (Any -> Query Result) -> Any -> Some Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Any -> Query Result
Query (Any -> Some Query) -> Decoder s Any -> Decoder s (Some Query)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder s Any
forall s. Decoder s Any
forall a s. Serialise a => Decoder s a
Serialise.decode

instance ShowQuery Query where
    showResult :: forall result. Query result -> result -> String
showResult (Query Any
query) result
result = (Any, result) -> String
forall a. Show a => a -> String
show (Any
query, result
result)
deriving instance Show (Query result)

instance Arbitrary (Query Result) where
    arbitrary :: Gen (Query Result)
arbitrary = Any -> Query Result
Query (Any -> Query Result) -> Gen Any -> Gen (Query Result)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Any
forall a. Arbitrary a => Gen a
arbitrary

localStateQueryCodec :: Codec (LocalStateQuery Block BlockPoint Query)
                              CBOR.DeserialiseFailure IO BL.ByteString
localStateQueryCodec :: Codec
  (LocalStateQuery Block BlockPoint Query)
  DeserialiseFailure
  IO
  ByteString
localStateQueryCodec =
    NodeToClientVersion
-> (BlockPoint -> Encoding)
-> (forall s. Decoder s BlockPoint)
-> (forall result. Query result -> Encoding)
-> (forall s. Decoder s (Some Query))
-> (forall result. Query result -> result -> Encoding)
-> (forall result. Query result -> forall s. Decoder s result)
-> Codec
     (LocalStateQuery Block BlockPoint Query)
     DeserialiseFailure
     IO
     ByteString
forall {k} (block :: k) point (query :: * -> *) (m :: * -> *).
(MonadST m, ShowQuery query) =>
NodeToClientVersion
-> (point -> Encoding)
-> (forall s. Decoder s point)
-> (forall result. query result -> Encoding)
-> (forall s. Decoder s (Some query))
-> (forall result. query result -> result -> Encoding)
-> (forall result. query result -> forall s. Decoder s result)
-> Codec
     (LocalStateQuery block point query) DeserialiseFailure m ByteString
codecLocalStateQuery
      NodeToClientVersion
forall a. Bounded a => a
maxBound
      BlockPoint -> Encoding
forall a. Serialise a => a -> Encoding
Serialise.encode Decoder s BlockPoint
forall s. Decoder s BlockPoint
forall a s. Serialise a => Decoder s a
Serialise.decode
      Query result -> Encoding
forall result. Query result -> Encoding
encodeQuery Decoder s (Some Query)
forall s. Decoder s (Some Query)
decodeQuery
      (\Query{} -> result -> Encoding
forall a. Serialise a => a -> Encoding
Serialise.encode) (\Query{} -> Decoder s result
forall {s}. Decoder s result
forall a s. Serialise a => Decoder s a
Serialise.decode)