module Data.Vhd.Types where
import Control.Exception
import qualified Data.ByteString as B
import qualified Data.Text as T
import Data.Vhd.Const
import Data.Text.Encoding
import Data.Word
class Sized a where
sized :: Num n => a -> n
newtype BlockSize = BlockSize Word32
deriving (Show,Eq,Ord,Num)
newtype BlockByteAddress = BlockByteAddress Word32
deriving (Show,Eq,Ord,Num)
newtype BlockSectorAddress = BlockSectorAddress Word32
deriving (Show,Eq,Ord,Num,Enum)
newtype VirtualBlockAddress = VirtualBlockAddress Word32
deriving (Show,Eq,Ord,Num,Enum)
newtype VirtualByteAddress = VirtualByteAddress Word64
deriving (Show,Eq,Ord,Num,Enum)
type DiskGeometryCylinders = Word16
type DiskGeometryHeads = Word8
type DiskGeometrySectorsPerTrack = Word8
type PhysicalByteAddress = Word64
type PhysicalByteCount = Word64
type PhysicalSectorAddress = Word32
type PhysicalSectorCount = Word32
type VirtualBlockCount = Word32
type VirtualByteCount = Word64
type VirtualSectorAddress = Word32
type VirtualSectorCount = Word32
vaddrPlus :: VirtualByteAddress -> Word64 -> VirtualByteAddress
vaddrPlus (VirtualByteAddress b) w = VirtualByteAddress (b + w)
vaddrToBlock :: VirtualByteAddress -> BlockSize -> (VirtualBlockAddress, BlockByteAddress, Word32)
vaddrToBlock (VirtualByteAddress b) (BlockSize blocksz) =
(VirtualBlockAddress $ fromIntegral d, fromIntegral m, blocksz fromIntegral m)
where (d,m) = b `divMod` fromIntegral blocksz
vaddrNextBlock :: VirtualByteAddress -> BlockSize -> VirtualByteAddress
vaddrNextBlock (VirtualByteAddress b) (BlockSize blocksz) =
VirtualByteAddress (((b `div` sz) * sz) + sz)
where sz = fromIntegral blocksz
addrToSector :: Word64 -> PhysicalSectorAddress
addrToSector w = fromIntegral (w `div` sectorLength)
data Version = Version VersionMajor VersionMinor deriving (Show, Eq)
type VersionMajor = Word16
type VersionMinor = Word16
data CreatorHostOs
= CreatorHostOsUnknown
| CreatorHostOsWindows
| CreatorHostOsMacintosh deriving (Show, Eq)
data DiskGeometry = DiskGeometry
DiskGeometryCylinders
DiskGeometryHeads
DiskGeometrySectorsPerTrack deriving (Show, Eq)
data DiskType
= DiskTypeFixed
| DiskTypeDynamic
| DiskTypeDifferencing deriving (Show, Eq)
newtype Cookie = Cookie B.ByteString deriving (Show, Eq)
newtype CreatorApplication = CreatorApplication B.ByteString deriving (Show, Eq)
data ParentLocatorEntry = ParentLocatorEntry
{ locatorCode :: Word32
, locatorDataSpace :: Word32
, locatorDataLength :: Word32
, locatorDataOffset :: Word64
} deriving (Show, Eq)
nullParentLocatorEntry :: ParentLocatorEntry
nullParentLocatorEntry = ParentLocatorEntry 0 0 0 0
newtype ParentUnicodeName = ParentUnicodeName String deriving (Show, Eq)
newtype ParentLocatorEntries = ParentLocatorEntries [ParentLocatorEntry] deriving (Show, Eq)
cookie :: B.ByteString -> Cookie
cookie c = assert (B.length c == 8) $ Cookie c
creatorApplication :: B.ByteString -> CreatorApplication
creatorApplication a = assert (B.length a == 4) $ CreatorApplication a
parentLocatorEntries :: [ParentLocatorEntry] -> ParentLocatorEntries
parentLocatorEntries e = assert ( length e == 8) $ ParentLocatorEntries e
parentUnicodeName :: [Char] -> ParentUnicodeName
parentUnicodeName n
| encodedLength > 512 = error "parent unicode name length must be <= 512 bytes"
| otherwise = ParentUnicodeName n
where
encodedLength = B.length $ encodeUtf16BE $ T.pack n