{-# LANGUAGE ScopedTypeVariables #-} module Network.ADB.Transport where import Control.Exception import Control.Monad.Error import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as C import Data.Monoid import Network.Socket.ByteString import System.IO.Error (IOError(..)) import Prelude hiding (read) -- | \'m\' is the monad to to run it in, \'h\' is the heuristic value which, where -- \'e\' is 'ByteString', is the number of bytes to read. \'e\' is the stream -- element type. data Transport m = Transport { write :: ByteString -> m (), -- ^ Write an item. read :: Int -> m ByteString, -- ^ Read an item with 'h' being the heuristic to say what it -- is we want to read. close :: m () } data TransportError = ADBFailure String | SocketFailure IOError | ConnectionFailure ByteString | ClosedByPeer | IllegalData deriving Show instance Error TransportError where noMsg = IllegalData strMsg _ = IllegalData -- | Block until the specified number of bytes has been read. readFully :: Monad m => Transport m -> Int -> m ByteString readFully rem n = doRecv C.empty where doRecv sofar | C.length sofar == n = return sofar doRecv sofar = do blk <- read rem (n - C.length sofar) doRecv (sofar `mappend` blk)