{-# LANGUAGE DeriveFunctor              #-}
{-# LANGUAGE DerivingStrategies         #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE RoleAnnotations            #-}
{-# OPTIONS_HADDOCK not-home #-}

module Database.LSMTree.Internal.Unsliced (
    -- * Unsliced raw bytes
    Unsliced
    -- * Unsliced keys
  , makeUnslicedKey
  , unsafeMakeUnslicedKey
  , fromUnslicedKey
  ) where

import           Control.DeepSeq (NFData)
import           Control.Exception (assert)
import           Data.ByteString.Short (ShortByteString (SBS))
import           Data.Primitive.ByteArray
import qualified Data.Vector.Primitive as VP
import           Database.LSMTree.Internal.RawBytes (RawBytes (..))
import qualified Database.LSMTree.Internal.RawBytes as RB
import           Database.LSMTree.Internal.Serialise (SerialisedKey (..))
import           Database.LSMTree.Internal.Vector (mkPrimVector,
                     noRetainedExtraMemory)

-- | Unsliced string of bytes
type role Unsliced nominal
newtype Unsliced a = Unsliced ByteArray
  deriving newtype Unsliced a -> ()
(Unsliced a -> ()) -> NFData (Unsliced a)
forall a. (a -> ()) -> NFData a
forall k (a :: k). Unsliced a -> ()
$crnf :: forall k (a :: k). Unsliced a -> ()
rnf :: Unsliced a -> ()
NFData

getByteArray :: RawBytes -> ByteArray
getByteArray :: RawBytes -> ByteArray
getByteArray (RawBytes (VP.Vector Int
_ Int
_ ByteArray
ba)) = ByteArray
ba

precondition :: RawBytes -> Bool
precondition :: RawBytes -> Bool
precondition (RawBytes Vector Word8
pvec) = Vector Word8 -> Bool
forall a. Prim a => Vector a -> Bool
noRetainedExtraMemory Vector Word8
pvec

makeUnsliced :: RawBytes -> Unsliced RawBytes
makeUnsliced :: RawBytes -> Unsliced RawBytes
makeUnsliced RawBytes
bytes
    | RawBytes -> Bool
precondition RawBytes
bytes = ByteArray -> Unsliced RawBytes
forall {k} (a :: k). ByteArray -> Unsliced a
Unsliced (RawBytes -> ByteArray
getByteArray RawBytes
bytes)
    | Bool
otherwise     = ByteArray -> Unsliced RawBytes
forall {k} (a :: k). ByteArray -> Unsliced a
Unsliced (RawBytes -> ByteArray
getByteArray (RawBytes -> ByteArray) -> RawBytes -> ByteArray
forall a b. (a -> b) -> a -> b
$ RawBytes -> RawBytes
RB.copy RawBytes
bytes)

unsafeMakeUnsliced :: RawBytes -> Unsliced RawBytes
unsafeMakeUnsliced :: RawBytes -> Unsliced RawBytes
unsafeMakeUnsliced RawBytes
bytes = Bool -> Unsliced RawBytes -> Unsliced RawBytes
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (RawBytes -> Bool
precondition RawBytes
bytes) (ByteArray -> Unsliced RawBytes
forall {k} (a :: k). ByteArray -> Unsliced a
Unsliced (RawBytes -> ByteArray
getByteArray RawBytes
bytes))

fromUnsliced :: Unsliced RawBytes -> RawBytes
fromUnsliced :: Unsliced RawBytes -> RawBytes
fromUnsliced (Unsliced ByteArray
ba) = Vector Word8 -> RawBytes
RawBytes (Int -> Int -> ByteArray -> Vector Word8
forall a. Prim a => Int -> Int -> ByteArray -> Vector a
mkPrimVector Int
0 (ByteArray -> Int
sizeofByteArray ByteArray
ba) ByteArray
ba)

{-------------------------------------------------------------------------------
  Unsliced keys
-------------------------------------------------------------------------------}

from :: Unsliced RawBytes -> Unsliced SerialisedKey
from :: Unsliced RawBytes -> Unsliced SerialisedKey
from (Unsliced ByteArray
ba) = ByteArray -> Unsliced SerialisedKey
forall {k} (a :: k). ByteArray -> Unsliced a
Unsliced ByteArray
ba

to :: Unsliced SerialisedKey -> Unsliced RawBytes
to :: Unsliced SerialisedKey -> Unsliced RawBytes
to (Unsliced ByteArray
ba) = ByteArray -> Unsliced RawBytes
forall {k} (a :: k). ByteArray -> Unsliced a
Unsliced ByteArray
ba

makeUnslicedKey :: SerialisedKey -> Unsliced SerialisedKey
makeUnslicedKey :: SerialisedKey -> Unsliced SerialisedKey
makeUnslicedKey (SerialisedKey RawBytes
rb) = Unsliced RawBytes -> Unsliced SerialisedKey
from (RawBytes -> Unsliced RawBytes
makeUnsliced RawBytes
rb)

unsafeMakeUnslicedKey :: SerialisedKey -> Unsliced SerialisedKey
unsafeMakeUnslicedKey :: SerialisedKey -> Unsliced SerialisedKey
unsafeMakeUnslicedKey (SerialisedKey RawBytes
rb) = Unsliced RawBytes -> Unsliced SerialisedKey
from (RawBytes -> Unsliced RawBytes
unsafeMakeUnsliced RawBytes
rb)

fromUnslicedKey :: Unsliced SerialisedKey -> SerialisedKey
fromUnslicedKey :: Unsliced SerialisedKey -> SerialisedKey
fromUnslicedKey Unsliced SerialisedKey
x = RawBytes -> SerialisedKey
SerialisedKey (Unsliced RawBytes -> RawBytes
fromUnsliced (Unsliced SerialisedKey -> Unsliced RawBytes
to Unsliced SerialisedKey
x))

instance Show (Unsliced SerialisedKey) where
  show :: Unsliced SerialisedKey -> String
show Unsliced SerialisedKey
x = SerialisedKey -> String
forall a. Show a => a -> String
show (Unsliced SerialisedKey -> SerialisedKey
fromUnslicedKey Unsliced SerialisedKey
x)

instance Eq (Unsliced SerialisedKey) where
  Unsliced ByteArray
ba1 == :: Unsliced SerialisedKey -> Unsliced SerialisedKey -> Bool
== Unsliced ByteArray
ba2 = ByteArray# -> ShortByteString
SBS ByteArray#
ba1' ShortByteString -> ShortByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteArray# -> ShortByteString
SBS ByteArray#
ba2'
    where
      !(ByteArray ByteArray#
ba1') = ByteArray
ba1
      !(ByteArray ByteArray#
ba2') = ByteArray
ba2

instance Ord (Unsliced SerialisedKey) where
  compare :: Unsliced SerialisedKey -> Unsliced SerialisedKey -> Ordering
compare (Unsliced ByteArray
ba1) (Unsliced ByteArray
ba2) = ShortByteString -> ShortByteString -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (ByteArray# -> ShortByteString
SBS ByteArray#
ba1') (ByteArray# -> ShortByteString
SBS ByteArray#
ba2')
    where
      !(ByteArray ByteArray#
ba1') = ByteArray
ba1
      !(ByteArray ByteArray#
ba2') = ByteArray
ba2