keyed-vals-0.2.0.0: src/KeyedVals/Handle/Internal.hs
{-# LANGUAGE StrictData #-}
{-# OPTIONS_HADDOCK prune not-home #-}
{- |
Module : KeyedVals.Handle.Internal
Copyright : (c) 2022 Tim Emiola
Maintainer : Tim Emiola <adetokunbo@emio.la>
SPDX-License-Identifier: BSD3
Declares the abstract @'Handle'@
-}
module KeyedVals.Handle.Internal (
-- * types used in the @Handle@ functions
HandleErr (..),
Glob,
mkGlob,
globPattern,
isIn,
Selection (..),
-- * the abstract @Handle@
Handle (..),
-- * aliases used in the 'Handle' functions
Key,
Val,
ValsByKey,
) where
import Control.Exception (Exception)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as LB
import Data.List.NonEmpty (NonEmpty (..))
import Data.Map.Strict (Map)
import Data.Text (Text)
import Numeric.Natural (Natural)
import Redis.Glob (matches, validate)
-- | A handle for accessing the 'ValsByKey' store.
data Handle m = Handle
{ hLoadVal :: !(Key -> m (Either HandleErr (Maybe Val)))
, hSaveVal :: !(Key -> Val -> m (Either HandleErr ()))
, hCountKVs :: !(Key -> m (Either HandleErr Natural))
, hLoadKVs :: !(Key -> m (Either HandleErr ValsByKey))
, hSaveKVs :: !(Key -> ValsByKey -> m (Either HandleErr ()))
, hUpdateKVs :: !(Key -> ValsByKey -> m (Either HandleErr ()))
, hLoadFrom :: !(Key -> Key -> m (Either HandleErr (Maybe Val)))
, hSaveTo :: !(Key -> Key -> Val -> m (Either HandleErr ()))
, hLoadSlice :: !(Key -> Selection -> m (Either HandleErr ValsByKey))
, hDeleteSelected :: !(Selection -> m (Either HandleErr ()))
, hDeleteSelectedKVs :: !(Key -> Selection -> m (Either HandleErr ()))
, hClose :: !(m ())
}
-- | Represents the errors that might arise in 'Handle' functions
data HandleErr
= ConnectionClosed
| Unanticipated !Text
| NotDecoded !Text
| BadKey
| Gone !Key
deriving (Eq, Show)
-- | Represents ways of restricting the keys used in a @'ValsByKey'@
data Selection
= -- | any keys that match the glob pattern
Match !Glob
| -- | any of the specified keys
AllOf !(NonEmpty Key)
deriving (Eq, Show)
-- | Represents a redis glob use to select keys
newtype Glob = Glob {globPattern :: ByteString}
deriving (Eq, Show)
{- | constructor for a 'Glob'
returns 'Nothing' if the pattern is invalid
-}
mkGlob :: ByteString -> Maybe Glob
mkGlob = fmap (Glob . LB.toStrict) . validate . LB.fromStrict
-- | tests if a 'ByteString' matches a Selection
isIn :: ByteString -> Selection -> Bool
isIn b (Match g) = LB.fromStrict b `matches` LB.fromStrict (globPattern g)
isIn b (AllOf (key :| ks)) = key == b || b `elem` ks
instance Exception HandleErr
-- | Represents a key used to store a 'Val'.
type Key = ByteString
-- | Represents a value stored in the service.
type Val = ByteString
-- | Represents a related group of @'Val'@s stored by @'Key'@.
type ValsByKey = Map Key Val