    {-# LANGUAGE CPP #-}
    -- |
    -- Module      : Network.Socket.ByteString.Lazy
    -- Copyright   : (c) Bryan O'Sullivan 2009
    -- License     : BSD-style
    --
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : POSIX, GHC
    --
    -- This module provides access to the BSD /socket/ interface.  This
    -- module is generally more efficient than the 'String' based network
    -- functions in 'Network.Socket'.  For detailed documentation, consult
    -- your favorite POSIX socket reference. All functions communicate
    -- failures by converting the error number to 'System.IO.IOError'.
    --
    -- This module is made to be imported with 'Network.Socket' like so:
    --
    -- > import Network.Socket
    -- > import Network.Socket.ByteString.Lazy
    -- > import Prelude hiding (getContents)
    --
    module Network.Socket.ByteString.Lazy (
        -- * Send data to a socket
        send
      , sendAll
        -- * Receive data from a socket
      , getContents
      , recv
      ) where

    import           Data.ByteString.Lazy.Internal (ByteString(..), defaultChunkSize)
    import           Network.Socket                (ShutdownCmd (..), shutdown)
    import           Prelude                       hiding (getContents)
    import           System.IO.Unsafe              (unsafeInterleaveIO)
    import           System.IO.Error               (catchIOError)

    #if defined(mingw32_HOST_OS)
    import Network.Socket.ByteString.Lazy.Windows  (send, sendAll)
    #else
    import Network.Socket.ByteString.Lazy.Posix    (send, sendAll)
    #endif

    import qualified Data.ByteString               as S
    import qualified Network.Socket.ByteString     as N
    import           Network.Socket.Imports
    import           Network.Socket.Types

    -- -----------------------------------------------------------------------------
    -- Receiving
    -- | Receive data from the socket.  The socket must be in a connected
    -- state.  Data is received on demand, in chunks; each chunk will be
    -- sized to reflect the amount of data received by individual 'recv'
    -- calls.
    --
    -- All remaining data from the socket is consumed.  When there is no
    -- more data to be received, the receiving side of the socket is shut
    -- down.  If there is an error and an exception is thrown, the socket
    -- is not shut down.
    getContents
        :: Socket -- ^ Connected socket
        -> IO ByteString -- ^ Data received
    getContents :: Socket -> IO ByteString
    getContents s :: Socket
    s = IO ByteString
    loop
      where
        loop :: IO ByteString
    loop = IO ByteString -> IO ByteString
    forall a. IO a -> IO a
    unsafeInterleaveIO (IO ByteString -> IO ByteString) -> IO ByteString -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ do
            ByteString
    sbs <- Socket -> Int -> IO ByteString
    N.recv Socket
    s Int
    defaultChunkSize
            if ByteString -> Bool
    S.null ByteString
    sbs
                then do
                  Socket -> ShutdownCmd -> IO ()
    shutdown Socket
    s ShutdownCmd
    ShutdownReceive IO () -> (IOError -> IO ()) -> IO ()
    forall a. IO a -> (IOError -> IO a) -> IO a
    `catchIOError` IO () -> IOError -> IO ()
    forall a b. a -> b -> a
    const (() -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())
                  ByteString -> IO ByteString
    forall (m :: * -> *) a. Monad m => a -> m a
    return ByteString
    Empty
                else ByteString -> ByteString -> ByteString
    Chunk ByteString
    sbs (ByteString -> ByteString) -> IO ByteString -> IO ByteString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> IO ByteString
    loop

    -- | Receive data from the socket.  The socket must be in a connected
    -- state.  This function may return fewer bytes than specified.  If
    -- the received data is longer than the specified length, it may be
    -- discarded depending on the type of socket.  This function may block
    -- until a message arrives.
    --
    -- If there is no more data to be received, returns an empty 'ByteString'.
    recv
        :: Socket -- ^ Connected socket
        -> Int64 -- ^ Maximum number of bytes to receive
        -> IO ByteString -- ^ Data received
    recv :: Socket -> Int64 -> IO ByteString
    recv s :: Socket
    s nbytes :: Int64
    nbytes = ByteString -> ByteString
    chunk (ByteString -> ByteString) -> IO ByteString -> IO ByteString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Socket -> Int -> IO ByteString
    N.recv Socket
    s (Int64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int64
    nbytes)
      where
        chunk :: ByteString -> ByteString
    chunk k :: ByteString
    k | ByteString -> Bool
    S.null ByteString
    k  = ByteString
    Empty
                | Bool
    otherwise = ByteString -> ByteString -> ByteString
    Chunk ByteString
    k ByteString
    Empty