hask-redis-mux-0.1.0.0: lib/redis-command-client/Database/Redis/FromResp.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Typeclass for converting 'RespData' values into user-chosen Haskell types.
--
-- This module provides 'FromResp' together with a collection of instances for
-- common types so that Redis commands can return typed values instead of raw
-- 'RespData'.
--
-- @since 0.1.0.0
module Database.Redis.FromResp
( FromResp (..)
) where
import Data.ByteString (ByteString)
import Data.Text (Text)
import qualified Data.Text.Encoding as TE
import Database.Redis.RedisError (RedisError (..))
import Database.Redis.Resp (RespData (..))
-- | Convert a 'RespData' value to a Haskell type.
--
-- Returns @Left (UnexpectedResp rd)@ when the conversion cannot be performed
-- for the given RESP value @rd@.
class FromResp a where
fromResp :: RespData -> Either RedisError a
-- | Identity instance – always succeeds.
instance FromResp RespData where
fromResp :: RespData -> Either RedisError RespData
fromResp = Right
-- | Extracts the payload of 'RespBulkString' or 'RespSimpleString'.
instance FromResp ByteString where
fromResp :: RespData -> Either RedisError ByteString
fromResp (RespBulkString bs) = Right bs
fromResp (RespSimpleString bs) = Right bs
fromResp rd = Left (UnexpectedResp rd)
-- | 'Nothing' for 'RespNullBulkString', otherwise delegates to the 'ByteString' instance.
instance FromResp (Maybe ByteString) where
fromResp :: RespData -> Either RedisError (Maybe ByteString)
fromResp RespNullBulkString = Right Nothing
fromResp rd = Just <$> fromResp rd
-- | Extracts 'RespInteger' payload.
instance FromResp Integer where
fromResp :: RespData -> Either RedisError Integer
fromResp (RespInteger i) = Right i
fromResp rd = Left (UnexpectedResp rd)
-- | Interprets @RespSimpleString \"OK\"@ and @RespInteger 1@ as 'True',
-- @RespInteger 0@ as 'False'.
instance FromResp Bool where
fromResp :: RespData -> Either RedisError Bool
fromResp (RespSimpleString "OK") = Right True
fromResp (RespInteger 1) = Right True
fromResp (RespInteger 0) = Right False
fromResp rd = Left (UnexpectedResp rd)
-- | Extracts each element of a 'RespArray' as a 'ByteString'.
instance FromResp [ByteString] where
fromResp :: RespData -> Either RedisError [ByteString]
fromResp (RespArray xs) = traverse fromResp xs
fromResp rd = Left (UnexpectedResp rd)
-- | Extracts each element of a 'RespArray' as 'RespData'.
instance FromResp [RespData] where
fromResp :: RespData -> Either RedisError [RespData]
fromResp (RespArray xs) = Right xs
fromResp rd = Left (UnexpectedResp rd)
-- | Always succeeds, discarding the response.
instance FromResp () where
fromResp :: RespData -> Either RedisError ()
fromResp _ = Right ()
-- | UTF-8 decode a 'ByteString' payload into 'Text'.
instance FromResp Text where
fromResp :: RespData -> Either RedisError Text
fromResp rd = case fromResp rd of
Right (bs :: ByteString) -> case TE.decodeUtf8' bs of
Right t -> Right t
Left _ -> Left (UnexpectedResp rd)
Left e -> Left e
-- | 'Nothing' for 'RespNullBulkString', otherwise delegates to the 'Text' instance.
instance FromResp (Maybe Text) where
fromResp :: RespData -> Either RedisError (Maybe Text)
fromResp RespNullBulkString = Right Nothing
fromResp rd = Just <$> fromResp rd