packages feed

lsm-tree-1.0.0.0: src-extras/Database/LSMTree/Extras/Orphans.hs

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DerivingVia    #-}
{-# LANGUAGE TypeFamilies   #-}

{-# OPTIONS_GHC -Wno-orphans #-}

module Database.LSMTree.Extras.Orphans (
    byteSwapWord256
  , indexWord8ArrayAsWord256
  , indexWord8ArrayAsWord128
  ) where

import           Control.DeepSeq
import qualified Data.Primitive as P
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import           Data.WideWord.Word128 (Word128 (..), byteSwapWord128)
import           Data.WideWord.Word256 (Word256 (..))
import           Database.LSMTree.Internal.Primitive (indexWord8ArrayAsWord64)
import qualified Database.LSMTree.Internal.RawBytes as RB
import           Database.LSMTree.Internal.Serialise (SerialisedBlob (..),
                     SerialisedKey (..), SerialisedValue (..))
import           Database.LSMTree.Internal.Serialise.Class
import           Database.LSMTree.Internal.Vector
import           GHC.Generics
import           GHC.Word
import qualified System.FS.API as FS
import qualified System.FS.IO.Handle as FS
import           System.Posix.Types (COff (..))
import           System.Random (Uniform)
import           Test.QuickCheck

{-------------------------------------------------------------------------------
  Word256
-------------------------------------------------------------------------------}

deriving anyclass instance Uniform Word256

instance SerialiseKey Word256 where
  serialiseKey w256 =
    RB.RawBytes $ mkPrimVector 0 32 $ P.runByteArray $ do
      ba <- P.newByteArray 32
      P.writeByteArray ba 0 $ byteSwapWord256 w256
      pure ba
  deserialiseKey (RawBytes (VP.Vector off len ba)) =
    requireBytesExactly "Word256" 32 len $
      byteSwapWord256 $ indexWord8ArrayAsWord256 ba off

instance SerialiseKeyOrderPreserving Word256

instance SerialiseValue Word256 where
  serialiseValue w256 =
    RB.RawBytes $ mkPrimVector 0 32 $ P.runByteArray $ do
      ba <- P.newByteArray 32
      P.writeByteArray ba 0 w256
      pure ba
  deserialiseValue (RawBytes (VP.Vector off len ba)) =
    requireBytesExactly "Word256" 32 len $
      indexWord8ArrayAsWord256 ba off

instance Arbitrary Word256 where
  arbitrary = Word256 <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
  shrink w256 = [ w256'
                | let i256 = toInteger w256
                , i256' <- shrink i256
                , toInteger (minBound :: Word256) <= i256'
                , toInteger (maxBound :: Word256) >= i256'
                , let w256' = fromIntegral i256'
                ]

{-# INLINE byteSwapWord256 #-}
byteSwapWord256 :: Word256 -> Word256
byteSwapWord256 (Word256 a3 a2 a1 a0) =
    Word256 (byteSwap64 a0) (byteSwap64 a1) (byteSwap64 a2) (byteSwap64 a3)

{-# INLINE indexWord8ArrayAsWord256 #-}
indexWord8ArrayAsWord256 :: P.ByteArray -> Int -> Word256
indexWord8ArrayAsWord256 !ba !off =
    Word256 (indexWord8ArrayAsWord64 ba (off + 24))
            (indexWord8ArrayAsWord64 ba (off + 16))
            (indexWord8ArrayAsWord64 ba (off + 8))
            (indexWord8ArrayAsWord64 ba off)

newtype instance VUM.MVector s Word256 = MV_Word256 (VP.MVector s Word256)
newtype instance VU.Vector     Word256 = V_Word256  (VP.Vector    Word256)

deriving via VU.UnboxViaPrim Word256 instance VGM.MVector VU.MVector Word256
deriving via VU.UnboxViaPrim Word256 instance VG.Vector   VU.Vector  Word256

instance VUM.Unbox Word256

{-------------------------------------------------------------------------------
  Word128
-------------------------------------------------------------------------------}

deriving anyclass instance Uniform Word128

instance SerialiseKey Word128 where
  serialiseKey w128 =
    RB.RawBytes $ mkPrimVector 0 16 $ P.runByteArray $ do
      ba <- P.newByteArray 16
      P.writeByteArray ba 0 $ byteSwapWord128 w128
      pure ba
  deserialiseKey (RawBytes (VP.Vector off len ba)) =
    requireBytesExactly "Word128" 16 len $
      byteSwapWord128 $ indexWord8ArrayAsWord128 ba off

instance SerialiseKeyOrderPreserving Word128

instance SerialiseValue Word128 where
  serialiseValue w128 =
    RB.RawBytes $ mkPrimVector 0 16 $ P.runByteArray $ do
      ba <- P.newByteArray 16
      P.writeByteArray ba 0 w128
      pure ba
  deserialiseValue (RawBytes (VP.Vector off len ba)) =
    requireBytesExactly "Word128" 16 len $
      indexWord8ArrayAsWord128 ba off

instance Arbitrary Word128 where
  arbitrary = Word128 <$> arbitrary <*> arbitrary
  shrink w128 = [ w128'
                | let i128 = toInteger w128
                , i128' <- shrink i128
                , toInteger (minBound :: Word128) <= i128'
                , toInteger (maxBound :: Word128) >= i128'
                , let w128' = fromIntegral i128'
                ]

{-# INLINE indexWord8ArrayAsWord128 #-}
indexWord8ArrayAsWord128 :: P.ByteArray -> Int -> Word128
indexWord8ArrayAsWord128 !ba !off =
    Word128 (indexWord8ArrayAsWord64 ba (off + 8))
            (indexWord8ArrayAsWord64 ba off)

newtype instance VUM.MVector s Word128 = MV_Word128 (VP.MVector s Word128)
newtype instance VU.Vector     Word128 = V_Word128  (VP.Vector    Word128)

deriving via VU.UnboxViaPrim Word128 instance VGM.MVector VU.MVector Word128
deriving via VU.UnboxViaPrim Word128 instance VG.Vector   VU.Vector  Word128

instance VUM.Unbox Word128

{-------------------------------------------------------------------------------
  NFData
-------------------------------------------------------------------------------}

deriving stock instance Generic (FS.HandleOS h)
deriving anyclass instance NFData (FS.HandleOS h)
deriving newtype instance NFData FS.BufferOffset
deriving newtype instance NFData COff

{-------------------------------------------------------------------------------
  RawBytes
-------------------------------------------------------------------------------}

instance SerialiseKey RawBytes where
  serialiseKey = id
  deserialiseKey = id

instance SerialiseValue RawBytes where
  serialiseValue = id
  deserialiseValue = id

{-------------------------------------------------------------------------------
  SerialisedKey/Value/Blob
-------------------------------------------------------------------------------}

deriving newtype instance SerialiseKey SerialisedKey

deriving newtype instance SerialiseValue SerialisedValue

deriving newtype instance SerialiseValue SerialisedBlob