module Data.Accessor.BinaryRead where
import qualified Data.Accessor.Basic as Accessor
import qualified Control.Monad.Trans.State as State
import Control.Monad.Trans.State (StateT, )
import Control.Monad.Trans.Class (lift, )
import Control.Monad (liftM, )
import Data.Word (Word8, )
import Data.Char (chr, )
import Prelude hiding (any)
type Stream = [Word8]
class C a where
any :: ByteSource source => source a
class Monad source => ByteSource source where
readWord8 :: source Word8
class ByteStream s where
getWord8 :: Monad m => s -> m (Word8, s)
instance ByteCompatible byte => ByteStream [byte] where
getWord8 xs =
case xs of
(c:cs) -> return (toByte c, cs)
_ -> fail "ByteStream: no more byte available"
class ByteCompatible byte where
toByte :: byte -> Word8
instance ByteCompatible Word8 where
toByte = id
instance (ByteStream s, Monad m) => ByteSource (StateT s m) where
readWord8 =
do xs <- State.get
(c,cs) <- lift (getWord8 xs)
State.put cs
return c
instance C Word8 where
any = readWord8
instance C Char where
any =
liftM (chr . fromIntegral) readWord8
instance C Int where
any =
do c0 <- readWord8
c1 <- readWord8
c2 <- readWord8
c3 <- readWord8
return
(foldl1 (\acc d -> acc*256+d)
(map fromIntegral [c0,c1,c2,c3]))
newtype Parser s r = Parser {runParser :: (r, s) -> Maybe (r, s)}
field :: (ByteStream s, C a) =>
Accessor.T r a -> Parser s r
field f =
Parser $
uncurry (\r -> State.runStateT $
fmap (\x -> Accessor.set f x r) any)
record :: [Parser s r] -> Parser s r
record ps =
Parser $ flip (foldl (>>=)) (map runParser ps) . Just