module System.TPFS.Device (Address, Device(..), Interleave(..), BinarySize(..)) where
import Control.Applicative
import Data.Binary
import Data.ByteString.Lazy (ByteString,hGet,hPut)
import qualified Data.ByteString.Lazy as B
import Data.Word
import System.IO
import System.IO.Unsafe (unsafeInterleaveIO)
type Address = Word64
class (Functor m, Applicative m, Monad m, Interleave m) => Device m h where
dGet :: Integral i
=> h
-> Address
-> i
-> m ByteString
dPut :: h
-> Address
-> ByteString
-> m ()
class Monad m => Interleave m where
interleave :: m a -> m a
interleave = id
instance Device IO Handle where
dGet h off len =
do hSeek h AbsoluteSeek (toInteger off)
r <- hGetI h len
if B.length r < fromIntegral len
then return (r `B.append` B.replicate (fromIntegral len B.length r) 0)
else return r
dPut h off s =
do hSeek h AbsoluteSeek (toInteger off)
hPut h s
hGetI :: Integral l => Handle -> l -> IO ByteString
hGetI h l
| l > mbi = B.append <$> hGet h maxBound <*> hGetI h (l mbi)
| otherwise = hGet h (fromEnum l)
where mbi = fromIntegral (maxBound :: Int)
instance Interleave IO where
interleave = unsafeInterleaveIO
class Binary a => BinarySize a where
binarySize :: a -> (Integer, Integer)
instance BinarySize Word8 where binarySize = const (1,1)
instance BinarySize Word16 where binarySize = const (2,2)
instance BinarySize Word32 where binarySize = const (4,4)
instance BinarySize Word64 where binarySize = const (8,8)