{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP          #-}
{-# LANGUAGE MagicHash    #-}
{-# OPTIONS_HADDOCK not-home #-}

-- | Primitive operations lifted into boxed types
module Database.LSMTree.Internal.Primitive (
    -- * Byte swaps
    byteSwapInt16
  , byteSwapInt32
  , byteSwapInt64
  , byteSwapInt
  , byteSwapWord16
  , byteSwapWord32
  , byteSwapWord64
  , byteSwapWord
    -- * Indexing byte arrays
  , indexInt8Array
  , indexWord8ArrayAsInt16
  , indexWord8ArrayAsInt32
  , indexWord8ArrayAsInt64
  , indexWord8ArrayAsInt
  , indexWord8Array
  , indexWord8ArrayAsWord16
  , indexWord8ArrayAsWord32
  , indexWord8ArrayAsWord64
  , indexWord8ArrayAsWord
  ) where

import           Data.Primitive.ByteArray (ByteArray (..))
import           GHC.Exts
import           GHC.Int
import           GHC.Word

{-------------------------------------------------------------------------------
  Conversions
-------------------------------------------------------------------------------}

{-# INLINE wordToInt16# #-}
wordToInt16# :: Word# -> Int16#
wordToInt16# :: Word# -> Int16#
wordToInt16# Word#
w# = Int# -> Int16#
intToInt16# (Word# -> Int#
word2Int# Word#
w#)

{-# INLINE int16ToWord# #-}
int16ToWord# :: Int16# -> Word#
int16ToWord# :: Int16# -> Word#
int16ToWord# Int16#
i# = Int# -> Word#
int2Word# (Int16# -> Int#
int16ToInt# Int16#
i#)

{-# INLINE wordToInt32# #-}
wordToInt32# :: Word# -> Int32#
wordToInt32# :: Word# -> Int32#
wordToInt32# Word#
w# = Int# -> Int32#
intToInt32# (Word# -> Int#
word2Int# Word#
w#)

{-# INLINE int32ToWord# #-}
int32ToWord# :: Int32# -> Word#
int32ToWord# :: Int32# -> Word#
int32ToWord# Int32#
i# = Int# -> Word#
int2Word# (Int32# -> Int#
int32ToInt# Int32#
i#)

#if MIN_VERSION_base(4,17,0)

{-# INLINE wordToInt64# #-}
wordToInt64# :: Word# -> Int64#
wordToInt64# :: Word# -> Int64#
wordToInt64# Word#
w# = Int# -> Int64#
intToInt64# (Word# -> Int#
word2Int# Word#
w#)

{-# INLINE int64ToWord# #-}
int64ToWord# :: Int64# -> Word#
int64ToWord# :: Int64# -> Word#
int64ToWord# Int64#
i# = Int# -> Word#
int2Word# (Int64# -> Int#
int64ToInt# Int64#
i#)

#endif

{-------------------------------------------------------------------------------
  Conversions: shims
-------------------------------------------------------------------------------}

{-# INLINE wordToInt64Shim# #-}
{-# INLINE int64ToWordShim# #-}

#if MIN_VERSION_base(4,17,0)

wordToInt64Shim# :: Word# -> Int64#
wordToInt64Shim# :: Word# -> Int64#
wordToInt64Shim# = Word# -> Int64#
wordToInt64#

int64ToWordShim# :: Int64# -> Word#
int64ToWordShim# :: Int64# -> Word#
int64ToWordShim# = Int64# -> Word#
int64ToWord#

#else

wordToInt64Shim# :: Word# -> Int#
wordToInt64Shim# = word2Int#

int64ToWordShim# :: Int# -> Word#
int64ToWordShim# = int2Word#

#endif

{-------------------------------------------------------------------------------
  Byte swaps
-------------------------------------------------------------------------------}

{-# INLINE byteSwapInt16 #-}
byteSwapInt16 :: Int16 -> Int16
byteSwapInt16 :: Int16 -> Int16
byteSwapInt16 (I16# Int16#
i#) = Int16# -> Int16
I16# (Word# -> Int16#
wordToInt16# (Word# -> Word#
byteSwap16# (Int16# -> Word#
int16ToWord# Int16#
i#)))

{-# INLINE byteSwapInt32 #-}
byteSwapInt32 :: Int32 -> Int32
byteSwapInt32 :: Int32 -> Int32
byteSwapInt32 (I32# Int32#
i#) = Int32# -> Int32
I32# (Word# -> Int32#
wordToInt32# (Word# -> Word#
byteSwap32# (Int32# -> Word#
int32ToWord# Int32#
i#)))

{-# INLINE byteSwapInt64 #-}
byteSwapInt64 :: Int64 -> Int64
byteSwapInt64 :: Int64 -> Int64
byteSwapInt64 (I64# Int64#
i#) = Int64# -> Int64
I64# (Word# -> Int64#
wordToInt64Shim# (Word# -> Word#
byteSwap# (Int64# -> Word#
int64ToWordShim# Int64#
i#)))

{-# INLINE byteSwapInt #-}
byteSwapInt :: Int -> Int
byteSwapInt :: Int -> Int
byteSwapInt (I# Int#
i#) = Int# -> Int
I# (Word# -> Int#
word2Int# (Word# -> Word#
byteSwap# (Int# -> Word#
int2Word# Int#
i#)))

{-# INLINE byteSwapWord16 #-}
byteSwapWord16 :: Word16 -> Word16
byteSwapWord16 :: Word16 -> Word16
byteSwapWord16 = Word16 -> Word16
byteSwap16

{-# INLINE byteSwapWord32 #-}
byteSwapWord32 :: Word32 -> Word32
byteSwapWord32 :: Word32 -> Word32
byteSwapWord32 = Word32 -> Word32
byteSwap32

{-# INLINE byteSwapWord64 #-}
byteSwapWord64 :: Word64 -> Word64
byteSwapWord64 :: Word64 -> Word64
byteSwapWord64 = Word64 -> Word64
byteSwap64

{-# INLINE byteSwapWord #-}
byteSwapWord :: Word -> Word
byteSwapWord :: Word -> Word
byteSwapWord (W# Word#
w#) = Word# -> Word
W# (Word# -> Word#
byteSwap# Word#
w#)

{-------------------------------------------------------------------------------
  Indexing byte arrays
-------------------------------------------------------------------------------}

{-# INLINE indexInt8Array #-}
indexInt8Array :: ByteArray -> Int -> Int8
indexInt8Array :: ByteArray -> Int -> Int8
indexInt8Array (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Int8# -> Int8
I8# (ByteArray# -> Int# -> Int8#
indexInt8Array# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsInt16 #-}
indexWord8ArrayAsInt16 :: ByteArray -> Int -> Int16
indexWord8ArrayAsInt16 :: ByteArray -> Int -> Int16
indexWord8ArrayAsInt16 (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Int16# -> Int16
I16# (ByteArray# -> Int# -> Int16#
indexWord8ArrayAsInt16# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsInt32 #-}
indexWord8ArrayAsInt32 :: ByteArray -> Int -> Int32
indexWord8ArrayAsInt32 :: ByteArray -> Int -> Int32
indexWord8ArrayAsInt32 (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Int32# -> Int32
I32# (ByteArray# -> Int# -> Int32#
indexWord8ArrayAsInt32# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsInt64 #-}
indexWord8ArrayAsInt64 :: ByteArray -> Int -> Int64
indexWord8ArrayAsInt64 :: ByteArray -> Int -> Int64
indexWord8ArrayAsInt64 (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Int64# -> Int64
I64# (ByteArray# -> Int# -> Int64#
indexWord8ArrayAsInt64# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsInt #-}
indexWord8ArrayAsInt :: ByteArray -> Int -> Int
indexWord8ArrayAsInt :: ByteArray -> Int -> Int
indexWord8ArrayAsInt (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Int# -> Int
I# (ByteArray# -> Int# -> Int#
indexWord8ArrayAsInt# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8Array #-}
indexWord8Array :: ByteArray -> Int -> Word8
indexWord8Array :: ByteArray -> Int -> Word8
indexWord8Array (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Word8# -> Word8
W8# (ByteArray# -> Int# -> Word8#
indexWord8Array# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsWord16 #-}
indexWord8ArrayAsWord16 :: ByteArray -> Int -> Word16
indexWord8ArrayAsWord16 :: ByteArray -> Int -> Word16
indexWord8ArrayAsWord16 (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Word16# -> Word16
W16# (ByteArray# -> Int# -> Word16#
indexWord8ArrayAsWord16# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsWord32 #-}
indexWord8ArrayAsWord32 :: ByteArray -> Int -> Word32
indexWord8ArrayAsWord32 :: ByteArray -> Int -> Word32
indexWord8ArrayAsWord32 (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Word32# -> Word32
W32# (ByteArray# -> Int# -> Word32#
indexWord8ArrayAsWord32# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsWord64 #-}
indexWord8ArrayAsWord64 :: ByteArray -> Int -> Word64
indexWord8ArrayAsWord64 :: ByteArray -> Int -> Word64
indexWord8ArrayAsWord64 (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Word64# -> Word64
W64# (ByteArray# -> Int# -> Word64#
indexWord8ArrayAsWord64# ByteArray#
ba# Int#
off#)

{-# INLINE indexWord8ArrayAsWord #-}
indexWord8ArrayAsWord :: ByteArray -> Int -> Word
indexWord8ArrayAsWord :: ByteArray -> Int -> Word
indexWord8ArrayAsWord (ByteArray !ByteArray#
ba#) (I# !Int#
off#) =
  Word# -> Word
W# (ByteArray# -> Int# -> Word#
indexWord8ArrayAsWord# ByteArray#
ba# Int#
off#)