module Control.Pipe.C3 ( -- * Pipes commandSender, commandReceiver ) where import Control.Monad ( forever ) import Control.Monad.Trans.Class ( lift ) import Control.Pipe ( runPipe, await, yield, (<+<) ) import Control.Pipe.Serialize ( serializer, deserializer ) import Control.Pipe.Socket ( Handler ) import Data.Serialize ( Serialize ) -- | Send a single command over the outgoing pipe and wait for a -- response. If the incoming pipe is closed before a response -- arrives, returns @Nothing@. commandSender :: (Serialize a, Serialize b) => a -> Handler (Maybe b) commandSender command reader writer = do runPipe (writer <+< serializer <+< sendCommand) runPipe (receiveResponse <+< (deserializer >> return Nothing) <+< (reader >> return Nothing)) where sendCommand = do yield command receiveResponse = do res <- await return (Just res) -- | Wait for commands on the incoming pipe, handle them, and send the -- reponses over the outgoing pipe. commandReceiver :: (Serialize a, Serialize b) => (a -> IO b) -> Handler () commandReceiver executeCommand reader writer = do runPipe (writer <+< serializer <+< commandExecuter <+< deserializer <+< reader) where commandExecuter = forever $ do comm <- await yield =<< lift (executeCommand comm)