packages feed

primdata-0.1.2.2: Data/Flat.hs

{-# language UnboxedTuples, TypeOperators, MagicHash, CPP, RankNTypes, TypeApplications,
             ScopedTypeVariables, AllowAmbiguousTypes #-}

module Data.Flat (
    Flat(..)
  , size
  , toByteOffset
  , fromByteOffset
  , sizeP
  , toByteOffsetP
  , fromByteOffsetP
  ) where

{-|
A class for types which can be naturally represented as uniform-sized pointer-free
values.
-}

import GHC.Exts
import GHC.Int
import GHC.Word
#include "MachDeps.h"

#if SIZEOF_HSWORD == 8
#define WORDSHIFT 3
#elif SIZEOF_HSWORD == 4
#define WORDSHIFT 2
#endif

class Flat a where

  -- | Size of values of type @a@.
  size# :: Proxy# a -> Int#

  -- | Convert an offset in terms of type elements to an offset in terms
  --   of bytes.
  toByteOffset# :: Proxy# a -> Int# -> Int#

  -- | Convert a byte offset to an offset in terms of values of the type.
  fromByteOffset# :: Proxy# a -> Int# -> Int#

  -- | Read a value from the array. The offset is in elements of type
  -- @a@ rather than in bytes.
  indexByteArray# :: ByteArray# -> Int# -> a

  -- | Read a value from the mutable array. The offset is in elements of type
  -- @a@ rather than in bytes.
  readByteArray# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)

  -- | Write a value to the mutable array. The offset is in elements of type
  -- @a@ rather than in bytes.
  writeByteArray# :: MutableByteArray# s -> Int# -> a -> State# s -> State# s

  -- | Read a value from a memory position given by an address and an offset.
  -- The memory block the address refers to must be immutable. The offset is in
  -- elements of type @a@ rather than in bytes.
  indexOffAddr# :: Addr# -> Int# -> a

  -- | Read a value from a memory position given by an address and an offset.
  -- The offset is in elements of type @a@ rather than in bytes.
  readOffAddr# :: Addr# -> Int# -> State# s -> (# State# s, a #)

  -- | Write a value to a memory position given by an address and an offset.
  -- The offset is in elements of type @a@ rather than in bytes.
  writeOffAddr# :: Addr# -> Int# -> a -> State# s -> State# s

  -- | Read a value from an array. The offset is in bytes.
  indexWord8ArrayAs# :: ByteArray# -> Int# -> a

  -- | Read a value from a mutable array. The offset is in bytes.
  readWord8ArrayAs# :: MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)

  -- | Write a value to a bytearray. The offset is in bytes.
  writeWord8ArrayAs# :: MutableByteArray# s -> Int# -> a -> State# s -> State# s

size :: forall a. Flat a => Int
size = I# (size# @a proxy#)
{-# inline size #-}

toByteOffset :: forall a. Flat a => Int -> Int
toByteOffset (I# i) = I# (toByteOffset# @a proxy# i)
{-# inline toByteOffset #-}

fromByteOffset :: forall a. Flat a => Int -> Int
fromByteOffset (I# i) = I# (fromByteOffset# @a proxy# i)
{-# inline fromByteOffset #-}

sizeP :: forall a. Flat a => Proxy# a -> Int
sizeP _ = I# (size# @a proxy#)
{-# inline sizeP #-}

toByteOffsetP :: forall a. Flat a => Proxy# a -> Int -> Int
toByteOffsetP _ (I# i) = I# (toByteOffset# @a proxy# i)
{-# inline toByteOffsetP #-}

fromByteOffsetP :: forall a. Flat a => Proxy# a -> Int -> Int
fromByteOffsetP _ (I# i) = I# (fromByteOffset# @a proxy# i)
{-# inline fromByteOffsetP #-}

#define derivePrim(ty, ctr, sz, tobo, frombo, idx_arr, rd_arr, wr_arr, idx_addr, rd_addr, wr_addr, idx_as, read_as, write_as) \
instance Flat (ty) where {                                 \
  size# _ = sz                                             \
; toByteOffset# _ i = tobo                                 \
; fromByteOffset# _ i = frombo                             \
; indexByteArray# arr i = ctr (idx_arr arr i)              \
; readByteArray#  arr i s = case rd_arr arr i s of         \
                        { (# s1, x #) -> (# s1, ctr x #) } \
; writeByteArray# arr i (ctr x) s = wr_arr arr i x s       \
; indexOffAddr# addr i = ctr (idx_addr addr i)             \
; readOffAddr#  addr i s = case rd_addr addr i s of        \
                        { (# s1, x #) -> (# s1, ctr x #) } \
; writeOffAddr# addr i (ctr x) s = wr_addr addr i x s      \
; indexWord8ArrayAs# arr i  = ctr (idx_as arr i)           \
; readWord8ArrayAs# arr i s = case read_as arr i s of      \
                        { (# s1, x #) -> (# s, ctr x #) }  \
; writeWord8ArrayAs# arr i (ctr x) s = write_as arr i x s  \
; {-# inline size# #-}                                     \
; {-# inline toByteOffset# #-}                             \
; {-# inline fromByteOffset# #-}                           \
; {-# inline indexByteArray# #-}                           \
; {-# inline readByteArray# #-}                            \
; {-# inline writeByteArray# #-}                           \
; {-# inline indexOffAddr# #-}                             \
; {-# inline readOffAddr# #-}                              \
; {-# inline writeOffAddr# #-}                             \
; {-# inline indexWord8ArrayAs# #-}                        \
; {-# inline readWord8ArrayAs# #-}                         \
; {-# inline writeWord8ArrayAs# #-}                        \
}

derivePrim(Int, I#, SIZEOF_HSINT#,
           uncheckedIShiftL# i WORDSHIFT#,
           uncheckedIShiftRA# i WORDSHIFT#,
           indexIntArray#, readIntArray#, writeIntArray#,
           indexIntOffAddr#, readIntOffAddr#, writeIntOffAddr#,
           indexWord8ArrayAsInt#, readWord8ArrayAsInt#, writeWord8ArrayAsInt#)

derivePrim(Word, W#, SIZEOF_HSWORD#,
           uncheckedIShiftL# i WORDSHIFT#,
           uncheckedIShiftRA# i WORDSHIFT#,
           indexWordArray#, readWordArray#, writeWordArray#,
           indexWordOffAddr#, readWordOffAddr#, writeWordOffAddr#,
           indexWord8ArrayAsWord#, readWord8ArrayAsWord#, writeWord8ArrayAsWord#)

derivePrim(Double, D#, SIZEOF_HSDOUBLE#,
           uncheckedIShiftL# i 3#,
           uncheckedIShiftRA# i 3#,
           indexDoubleArray#, readDoubleArray#, writeDoubleArray#,
           indexDoubleOffAddr#, readDoubleOffAddr#, writeDoubleOffAddr#,
           indexWord8ArrayAsDouble#, readWord8ArrayAsDouble#, writeWord8ArrayAsDouble#)

derivePrim(Char, C#, SIZEOF_HSCHAR#,
           uncheckedIShiftL# i 2#,
           uncheckedIShiftRA# i 2#,
           indexWideCharArray#, readWideCharArray#, writeWideCharArray#,
           indexWideCharOffAddr#, readWideCharOffAddr#, writeWideCharOffAddr#,
           indexWord8ArrayAsWideChar#, readWord8ArrayAsWideChar#, writeWord8ArrayAsWideChar#)

derivePrim(Word8, W8#, SIZEOF_WORD8#,
           i,
           i,
           indexWord8Array#, readWord8Array#, writeWord8Array#,
           indexWord8OffAddr#, readWord8OffAddr#, writeWord8OffAddr#,
           indexWord8Array#, readWord8Array#, writeWord8Array#)

derivePrim(Word16, W16#, SIZEOF_WORD16#,
           uncheckedIShiftL# i 1#,
           uncheckedIShiftRA# i 1#,
           indexWord16Array#, readWord16Array#, writeWord16Array#,
           indexWord16OffAddr#, readWord16OffAddr#, writeWord16OffAddr#,
           indexWord8ArrayAsWord16#, readWord8ArrayAsWord16#, writeWord8ArrayAsWord16#)

derivePrim(Word32, W32#, SIZEOF_WORD32#,
           uncheckedIShiftL# i 2#,
           uncheckedIShiftRA# i 2#,
           indexWord32Array#, readWord32Array#, writeWord32Array#,
           indexWord32OffAddr#, readWord32OffAddr#, writeWord32OffAddr#,
           indexWord8ArrayAsWord32#, readWord8ArrayAsWord32#, writeWord8ArrayAsWord32#)

derivePrim(Word64, W64#, SIZEOF_WORD64#,
           uncheckedIShiftL# i 3#,
           uncheckedIShiftRA# i 3#,
           indexWord64Array#, readWord64Array#, writeWord64Array#,
           indexWord64OffAddr#, readWord64OffAddr#, writeWord64OffAddr#,
           indexWord8ArrayAsWord64#, readWord8ArrayAsWord64#, writeWord8ArrayAsWord64#)

derivePrim(Int8, I8#, SIZEOF_INT8#,
           i,
           i,
           indexInt8Array#, readInt8Array#, writeInt8Array#,
           indexInt8OffAddr#, readInt8OffAddr#, writeInt8OffAddr#,
           indexInt8Array#, readInt8Array#, writeInt8Array#)

derivePrim(Int16, I16#, SIZEOF_INT16#,
           uncheckedIShiftL# i 1#,
           uncheckedIShiftRA# i 1#,
           indexInt16Array#, readInt16Array#, writeInt16Array#,
           indexInt16OffAddr#, readInt16OffAddr#, writeInt16OffAddr#,
           indexWord8ArrayAsInt16#, readWord8ArrayAsInt16#, writeWord8ArrayAsInt16#)

derivePrim(Int32, I32#, SIZEOF_INT32#,
           uncheckedIShiftL# i 2#,
           uncheckedIShiftRA# i 2#,
           indexInt32Array#, readInt32Array#, writeInt32Array#,
           indexInt32OffAddr#, readInt32OffAddr#, writeInt32OffAddr#,
           indexWord8ArrayAsInt32#, readWord8ArrayAsInt32#, writeWord8ArrayAsInt32#)

derivePrim(Int64, I64#, SIZEOF_INT64#,
           uncheckedIShiftL# i 3#,
           uncheckedIShiftRA# i 3#,
           indexInt64Array#, readInt64Array#, writeInt64Array#,
           indexInt64OffAddr#, readInt64OffAddr#, writeInt64OffAddr#,
           indexWord8ArrayAsInt64#, readWord8ArrayAsInt64#, writeWord8ArrayAsInt64#)

derivePrim((Ptr a), Ptr, SIZEOF_HSPTR#,
           uncheckedIShiftL# i WORDSHIFT#,
           uncheckedIShiftRA# i WORDSHIFT#,
           indexAddrArray#, readAddrArray#, writeAddrArray#,
           indexAddrOffAddr#, readAddrOffAddr#, writeAddrOffAddr#,
           indexWord8ArrayAsAddr#, readWord8ArrayAsAddr#, writeWord8ArrayAsAddr#)