{-# LANGUAGE GeneralizedNewtypeDeriving, OverloadedStrings, RecordWildCards,
    StandaloneDeriving #-}

-- |
-- Module:      Network.Riak.Value
-- Copyright:   (c) 2011 MailRank, Inc.
-- License:     Apache
-- Maintainer:  Mark Hibberd <mark@hibberd.id.au>, Nathan Hunter <nhunter@janrain.com>
-- Stability:   experimental
-- Portability: portable
--
-- This module allows storage and retrieval of data using the
-- 'IsContent' typeclass.  This provides access to more of Riak's
-- storage features than JSON, e.g. links.
--
-- The functions in this module do not perform any conflict resolution.

module Network.Riak.Value
    (
      IsContent(..)
    , fromContent
    , get
    , getMany
    , getByIndex
    , addIndexes
    , put
    , putIndexed
    , put_
    , putMany
    , putMany_
    ) where

import Control.Applicative
import Data.Aeson.Types (Parser, Result(..), parse)
import Data.Monoid ((<>))
import Network.Riak.Connection.Internal
import Network.Riak.Lens
import Network.Riak.Resolvable (ResolvableMonoid(..))
import Network.Riak.Response (unescapeLinks)
import Network.Riak.Types.Internal hiding (MessageTag(..))
import qualified Data.Riak.Proto as Proto
import qualified Data.Aeson as Aeson (eitherDecodeStrict)
import qualified Data.Aeson.Types as Aeson
import qualified Data.ByteString as L
import qualified Data.ByteString.Char8 as CL8
import qualified Network.Riak.Content as C
import qualified Network.Riak.Request as Req

fromContent :: IsContent c => Proto.RpbContent -> Maybe c
fromContent :: RpbContent -> Maybe c
fromContent RpbContent
c = case (RpbContent -> Parser c) -> RpbContent -> Result c
forall a b. (a -> Parser b) -> a -> Result b
parse RpbContent -> Parser c
forall c. IsContent c => RpbContent -> Parser c
parseContent RpbContent
c of
                  Success c
a -> c -> Maybe c
forall a. a -> Maybe a
Just c
a
                  Error String
_   -> Maybe c
forall a. Maybe a
Nothing

class IsContent c where
    parseContent :: Proto.RpbContent -> Parser c
    toContent :: c -> Proto.RpbContent

instance IsContent Proto.RpbContent where
    parseContent :: RpbContent -> Parser RpbContent
parseContent = RpbContent -> Parser RpbContent
forall (m :: * -> *) a. Monad m => a -> m a
return
    {-# INLINE parseContent #-}

    toContent :: RpbContent -> RpbContent
toContent RpbContent
v = RpbContent
v
    {-# INLINE toContent #-}

instance IsContent () where
    parseContent :: RpbContent -> Parser ()
parseContent RpbContent
c | RpbContent
c RpbContent -> RpbContent -> Bool
forall a. Eq a => a -> a -> Bool
== RpbContent
C.empty = () -> Parser ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
                   | Bool
otherwise    = Parser ()
forall (f :: * -> *) a. Alternative f => f a
empty
    {-# INLINE parseContent #-}

    toContent :: () -> RpbContent
toContent ()
_ = RpbContent
C.empty
    {-# INLINE toContent #-}

instance IsContent Aeson.Value where
    parseContent :: RpbContent -> Parser Value
parseContent RpbContent
c | RpbContent
c RpbContent
-> Lens RpbContent (Maybe ByteString) -> Maybe ByteString
forall s a. s -> Lens s a -> a
^. Lens RpbContent (Maybe ByteString)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'contentType" a) =>
LensLike' f s a
Proto.maybe'contentType Maybe ByteString -> Maybe ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"application/json" =
                      case ByteString -> Either String Value
forall a. FromJSON a => ByteString -> Either String a
Aeson.eitherDecodeStrict (RpbContent
c RpbContent -> Lens RpbContent ByteString -> ByteString
forall s a. s -> Lens s a -> a
^. Lens RpbContent ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "value" a) =>
LensLike' f s a
Proto.value) of
                        Left String
err -> String -> Parser Value
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
                        Right Value
a -> Value -> Parser Value
forall (m :: * -> *) a. Monad m => a -> m a
return Value
a
                   | Bool
otherwise = String -> Parser Value
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"non-JSON document"
    toContent :: Value -> RpbContent
toContent = Value -> RpbContent
forall a. ToJSON a => a -> RpbContent
C.json
    {-# INLINE toContent #-}

deriving instance (IsContent a) => IsContent (ResolvableMonoid a)

-- | Add indexes to a content value for a further put request.
addIndexes :: [IndexValue] -> Proto.RpbContent -> Proto.RpbContent
addIndexes :: [IndexValue] -> RpbContent -> RpbContent
addIndexes [IndexValue]
ix RpbContent
c =
    RpbContent
c RpbContent -> (RpbContent -> RpbContent) -> RpbContent
forall a b. a -> (a -> b) -> b
& LensLike' Identity RpbContent [RpbPair]
forall (f :: * -> *) s a.
(Functor f, HasField s "indexes" a) =>
LensLike' f s a
Proto.indexes LensLike' Identity RpbContent [RpbPair]
-> [RpbPair] -> RpbContent -> RpbContent
forall s a. Setter s a -> a -> s -> s
.~ ((IndexValue -> RpbPair) -> [IndexValue] -> [RpbPair]
forall a b. (a -> b) -> [a] -> [b]
map IndexValue -> RpbPair
toPair [IndexValue]
ix)
  where
    toPair :: IndexValue -> Proto.RpbPair
    toPair :: IndexValue -> RpbPair
toPair (IndexInt ByteString
k Int
v) = RpbPair
forall msg. Message msg => msg
Proto.defMessage
                              RpbPair -> (RpbPair -> RpbPair) -> RpbPair
forall a b. a -> (a -> b) -> b
& LensLike' Identity RpbPair ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "key" a) =>
LensLike' f s a
Proto.key LensLike' Identity RpbPair ByteString
-> ByteString -> RpbPair -> RpbPair
forall s a. Setter s a -> a -> s -> s
.~ (ByteString
k ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"_int")
                              RpbPair -> (RpbPair -> RpbPair) -> RpbPair
forall a b. a -> (a -> b) -> b
& LensLike' Identity RpbPair ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "value" a) =>
LensLike' f s a
Proto.value LensLike' Identity RpbPair ByteString
-> ByteString -> RpbPair -> RpbPair
forall s a. Setter s a -> a -> s -> s
.~ (String -> ByteString
CL8.pack (String -> ByteString) -> (Int -> String) -> Int -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show (Int -> ByteString) -> Int -> ByteString
forall a b. (a -> b) -> a -> b
$ Int
v)
    toPair (IndexBin ByteString
k ByteString
v) = RpbPair
forall msg. Message msg => msg
Proto.defMessage
                              RpbPair -> (RpbPair -> RpbPair) -> RpbPair
forall a b. a -> (a -> b) -> b
& LensLike' Identity RpbPair ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "key" a) =>
LensLike' f s a
Proto.key LensLike' Identity RpbPair ByteString
-> ByteString -> RpbPair -> RpbPair
forall s a. Setter s a -> a -> s -> s
.~ (ByteString
k ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"_bin")
                              RpbPair -> (RpbPair -> RpbPair) -> RpbPair
forall a b. a -> (a -> b) -> b
& LensLike' Identity RpbPair ByteString
forall (f :: * -> *) s a.
(Functor f, HasField s "value" a) =>
LensLike' f s a
Proto.value LensLike' Identity RpbPair ByteString
-> ByteString -> RpbPair -> RpbPair
forall s a. Setter s a -> a -> s -> s
.~ ByteString
v

-- | Store a single value.  This may return multiple conflicting
-- siblings.  Choosing among them, and storing a new value, is your
-- responsibility.
--
-- You should /only/ supply 'Nothing' as a 'T.VClock' if you are sure
-- that the given type+bucket+key combination does not already exist.
-- If you omit a 'T.VClock' but the type+bucket+key /does/ exist, your
-- value will not be stored.
put :: (IsContent c) => Connection
    -> Maybe BucketType -> Bucket -> Key -> Maybe VClock -> c
    -> W -> DW -> IO ([c], VClock)
put :: Connection
-> Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> c
-> W
-> W
-> IO ([c], VClock)
put Connection
conn Maybe ByteString
btype ByteString
bucket ByteString
key Maybe VClock
mvclock c
val W
w W
dw =
  RpbPutResp -> IO ([c], VClock)
forall c. IsContent c => RpbPutResp -> IO ([c], VClock)
putResp (RpbPutResp -> IO ([c], VClock))
-> IO RpbPutResp -> IO ([c], VClock)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Connection -> RpbPutReq -> IO RpbPutResp
forall req resp. Exchange req resp => Connection -> req -> IO resp
exchange Connection
conn
              (Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> RpbContent
-> W
-> W
-> Bool
-> RpbPutReq
Req.put Maybe ByteString
btype ByteString
bucket ByteString
key Maybe VClock
mvclock (c -> RpbContent
forall c. IsContent c => c -> RpbContent
toContent c
val) W
w W
dw Bool
True)

-- | Store an indexed value.
putIndexed :: (IsContent c) => Connection -> Maybe BucketType -> Bucket -> Key
           -> [IndexValue]
           -> Maybe VClock -> c
           -> W -> DW -> IO ([c], VClock)
putIndexed :: Connection
-> Maybe ByteString
-> ByteString
-> ByteString
-> [IndexValue]
-> Maybe VClock
-> c
-> W
-> W
-> IO ([c], VClock)
putIndexed Connection
conn Maybe ByteString
bt ByteString
b ByteString
k [IndexValue]
inds Maybe VClock
mvclock c
val W
w W
dw =
    RpbPutResp -> IO ([c], VClock)
forall c. IsContent c => RpbPutResp -> IO ([c], VClock)
putResp (RpbPutResp -> IO ([c], VClock))
-> IO RpbPutResp -> IO ([c], VClock)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Connection -> RpbPutReq -> IO RpbPutResp
forall req resp. Exchange req resp => Connection -> req -> IO resp
exchange Connection
conn
                  (Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> RpbContent
-> W
-> W
-> Bool
-> RpbPutReq
Req.put Maybe ByteString
bt ByteString
b ByteString
k Maybe VClock
mvclock ([IndexValue] -> RpbContent -> RpbContent
addIndexes [IndexValue]
inds (c -> RpbContent
forall c. IsContent c => c -> RpbContent
toContent c
val))
                      W
w W
dw Bool
True)

-- | Store many values.  This may return multiple conflicting siblings
-- for each value stored.  Choosing among them, and storing a new
-- value in each case, is your responsibility.
--
-- You should /only/ supply 'Nothing' as a 'T.VClock' if you are sure
-- that the given type+bucket+key combination does not already exist.
-- If you omit a 'T.VClock' but the type+bucket+key /does/ exist, your
-- value will not be stored.
putMany :: (IsContent c) => Connection
        -> Maybe BucketType -> Bucket -> [(Key, Maybe VClock, c)]
        -> W -> DW -> IO [([c], VClock)]
putMany :: Connection
-> Maybe ByteString
-> ByteString
-> [(ByteString, Maybe VClock, c)]
-> W
-> W
-> IO [([c], VClock)]
putMany Connection
conn Maybe ByteString
bt ByteString
b [(ByteString, Maybe VClock, c)]
puts W
w W
dw =
  (RpbPutResp -> IO ([c], VClock))
-> [RpbPutResp] -> IO [([c], VClock)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM RpbPutResp -> IO ([c], VClock)
forall c. IsContent c => RpbPutResp -> IO ([c], VClock)
putResp ([RpbPutResp] -> IO [([c], VClock)])
-> IO [RpbPutResp] -> IO [([c], VClock)]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Connection -> [RpbPutReq] -> IO [RpbPutResp]
forall req resp.
Exchange req resp =>
Connection -> [req] -> IO [resp]
pipeline Connection
conn (((ByteString, Maybe VClock, c) -> RpbPutReq)
-> [(ByteString, Maybe VClock, c)] -> [RpbPutReq]
forall a b. (a -> b) -> [a] -> [b]
map (\(ByteString
k,Maybe VClock
v,c
c) -> Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> RpbContent
-> W
-> W
-> Bool
-> RpbPutReq
Req.put Maybe ByteString
bt ByteString
b ByteString
k Maybe VClock
v (c -> RpbContent
forall c. IsContent c => c -> RpbContent
toContent c
c) W
w W
dw Bool
True) [(ByteString, Maybe VClock, c)]
puts)

putResp :: (IsContent c) => Proto.RpbPutResp -> IO ([c], VClock)
putResp :: RpbPutResp -> IO ([c], VClock)
putResp RpbPutResp
response = do
  case RpbPutResp
response RpbPutResp
-> Lens RpbPutResp (Maybe ByteString) -> Maybe ByteString
forall s a. s -> Lens s a -> a
^. Lens RpbPutResp (Maybe ByteString)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'vclock" a) =>
LensLike' f s a
Proto.maybe'vclock of
    Maybe ByteString
Nothing -> ([c], VClock) -> IO ([c], VClock)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], ByteString -> VClock
VClock ByteString
L.empty)
    Just ByteString
s  -> do
      [c]
c <- [RpbContent] -> IO [c]
forall v. IsContent v => [RpbContent] -> IO [v]
convert (RpbPutResp
response RpbPutResp -> Lens RpbPutResp [RpbContent] -> [RpbContent]
forall s a. s -> Lens s a -> a
^. Lens RpbPutResp [RpbContent]
forall (f :: * -> *) s a.
(Functor f, HasField s "content" a) =>
LensLike' f s a
Proto.content)
      ([c], VClock) -> IO ([c], VClock)
forall (m :: * -> *) a. Monad m => a -> m a
return ([c]
c, ByteString -> VClock
VClock ByteString
s)

-- | Store a single value, without the possibility of conflict
-- resolution.
--
-- You should /only/ supply 'Nothing' as a 'T.VClock' if you are sure
-- that the given type+bucket+key combination does not already exist.
-- If you omit a 'T.VClock' but the type+bucket+key /does/ exist, your
-- value will not be stored, and you will not be notified.
put_ :: (IsContent c) => Connection
     -> Maybe BucketType -> Bucket -> Key -> Maybe VClock -> c
     -> W -> DW -> IO ()
put_ :: Connection
-> Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> c
-> W
-> W
-> IO ()
put_ Connection
conn Maybe ByteString
btype ByteString
bucket ByteString
key Maybe VClock
mvclock c
val W
w W
dw =
  Connection -> RpbPutReq -> IO ()
forall req. Request req => Connection -> req -> IO ()
exchange_ Connection
conn (Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> RpbContent
-> W
-> W
-> Bool
-> RpbPutReq
Req.put Maybe ByteString
btype ByteString
bucket ByteString
key Maybe VClock
mvclock (c -> RpbContent
forall c. IsContent c => c -> RpbContent
toContent c
val) W
w W
dw Bool
False)

-- | Store many values, without the possibility of conflict
-- resolution.
--
-- You should /only/ supply 'Nothing' as a 'T.VClock' if you are sure
-- that the given type+bucket+key combination does not already exist.
-- If you omit a 'T.VClock' but the type+bucket+key /does/ exist, your
-- value will not be stored, and you will not be notified.
putMany_ :: (IsContent c) => Connection
         -> Maybe BucketType -> Bucket -> [(Key, Maybe VClock, c)]
         -> W -> DW -> IO ()
putMany_ :: Connection
-> Maybe ByteString
-> ByteString
-> [(ByteString, Maybe VClock, c)]
-> W
-> W
-> IO ()
putMany_ Connection
conn Maybe ByteString
bt ByteString
b [(ByteString, Maybe VClock, c)]
puts W
w W
dw =
  Connection -> [RpbPutReq] -> IO ()
forall req. Request req => Connection -> [req] -> IO ()
pipeline_ Connection
conn ([RpbPutReq] -> IO ())
-> ([(ByteString, Maybe VClock, c)] -> [RpbPutReq])
-> [(ByteString, Maybe VClock, c)]
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, Maybe VClock, c) -> RpbPutReq)
-> [(ByteString, Maybe VClock, c)] -> [RpbPutReq]
forall a b. (a -> b) -> [a] -> [b]
map (\(ByteString
k,Maybe VClock
v,c
c) -> Maybe ByteString
-> ByteString
-> ByteString
-> Maybe VClock
-> RpbContent
-> W
-> W
-> Bool
-> RpbPutReq
Req.put Maybe ByteString
bt ByteString
b ByteString
k Maybe VClock
v (c -> RpbContent
forall c. IsContent c => c -> RpbContent
toContent c
c) W
w W
dw Bool
False) ([(ByteString, Maybe VClock, c)] -> IO ())
-> [(ByteString, Maybe VClock, c)] -> IO ()
forall a b. (a -> b) -> a -> b
$ [(ByteString, Maybe VClock, c)]
puts

-- | Retrieve a value.  This may return multiple conflicting siblings.
-- Choosing among them is your responsibility.
get :: (IsContent c) => Connection -> Maybe BucketType -> Bucket -> Key -> R
    -> IO (Maybe ([c], VClock))
get :: Connection
-> Maybe ByteString
-> ByteString
-> ByteString
-> W
-> IO (Maybe ([c], VClock))
get Connection
conn Maybe ByteString
btype ByteString
bucket ByteString
key W
r = Maybe RpbGetResp -> IO (Maybe ([c], VClock))
forall c.
IsContent c =>
Maybe RpbGetResp -> IO (Maybe ([c], VClock))
getResp (Maybe RpbGetResp -> IO (Maybe ([c], VClock)))
-> IO (Maybe RpbGetResp) -> IO (Maybe ([c], VClock))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Connection -> RpbGetReq -> IO (Maybe RpbGetResp)
forall req resp.
Exchange req resp =>
Connection -> req -> IO (Maybe resp)
exchangeMaybe Connection
conn (Maybe ByteString -> ByteString -> ByteString -> W -> RpbGetReq
Req.get Maybe ByteString
btype ByteString
bucket ByteString
key W
r)

-- | Retrieve list of keys matching some index query.
getByIndex :: Connection -> Bucket -> IndexQuery
           -> IO [Key]
getByIndex :: Connection -> ByteString -> IndexQuery -> IO [ByteString]
getByIndex Connection
conn ByteString
b IndexQuery
indq =
    Maybe RpbIndexResp -> IO [ByteString]
getByIndexResp (Maybe RpbIndexResp -> IO [ByteString])
-> IO (Maybe RpbIndexResp) -> IO [ByteString]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Connection -> RpbIndexReq -> IO (Maybe RpbIndexResp)
forall req resp.
Exchange req resp =>
Connection -> req -> IO (Maybe resp)
exchangeMaybe Connection
conn (ByteString -> IndexQuery -> RpbIndexReq
Req.getByIndex ByteString
b IndexQuery
indq)

getMany :: (IsContent c) => Connection
        -> Maybe BucketType -> Bucket -> [Key] -> R
        -> IO [Maybe ([c], VClock)]
getMany :: Connection
-> Maybe ByteString
-> ByteString
-> [ByteString]
-> W
-> IO [Maybe ([c], VClock)]
getMany Connection
conn Maybe ByteString
bt ByteString
b [ByteString]
ks W
r =
    (Maybe RpbGetResp -> IO (Maybe ([c], VClock)))
-> [Maybe RpbGetResp] -> IO [Maybe ([c], VClock)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Maybe RpbGetResp -> IO (Maybe ([c], VClock))
forall c.
IsContent c =>
Maybe RpbGetResp -> IO (Maybe ([c], VClock))
getResp ([Maybe RpbGetResp] -> IO [Maybe ([c], VClock)])
-> IO [Maybe RpbGetResp] -> IO [Maybe ([c], VClock)]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Connection -> [RpbGetReq] -> IO [Maybe RpbGetResp]
forall req resp.
Exchange req resp =>
Connection -> [req] -> IO [Maybe resp]
pipelineMaybe Connection
conn ((ByteString -> RpbGetReq) -> [ByteString] -> [RpbGetReq]
forall a b. (a -> b) -> [a] -> [b]
map (\ByteString
k -> Maybe ByteString -> ByteString -> ByteString -> W -> RpbGetReq
Req.get Maybe ByteString
bt ByteString
b ByteString
k W
r) [ByteString]
ks)

getResp :: (IsContent c) => Maybe Proto.RpbGetResp -> IO (Maybe ([c], VClock))
getResp :: Maybe RpbGetResp -> IO (Maybe ([c], VClock))
getResp Maybe RpbGetResp
resp =
  case Maybe RpbGetResp
resp of
    Just RpbGetResp
resp' ->
      case RpbGetResp
resp' RpbGetResp
-> Lens RpbGetResp (Maybe ByteString) -> Maybe ByteString
forall s a. s -> Lens s a -> a
^. Lens RpbGetResp (Maybe ByteString)
forall (f :: * -> *) s a.
(Functor f, HasField s "maybe'vclock" a) =>
LensLike' f s a
Proto.maybe'vclock of
        Just ByteString
s -> do
           [c]
c <- [RpbContent] -> IO [c]
forall v. IsContent v => [RpbContent] -> IO [v]
convert (RpbGetResp
resp' RpbGetResp -> Lens RpbGetResp [RpbContent] -> [RpbContent]
forall s a. s -> Lens s a -> a
^. Lens RpbGetResp [RpbContent]
forall (f :: * -> *) s a.
(Functor f, HasField s "content" a) =>
LensLike' f s a
Proto.content)
           Maybe ([c], VClock) -> IO (Maybe ([c], VClock))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([c], VClock) -> IO (Maybe ([c], VClock)))
-> Maybe ([c], VClock) -> IO (Maybe ([c], VClock))
forall a b. (a -> b) -> a -> b
$ ([c], VClock) -> Maybe ([c], VClock)
forall a. a -> Maybe a
Just ([c]
c, ByteString -> VClock
VClock ByteString
s)
        Maybe ByteString
_ -> Maybe ([c], VClock) -> IO (Maybe ([c], VClock))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([c], VClock)
forall a. Maybe a
Nothing
    Maybe RpbGetResp
_ -> Maybe ([c], VClock) -> IO (Maybe ([c], VClock))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([c], VClock)
forall a. Maybe a
Nothing

getByIndexResp :: Maybe Proto.RpbIndexResp -> IO [Key]
getByIndexResp :: Maybe RpbIndexResp -> IO [ByteString]
getByIndexResp Maybe RpbIndexResp
resp =
    case Maybe RpbIndexResp
resp of
      Just RpbIndexResp
resp' -> [ByteString] -> IO [ByteString]
forall (m :: * -> *) a. Monad m => a -> m a
return (RpbIndexResp
resp' RpbIndexResp -> Lens RpbIndexResp [ByteString] -> [ByteString]
forall s a. s -> Lens s a -> a
^. Lens RpbIndexResp [ByteString]
forall (f :: * -> *) s a.
(Functor f, HasField s "keys" a) =>
LensLike' f s a
Proto.keys)
      Maybe RpbIndexResp
Nothing -> [ByteString] -> IO [ByteString]
forall (m :: * -> *) a. Monad m => a -> m a
return []

convert :: IsContent v => [Proto.RpbContent] -> IO [v]
convert :: [RpbContent] -> IO [v]
convert = [RpbContent] -> [v] -> [RpbContent] -> IO [v]
forall a (m :: * -> *).
(IsContent a, Monad m) =>
[RpbContent] -> [a] -> [RpbContent] -> m [a]
go [] []
    where go :: [RpbContent] -> [a] -> [RpbContent] -> m [a]
go [RpbContent]
cs [a]
vs (RpbContent
x:[RpbContent]
xs) = case RpbContent -> Maybe a
forall c. IsContent c => RpbContent -> Maybe c
fromContent RpbContent
y of
                              Just a
v -> [RpbContent] -> [a] -> [RpbContent] -> m [a]
go [RpbContent]
cs (a
va -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
vs) [RpbContent]
xs
                              Maybe a
_      -> [RpbContent] -> [a] -> [RpbContent] -> m [a]
go (RpbContent
yRpbContent -> [RpbContent] -> [RpbContent]
forall a. a -> [a] -> [a]
:[RpbContent]
cs) [a]
vs [RpbContent]
xs
              where y :: RpbContent
y = RpbContent -> RpbContent
unescapeLinks RpbContent
x
          go [] [a]
vs [RpbContent]
_      = [a] -> m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
vs)
          go [RpbContent]
cs [a]
_  [RpbContent]
_      = String -> String -> String -> m [a]
forall a. String -> String -> String -> a
typeError String
"Network.Riak.Value" String
"convert" (String -> m [a]) -> String -> m [a]
forall a b. (a -> b) -> a -> b
$
                            Int -> String
forall a. Show a => a -> String
show ([RpbContent] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [RpbContent]
cs) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" values failed conversion: " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                            [RpbContent] -> String
forall a. Show a => a -> String
show [RpbContent]
cs