module File.Binary.Instances () where
import Prelude hiding (take, drop, span)
import File.Binary.Classes (Field(..), Binary(..))
import Data.Word (Word8)
import Data.ByteString.Lazy
(ByteString, take, drop, toChunks, fromChunks, pack, unpack, uncons, span)
import qualified Data.ByteString.Lazy.Char8 as BSLC (pack, unpack)
import qualified Data.ByteString as BS (ByteString, take, drop, concat, uncons, span)
import qualified Data.ByteString.Char8 ()
import Control.Monad (foldM)
import "monads-tf" Control.Monad.State (StateT(..))
import Control.Applicative ((<$>))
import Control.Arrow (first, (&&&))
import Data.Monoid (mempty)
import Data.Char
import Data.Maybe
instance Field ByteString where
type FieldArgument ByteString = Int
fromBinary a = return . getBytes a
toBinary _ = return . makeBinary
instance Field BS.ByteString where
type FieldArgument BS.ByteString = Int
fromBinary n = return . first (BS.concat . toChunks) . getBytes n
toBinary _ = return . makeBinary . fromChunks . (: [])
instance Field Char where
type FieldArgument Char = ()
fromBinary _ = return . first (head . BSLC.unpack) . getBytes 1
toBinary _ = return . makeBinary . BSLC.pack . (: [])
instance Field Word8 where
type FieldArgument Word8 = ()
fromBinary _ = return . first (head . unpack) . getBytes 1
toBinary _ = return . makeBinary . pack . (: [])
instance Field r => Field [r] where
type FieldArgument [r] = [FieldArgument r]
fromBits as = smap mempty as fromBits
consToBits as fs ret = foldM (flip $ uncurry consToBits) ret $ reverse $ zip as fs
myMapM :: (Monad m, Functor m) => (a -> m (Maybe b)) -> [a] -> m [b]
myMapM _ [] = return []
myMapM f (x : xs) = do
ret <- f x
case ret of
Just y -> (y :) <$> myMapM f xs
Nothing -> return []
smap :: (Monad m, Functor m, Eq s) =>
s -> [a] -> (a -> s -> m (ret, s)) -> s -> m ([ret], s)
smap e xs f = runStateT $ myMapM (StateT . f') xs
where
f' x s | s == e = return (Nothing, s)
| otherwise = first Just <$> f x s
instance Binary String where
getBytes n = first BSLC.pack . splitAt n
unconsByte = fromIntegral . ord . head &&& tail
makeBinary = BSLC.unpack
instance Binary ByteString where
getBytes n = take (fromIntegral n) &&& drop (fromIntegral n)
spanBytes = span
unconsByte = fromMaybe (0, "") . uncons
makeBinary = id
instance Binary BS.ByteString where
getBytes n = fromChunks . (: []) . BS.take n &&& BS.drop n
spanBytes p = first (fromChunks . (: [])) . BS.span p
unconsByte = fromMaybe (0, "") . BS.uncons
makeBinary = BS.concat . toChunks