packages feed

lsm-tree-1.0.0.0: test/Test/Database/LSMTree/StateMachine/Op.hs

{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE InstanceSigs          #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- | SumProd Op extended with BlobRef extraction
module Test.Database.LSMTree.StateMachine.Op (
    -- * 'Op'
    Op (..)
  , intOpId
    -- * 'HasBlobRef' class
  , HasBlobRef (..)
  ) where

import           Control.Monad ((<=<))
import           Control.Monad.Identity (Identity (..))
import qualified Data.Vector as V
import qualified Database.LSMTree.Class as Class
import           GHC.Show (appPrec)
import           Test.QuickCheck.StateModel.Lockstep (InterpretOp, Operation)
import qualified Test.QuickCheck.StateModel.Lockstep.Op as Op
import           Test.Util.Orphans ()
import           Test.Util.TypeFamilyWrappers (WrapBlobRef)

{-------------------------------------------------------------------------------
  'Op'
-------------------------------------------------------------------------------}

data Op a b where
  OpId                 :: Op a a
  OpFst                :: Op (a, b) a
  OpSnd                :: Op (b, a) a
  OpLeft               :: Op a (Either a b)
  OpRight              :: Op b (Either a b)
  OpFromLeft           :: Op (Either a b) a
  OpFromRight          :: Op (Either a b) b
  OpComp               :: Op b c -> Op a b -> Op a c
  OpLookupResults      :: Op (V.Vector (Class.LookupResult v (WrapBlobRef h m b))) (V.Vector (WrapBlobRef h m b))
  OpEntrys             :: Op (V.Vector (Class.Entry k v (WrapBlobRef h m b))) (V.Vector (WrapBlobRef h m b))

intOpId :: Op a b -> a -> Maybe b
intOpId OpId            = Just
intOpId OpFst           = Just . fst
intOpId OpSnd           = Just . snd
intOpId OpLeft          = Just . Left
intOpId OpRight         = Just . Right
intOpId OpFromLeft      = either Just (const Nothing)
intOpId OpFromRight     = either (const Nothing) Just
intOpId (OpComp g f)    = intOpId g <=< intOpId f
intOpId OpLookupResults = Just . V.mapMaybe getBlobRef
intOpId OpEntrys        = Just . V.mapMaybe getBlobRef

{-------------------------------------------------------------------------------
  'InterpretOp' instances
-------------------------------------------------------------------------------}

instance Operation Op where
  opIdentity = OpId

instance InterpretOp Op Identity where
  intOp = Op.intOpIdentity intOpId

{-------------------------------------------------------------------------------
  'Show' and 'Eq' instances
-------------------------------------------------------------------------------}

sameOp :: Op a b -> Op c d -> Bool
sameOp = go
  where
    go :: Op a b -> Op c d -> Bool
    go OpId                 OpId            = True
    go OpFst                OpFst           = True
    go OpSnd                OpSnd           = True
    go OpLeft               OpLeft          = True
    go OpRight              OpRight         = True
    go OpFromLeft           OpFromLeft      = True
    go OpFromRight          OpFromRight     = True
    go (OpComp g f)         (OpComp g' f')  = go g g' && go f f'
    go OpLookupResults      OpLookupResults = True
    go OpEntrys             OpEntrys        = True
    go _                    _               = False

    _coveredAllCases :: Op a b -> ()
    _coveredAllCases = \case
        OpId                   -> ()
        OpFst                  -> ()
        OpSnd                  -> ()
        OpLeft                 -> ()
        OpRight                -> ()
        OpFromLeft             -> ()
        OpFromRight            -> ()
        OpComp{}               -> ()
        OpLookupResults{}      -> ()
        OpEntrys{}             -> ()


instance Eq (Op a b)  where
  (==) = sameOp

instance Show (Op a b) where
  showsPrec :: Int -> Op a b -> ShowS
  showsPrec p = \op -> case op of
      OpComp{} -> showParen (p > appPrec) (go op)
      _        -> go op
    where
      go :: Op x y -> String -> String
      go OpId            = showString "OpId"
      go OpFst           = showString "OpFst"
      go OpSnd           = showString "OpSnd"
      go OpLeft          = showString "OpLeft"
      go OpRight         = showString "OpRight"
      go OpFromLeft      = showString "OpFromLeft"
      go OpFromRight     = showString "OpFromRight"
      go (OpComp g f)    = go g . showString " `OpComp` " . go f
      go OpLookupResults = showString "OpLookupResults"
      go OpEntrys        = showString "OpEntrys"

{-------------------------------------------------------------------------------
  'HasBlobRef' class
-------------------------------------------------------------------------------}

class HasBlobRef f where
  getBlobRef :: f b  -> Maybe b

instance HasBlobRef (Class.LookupResult v) where
  getBlobRef Class.NotFound{}                = Nothing
  getBlobRef Class.Found{}                   = Nothing
  getBlobRef (Class.FoundWithBlob _ blobref) = Just blobref

instance HasBlobRef (Class.Entry k v) where
  getBlobRef Class.Entry{}                     = Nothing
  getBlobRef (Class.EntryWithBlob _ _ blobref) = Just blobref