packages feed

vhd-0.2.1: Data/Vhd/Batmap.hs

module Data.Vhd.Batmap
    ( BatmapHeader(..)
    , KeyHash(..)
    , batmapSetKeyHash
    , batmapClearKeyHash
    ) where

import Control.Applicative
import qualified Data.ByteString as B
import Data.Serialize
import Data.Word
import Data.Vhd.Serialize
import Data.Vhd.Types
import Data.Vhd.Checksum

data BatmapHeader = BatmapHeader
    { batmapHeaderCookie       :: Cookie
    , batmapHeaderOffset       :: PhysicalByteAddress
    , batmapHeaderSize         :: Word32
    , batmapHeaderVersion      :: Version
    , batmapHeaderChecksum     :: Checksum
    , batmapHeaderMarker       :: Word8
    , batmapHeaderKeyHash      :: KeyHash
    , batmapHeaderReserved     :: B.ByteString
    } deriving (Show, Eq)

newtype KeyHash = KeyHash (Maybe (B.ByteString, B.ByteString))
    deriving (Show,Eq)

instance Serialize BatmapHeader where
    get = BatmapHeader
        <$> getCookie
        <*> getDataOffset
        <*> getWord32be
        <*> getVersion
        <*> get
        <*> getWord8
        <*> get
        <*> getByteString 418
    put b = do
        putCookie     $ batmapHeaderCookie   b
        putDataOffset $ batmapHeaderOffset   b
        putWord32be   $ batmapHeaderSize     b
        putVersion    $ batmapHeaderVersion  b
        put           $ batmapHeaderChecksum b
        putWord8      $ batmapHeaderMarker   b
        put           $ batmapHeaderKeyHash  b
        putByteString $ batmapHeaderReserved b

instance Serialize KeyHash where
    get = do
        c <- getWord8
        if c /= 1
            then return $ KeyHash Nothing
            else do nonce <- getByteString 32
                    hash  <- getByteString 32
                    return $ KeyHash (Just (nonce, hash))
    put (KeyHash Nothing) = putByteString $ B.replicate (32+32+1) 0
    put (KeyHash (Just (nonce, hash))) = do
        putWord8 1
        putByteString nonce
        putByteString hash

instance Sized BatmapHeader where
    sized _ = 512

batmapClearKeyHash :: BatmapHeader -> BatmapHeader
batmapClearKeyHash bhdr = bhdr { batmapHeaderKeyHash = KeyHash Nothing }

batmapSetKeyHash :: B.ByteString -> B.ByteString -> BatmapHeader -> BatmapHeader
batmapSetKeyHash nonce hash bhdr
    | B.length nonce /= 32 || B.length hash /= 32 = error "not valid keyhash"
    | otherwise = bhdr { batmapHeaderKeyHash = KeyHash (Just (nonce, hash)) }