-- | Atomic binary formats. module Data.Repa.Convert.Format.Binary ( Format (..) , Word8be (..), Int8be (..) , Word16be (..), Int16be (..) , Word32be (..), Int32be (..) , Word64be (..), Int64be (..) , Float32be (..) , Float64be (..)) where import Data.Repa.Convert.Format.Base import Data.Bits import Data.Int as V import Data.Word as V import qualified Foreign.Storable as S import qualified Foreign.Marshal.Alloc as S import qualified Foreign.Ptr as S import qualified Control.Monad.Primitive as Prim ------------------------------------------------------------------------------------------- Word8be -- | Big-endian 8-bit unsigned word. data Word8be = Word8be deriving (Eq, Show) instance Format Word8be where type Value Word8be = Word8 fieldCount _ = 1 minSize _ = 1 fixedSize _ = Just 1 packedSize _ _ = Just 1 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Word8be where pack Word8be x = Packer $ \buf k -> do S.poke buf (fromIntegral x) k (S.plusPtr buf 1) {-# INLINE pack #-} unpack Word8be = Unpacker $ \start _end _stop _fail eat -> do x <- S.peek start eat (S.plusPtr start 1) (fromIntegral x) {-# INLINE unpack #-} w8 :: Integral a => a -> Word8 w8 = fromIntegral {-# INLINE w8 #-} ------------------------------------------------------------------------------------------- Int8be -- | Big-endian 8-bit signed integer. data Int8be = Int8be deriving (Eq, Show) instance Format Int8be where type Value Int8be = V.Int8 fieldCount _ = 1 minSize _ = 1 fixedSize _ = Just 1 packedSize _ _ = Just 1 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Int8be where pack Int8be x = pack Word8be (w8 x) unpack Int8be = fmap i8 (unpack Word8be) {-# INLINE pack #-} {-# INLINE unpack #-} i8 :: Integral a => a -> Int8 i8 = fromIntegral {-# INLINE i8 #-} ------------------------------------------------------------------------------------------ Word16be -- | Big-endian 32-bit unsigned word. data Word16be = Word16be deriving (Eq, Show) instance Format Word16be where type Value Word16be = V.Word16 fieldCount _ = 1 minSize _ = 2 fixedSize _ = Just 2 packedSize _ _ = Just 2 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Word16be where pack Word16be x = Packer $ \buf k -> do S.poke buf (w8 ((w16 x .&. 0x0ff00) `shiftR` 8)) S.pokeByteOff buf 1 (w8 ((w16 x .&. 0x000ff))) k (S.plusPtr buf 2) {-# INLINE pack #-} unpack Word16be = Unpacker $ \start _end _stop _fail eat -> do x0 :: Word8 <- S.peek start x1 :: Word8 <- S.peekByteOff start 1 eat (S.plusPtr start 2) (w16 ((w16 x0 `shiftL` 8) .|. w16 x1)) {-# INLINE unpack #-} w16 :: Integral a => a -> Word16 w16 = fromIntegral {-# INLINE w16 #-} ------------------------------------------------------------------------------------------- Int16be --- | Big-endian 16-bit signed integer. data Int16be = Int16be deriving (Eq, Show) instance Format Int16be where type Value Int16be = V.Int16 fieldCount _ = 1 minSize _ = 2 fixedSize _ = Just 2 packedSize _ _ = Just 2 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Int16be where pack Int16be x = pack Word16be (w16 x) unpack Int16be = fmap i16 (unpack Word16be) {-# INLINE pack #-} {-# INLINE unpack #-} i16 :: Integral a => a -> Int16 i16 = fromIntegral {-# INLINE i16 #-} ------------------------------------------------------------------------------------------ Word32be -- | Big-endian 32-bit unsigned word. data Word32be = Word32be deriving (Eq, Show) instance Format Word32be where type Value Word32be = V.Word32 fieldCount _ = 1 minSize _ = 4 fixedSize _ = Just 4 packedSize _ _ = Just 4 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Word32be where pack Word32be x = Packer $ \buf k -> do S.poke buf (w8 ((w32 x .&. 0x0ff000000) `shiftR` 24)) S.pokeByteOff buf 1 (w8 ((w32 x .&. 0x000ff0000) `shiftR` 16)) S.pokeByteOff buf 2 (w8 ((w32 x .&. 0x00000ff00) `shiftR` 8)) S.pokeByteOff buf 3 (w8 ((w32 x .&. 0x0000000ff))) k (S.plusPtr buf 4) {-# INLINE pack #-} unpack Word32be = Unpacker $ \start _end _fail _stop eat -> do x0 :: Word8 <- S.peek start x1 :: Word8 <- S.peekByteOff start 1 x2 :: Word8 <- S.peekByteOff start 2 x3 :: Word8 <- S.peekByteOff start 3 eat (S.plusPtr start 4) (w32 ( (w32 x0 `shiftL` 24) .|. (w32 x1 `shiftL` 16) .|. (w32 x2 `shiftL` 8) .|. (w32 x3))) {-# INLINE unpack #-} w32 :: Integral a => a -> Word32 w32 = fromIntegral {-# INLINE w32 #-} ------------------------------------------------------------------------------------------- Int32be -- | Big-endian 32-bit signed integer. data Int32be = Int32be deriving (Eq, Show) instance Format Int32be where type Value Int32be = V.Int32 fieldCount _ = 1 minSize _ = 4 fixedSize _ = Just 4 packedSize _ _ = Just 4 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Int32be where pack Int32be x = pack Word32be (w32 x) unpack Int32be = fmap i32 (unpack Word32be) {-# INLINE pack #-} {-# INLINE unpack #-} i32 :: Integral a => a -> Int32 i32 = fromIntegral {-# INLINE i32 #-} ------------------------------------------------------------------------------------------ Word64be -- | Big-endian 64-bit unsigned word. data Word64be = Word64be deriving (Eq, Show) instance Format Word64be where type Value Word64be = V.Word64 fieldCount _ = 1 minSize _ = 8 fixedSize _ = Just 8 packedSize _ _ = Just 8 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Word64be where pack Word64be x = Packer $ \buf k -> do S.poke buf (w8 ((w64 x .&. 0x0ff00000000000000) `shiftR` 56)) S.pokeByteOff buf 1 (w8 ((w64 x .&. 0x000ff000000000000) `shiftR` 48)) S.pokeByteOff buf 2 (w8 ((w64 x .&. 0x00000ff0000000000) `shiftR` 40)) S.pokeByteOff buf 3 (w8 ((w64 x .&. 0x0000000ff00000000) `shiftR` 32)) S.pokeByteOff buf 4 (w8 ((w64 x .&. 0x000000000ff000000) `shiftR` 24)) S.pokeByteOff buf 5 (w8 ((w64 x .&. 0x00000000000ff0000) `shiftR` 16)) S.pokeByteOff buf 6 (w8 ((w64 x .&. 0x0000000000000ff00) `shiftR` 8)) S.pokeByteOff buf 7 (w8 ((w64 x .&. 0x000000000000000ff) )) k (S.plusPtr buf 8) {-# INLINE pack #-} unpack Word64be = Unpacker $ \start _end _fail _stop eat -> do x0 :: Word8 <- S.peek start x1 :: Word8 <- S.peekByteOff start 1 x2 :: Word8 <- S.peekByteOff start 2 x3 :: Word8 <- S.peekByteOff start 3 x4 :: Word8 <- S.peekByteOff start 4 x5 :: Word8 <- S.peekByteOff start 5 x6 :: Word8 <- S.peekByteOff start 6 x7 :: Word8 <- S.peekByteOff start 7 eat (S.plusPtr start 8) (w64 ( (w64 x0 `shiftL` 56) .|. (w64 x1 `shiftL` 48) .|. (w64 x2 `shiftL` 40) .|. (w64 x3 `shiftL` 32) .|. (w64 x4 `shiftL` 24) .|. (w64 x5 `shiftL` 16) .|. (w64 x6 `shiftL` 8) .|. (w64 x7 ))) {-# INLINE unpack #-} w64 :: Integral a => a -> Word64 w64 = fromIntegral {-# INLINE w64 #-} ------------------------------------------------------------------------------------------- Int64be -- | Big-endian 64-bit signed integer. data Int64be = Int64be deriving (Eq, Show) instance Format Int64be where type Value Int64be = V.Int64 fieldCount _ = 1 minSize _ = 8 fixedSize _ = Just 8 packedSize _ _ = Just 8 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Int64be where pack Int64be x = pack Word64be (w64 x) unpack Int64be = fmap i64 (unpack Word64be) {-# INLINE pack #-} {-# INLINE unpack #-} i64 :: Integral a => a -> Int64 i64 = fromIntegral {-# INLINE i64 #-} ----------------------------------------------------------------------------------------- Float32be -- | Big-endian 32-bit IEEE 754 float. data Float32be = Float32be deriving (Eq, Show) instance Format Float32be where type Value Float32be = Float fieldCount _ = 1 minSize _ = 4 fixedSize _ = Just 4 packedSize _ _ = Just 4 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Float32be where pack Float32be x = pack Word32be (floatToWord32 x) unpack Float32be = fmap word32ToFloat (unpack Word32be) {-# INLINE pack #-} {-# INLINE unpack #-} -- | Bitwise cast of `Float` to `Word32`. -- -- The resulting `Word32` contains the representation of the `Float`, -- rather than it's value. floatToWord32 :: Float -> Word32 floatToWord32 d = Prim.unsafeInlineIO $ S.alloca $ \buf -> do S.poke (S.castPtr buf) d S.peek buf {-# INLINE floatToWord32 #-} -- | Inverse of `doubleToFloat32` word32ToFloat :: Word32 -> Float word32ToFloat w = Prim.unsafeInlineIO $ S.alloca $ \buf -> do S.poke (S.castPtr buf) w S.peek buf {-# INLINE word32ToFloat #-} ----------------------------------------------------------------------------------------- Float64be -- | Big-endian 64-bit IEEE 754 float. data Float64be = Float64be deriving (Eq, Show) instance Format Float64be where type Value Float64be = Double fieldCount _ = 1 minSize _ = 8 fixedSize _ = Just 8 packedSize _ _ = Just 8 {-# INLINE minSize #-} {-# INLINE fieldCount #-} {-# INLINE fixedSize #-} {-# INLINE packedSize #-} instance Packable Float64be where pack Float64be x = pack Word64be (doubleToWord64 x) unpack Float64be = fmap word64ToDouble (unpack Word64be) {-# INLINE pack #-} {-# INLINE unpack #-} -- | Bitwise cast of `Double` to `Word64`. -- -- The resulting `Word64` contains the representation of the `Double`, -- rather than it's value. doubleToWord64 :: Double -> Word64 doubleToWord64 d = Prim.unsafeInlineIO $ S.alloca $ \buf -> do S.poke (S.castPtr buf) d S.peek buf {-# INLINE doubleToWord64 #-} -- | Inverse of `doubleToWord64` word64ToDouble :: Word64 -> Double word64ToDouble w = Prim.unsafeInlineIO $ S.alloca $ \buf -> do S.poke (S.castPtr buf) w S.peek buf {-# INLINE word64ToDouble #-}