adb-0.1.0.0: Network/ADB/Transport.hs
{-# 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)