grapesy-1.0.0: kvstore/KVStore/API.hs
-- | Serialization format agnostic layer
--
-- This allows us to the run the same client with either Protobuf or Java, and
-- similarly for the server.
module KVStore.API (
Key(..)
, Value(..)
, KVStore(..)
) where
import Control.DeepSeq (NFData)
import Control.Monad
import Data.Aeson.Types qualified as Aeson
import Data.ByteString (ByteString)
import Data.ByteString.Base64 qualified as Base64
import Data.Hashable
import Data.Text.Encoding qualified as Text
import Network.GRPC.Common.JSON
{-------------------------------------------------------------------------------
Key and value
-------------------------------------------------------------------------------}
newtype Key = Key {
getKey :: ByteString
}
deriving stock (Show, Eq, Ord)
deriving newtype (Hashable, NFData)
deriving (ToJSON, FromJSON) via Base64
newtype Value = Value {
getValue :: ByteString
}
deriving stock (Show, Eq, Ord)
deriving newtype (NFData)
deriving (ToJSON, FromJSON) via Base64
{-------------------------------------------------------------------------------
Main API
-------------------------------------------------------------------------------}
data KVStore = KVStore {
create :: (Key, Value) -> IO ()
, retrieve :: Key -> IO Value
, update :: (Key, Value) -> IO ()
, delete :: Key -> IO ()
}
{-------------------------------------------------------------------------------
Auxiliary: base64 encoding
-------------------------------------------------------------------------------}
newtype Base64 = Base64 { getBase64 :: ByteString }
instance ToJSON Base64 where
toJSON = toJSON . Text.decodeUtf8 . Base64.encode . getBase64
instance FromJSON Base64 where
parseJSON = fmap Base64 . decode . Text.encodeUtf8 <=< parseJSON
where
decode :: ByteString -> Aeson.Parser ByteString
decode = either fail return . Base64.decode