{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Ouroboros.Network.Protocol.PeerSharing.Examples where

import Data.Word (Word8)
import Ouroboros.Network.Protocol.PeerSharing.Client (PeerSharingClient (..))
import Ouroboros.Network.Protocol.PeerSharing.Server (PeerSharingServer (..))
import Ouroboros.Network.Protocol.PeerSharing.Type (PeerSharingAmount (..))
import Test.QuickCheck.Function (Fun, applyFun)


-- | A client which collects answers whenever it receives
-- 'MsgSharePeers' and returns the result.
--
peerSharingClientCollect :: forall peer m . Monad m
                         => [PeerSharingAmount]
                         -> PeerSharingClient peer m [peer]
peerSharingClientCollect :: forall peer (m :: * -> *).
Monad m =>
[PeerSharingAmount] -> PeerSharingClient peer m [peer]
peerSharingClientCollect = [peer] -> [PeerSharingAmount] -> PeerSharingClient peer m [peer]
go []
  where
    go :: [peer] -> [PeerSharingAmount] -> PeerSharingClient peer m [peer]
    go :: [peer] -> [PeerSharingAmount] -> PeerSharingClient peer m [peer]
go [peer]
acc []    = m [peer] -> PeerSharingClient peer m [peer]
forall (m :: * -> *) a peerAddress.
m a -> PeerSharingClient peerAddress m a
SendMsgDone ([peer] -> m [peer]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [peer]
acc)
    go [peer]
acc (PeerSharingAmount
h:[PeerSharingAmount]
t) = PeerSharingAmount
-> ([peer] -> m (PeerSharingClient peer m [peer]))
-> PeerSharingClient peer m [peer]
forall peerAddress (m :: * -> *) a.
PeerSharingAmount
-> ([peerAddress] -> m (PeerSharingClient peerAddress m a))
-> PeerSharingClient peerAddress m a
SendMsgShareRequest PeerSharingAmount
h (\[peer]
r -> PeerSharingClient peer m [peer]
-> m (PeerSharingClient peer m [peer])
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([peer] -> [PeerSharingAmount] -> PeerSharingClient peer m [peer]
go ([peer]
r [peer] -> [peer] -> [peer]
forall a. [a] -> [a] -> [a]
++ [peer]
acc) [PeerSharingAmount]
t))


-- | A server which counts number received of 'MsgPeerShareRequest'.
--
peerSharingServerReplicate :: forall m . Monad m
                           => Fun Word8 Int
                           -> PeerSharingServer Int m
peerSharingServerReplicate :: forall (m :: * -> *).
Monad m =>
Fun Word8 Int -> PeerSharingServer Int m
peerSharingServerReplicate Fun Word8 Int
f = Int -> PeerSharingServer Int m
go Int
0
  where
    go :: Int -> PeerSharingServer Int m
    go :: Int -> PeerSharingServer Int m
go Int
n =
      PeerSharingServer
        { recvMsgShareRequest :: PeerSharingAmount -> m ([Int], PeerSharingServer Int m)
recvMsgShareRequest = \ (PeerSharingAmount Word8
amount) -> do
            let r :: [Int]
r = Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate (Fun Word8 Int -> Word8 -> Int
forall a b. Fun a b -> a -> b
applyFun Fun Word8 Int
f Word8
amount) Int
n
            ([Int], PeerSharingServer Int m)
-> m ([Int], PeerSharingServer Int m)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Int]
r, Int -> PeerSharingServer Int m
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1))
        }