{-# LANGUAGE ForeignFunctionInterface, DeriveDataTypeable #-}
-- |
-- Module:          Nanomsg.Binary
--
-- This module offers a thin serialization layer ("Binary" based)
-- over @'send'@ and @'receive'@. You just need to import 
-- @Nanomsg.Binary@ instead of @Nanomsg@.

module Nanomsg.Binary
  (
  -- * Types
  -- ** Socket types
    Pair(..)
  , Req(..)
  , Rep(..)
  , Pub(..)
  , Sub(..)
  , Surveyor(..)
  , Respondent(..)
  , Push(..)
  , Pull(..)
  , Bus(..)
  -- ** Other
  , Socket
  , Endpoint
  , NNException
--  , eTERM
--  , eFSM
  , SocketType
  , Sender
  , Receiver
  -- * Operations
  -- ** General operations
  , socket
  , withSocket
  , bind
  , connect
  , send
  , recv
  , recv'
  , subscribe
  , unsubscribe
  , shutdown
  , close
  , term
  -- ** Socket option settings
  , linger
  , setLinger
  , sndBuf
  , setSndBuf
  , rcvBuf
  , setRcvBuf
  , reconnectInterval
  , setReconnectInterval
  , reconnectIntervalMax
  , setReconnectIntervalMax
  , sndPrio
  , setSndPrio
  , ipv4Only
  , setIpv4Only
  , requestResendInterval
  , setRequestResendInterval
  , surveyorDeadline
  , setSurveyorDeadline
  , tcpNoDelay
  , setTcpNoDelay

  ) where

import Control.Applicative
import Nanomsg hiding (send,recv,recv')
import qualified Nanomsg as NM
import Data.Binary
import Data.ByteString.Lazy

send
  :: (Sender s, Binary dat)
  => Socket s
  -> dat
  -> IO ()
send :: forall s dat. (Sender s, Binary dat) => Socket s -> dat -> IO ()
send Socket s
s dat
d = Socket s -> ByteString -> IO ()
forall a. Sender a => Socket a -> ByteString -> IO ()
NM.send Socket s
s (LazyByteString -> ByteString
toStrict (LazyByteString -> ByteString)
-> (dat -> LazyByteString) -> dat -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. dat -> LazyByteString
forall a. Binary a => a -> LazyByteString
encode (dat -> ByteString) -> dat -> ByteString
forall a b. (a -> b) -> a -> b
$ dat
d)

recv
  :: (Receiver s, Binary dat)
  => Socket s
  -> IO dat
recv :: forall s dat. (Receiver s, Binary dat) => Socket s -> IO dat
recv Socket s
s = LazyByteString -> dat
forall a. Binary a => LazyByteString -> a
decode (LazyByteString -> dat)
-> (ByteString -> LazyByteString) -> ByteString -> dat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> LazyByteString
fromStrict (ByteString -> dat) -> IO ByteString -> IO dat
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Socket s -> IO ByteString
forall a. Receiver a => Socket a -> IO ByteString
NM.recv Socket s
s

recv'
  :: (Receiver s, Binary dat)
  => Socket s
  -> IO (Maybe dat)
recv' :: forall s dat.
(Receiver s, Binary dat) =>
Socket s -> IO (Maybe dat)
recv' Socket s
s = (ByteString -> dat) -> Maybe ByteString -> Maybe dat
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LazyByteString -> dat
forall a. Binary a => LazyByteString -> a
decode (LazyByteString -> dat)
-> (ByteString -> LazyByteString) -> ByteString -> dat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> LazyByteString
fromStrict) (Maybe ByteString -> Maybe dat)
-> IO (Maybe ByteString) -> IO (Maybe dat)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Socket s -> IO (Maybe ByteString)
forall a. Receiver a => Socket a -> IO (Maybe ByteString)
NM.recv' Socket s
s