module System.Directory.Watchman.BSER
    ( BSERObject
    , BSERValue(..)
    , compactBSERInt
    , readBSERInt
    , readBSERInt64
    ) where

import Control.Monad (replicateM, forM, forM_, when)
import Data.Binary
import Data.Binary.Get
import Data.Binary.Put
import Data.ByteString (ByteString)
import Data.Foldable (toList)
import Data.Int
import Data.Map.Strict (Map)
import Data.Maybe (mapMaybe)
import Data.Sequence (Seq)
import qualified Data.ByteString as B
import qualified Data.Map.Strict as M
import qualified Data.Sequence as Seq

type BSERObject = Map ByteString BSERValue

-- | See:
--   <https://facebook.github.io/watchman/docs/bser.html>
data BSERValue
    = BSERArray (Seq BSERValue)
    | BSERObject (Map ByteString BSERValue)
    | BSERString ByteString
    | BSERInt8 Int8
    | BSERInt16 Int16
    | BSERInt32 Int32
    | BSERInt64 Int64
    | BSERReal Double
    | BSERBool Bool
    | BSERNull
    deriving (Int -> BSERValue -> ShowS
[BSERValue] -> ShowS
BSERValue -> String
(Int -> BSERValue -> ShowS)
-> (BSERValue -> String)
-> ([BSERValue] -> ShowS)
-> Show BSERValue
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BSERValue] -> ShowS
$cshowList :: [BSERValue] -> ShowS
show :: BSERValue -> String
$cshow :: BSERValue -> String
showsPrec :: Int -> BSERValue -> ShowS
$cshowsPrec :: Int -> BSERValue -> ShowS
Show, BSERValue -> BSERValue -> Bool
(BSERValue -> BSERValue -> Bool)
-> (BSERValue -> BSERValue -> Bool) -> Eq BSERValue
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BSERValue -> BSERValue -> Bool
$c/= :: BSERValue -> BSERValue -> Bool
== :: BSERValue -> BSERValue -> Bool
$c== :: BSERValue -> BSERValue -> Bool
Eq, Eq BSERValue
Eq BSERValue
-> (BSERValue -> BSERValue -> Ordering)
-> (BSERValue -> BSERValue -> Bool)
-> (BSERValue -> BSERValue -> Bool)
-> (BSERValue -> BSERValue -> Bool)
-> (BSERValue -> BSERValue -> Bool)
-> (BSERValue -> BSERValue -> BSERValue)
-> (BSERValue -> BSERValue -> BSERValue)
-> Ord BSERValue
BSERValue -> BSERValue -> Bool
BSERValue -> BSERValue -> Ordering
BSERValue -> BSERValue -> BSERValue
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: BSERValue -> BSERValue -> BSERValue
$cmin :: BSERValue -> BSERValue -> BSERValue
max :: BSERValue -> BSERValue -> BSERValue
$cmax :: BSERValue -> BSERValue -> BSERValue
>= :: BSERValue -> BSERValue -> Bool
$c>= :: BSERValue -> BSERValue -> Bool
> :: BSERValue -> BSERValue -> Bool
$c> :: BSERValue -> BSERValue -> Bool
<= :: BSERValue -> BSERValue -> Bool
$c<= :: BSERValue -> BSERValue -> Bool
< :: BSERValue -> BSERValue -> Bool
$c< :: BSERValue -> BSERValue -> Bool
compare :: BSERValue -> BSERValue -> Ordering
$ccompare :: BSERValue -> BSERValue -> Ordering
$cp1Ord :: Eq BSERValue
Ord)

readBSERInt :: BSERValue -> Either String Int
readBSERInt :: BSERValue -> Either String Int
readBSERInt (BSERInt8 Int8
n) = Int -> Either String Int
forall a b. b -> Either a b
Right (Int8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
n)
readBSERInt (BSERInt16 Int16
n) = Int -> Either String Int
forall a b. b -> Either a b
Right (Int16 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
n)
readBSERInt (BSERInt32 Int32
n) = Int -> Either String Int
forall a b. b -> Either a b
Right (Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
n)
readBSERInt (BSERInt64 Int64
n) =
    if Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
>= Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
minBound :: Int) Bool -> Bool -> Bool
&& Int64
n Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)
        then Int -> Either String Int
forall a b. b -> Either a b
Right (Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
n)
        else String -> Either String Int
forall a b. a -> Either a b
Left String
conversionError
    where
    conversionError :: String
conversionError = String
"Integer value is out of range"
readBSERInt BSERValue
_ = String -> Either String Int
forall a b. a -> Either a b
Left String
"Not an Integer"

readBSERInt64 :: BSERValue -> Either String Int64
readBSERInt64 :: BSERValue -> Either String Int64
readBSERInt64 (BSERInt8 Int8
n) = Int64 -> Either String Int64
forall a b. b -> Either a b
Right (Int8 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
n)
readBSERInt64 (BSERInt16 Int16
n) = Int64 -> Either String Int64
forall a b. b -> Either a b
Right (Int16 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
n)
readBSERInt64 (BSERInt32 Int32
n) = Int64 -> Either String Int64
forall a b. b -> Either a b
Right (Int32 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
n)
readBSERInt64 (BSERInt64 Int64
n) = Int64 -> Either String Int64
forall a b. b -> Either a b
Right Int64
n
readBSERInt64 BSERValue
_ = String -> Either String Int64
forall a b. a -> Either a b
Left String
"Not an Integer"


-- | Chooses the smallest BSERInt* that the number will fit into
compactBSERInt :: Integral n => n -> BSERValue
compactBSERInt :: n -> BSERValue
compactBSERInt n
n | n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
0x80 Bool -> Bool -> Bool
&& n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
>= (-n
0x80) = Int8 -> BSERValue
BSERInt8 (n -> Int8
forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n)
                 | n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
0x8000 Bool -> Bool -> Bool
&& n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
>= (-n
0x8000) = Int16 -> BSERValue
BSERInt16 (n -> Int16
forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n)
                 | n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
< n
0x80000000 Bool -> Bool -> Bool
&& n
n n -> n -> Bool
forall a. Ord a => a -> a -> Bool
>= (-n
0x80000000) = Int32 -> BSERValue
BSERInt32 (n -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n)
                 | Bool
otherwise = Int64 -> BSERValue
BSERInt64 (n -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n)

instance Binary BSERValue where
    put :: BSERValue -> Put
put (BSERArray Seq BSERValue
elements) = do
        Word8 -> Put
putWord8 Word8
0x00
        BSERValue -> Put
forall t. Binary t => t -> Put
put (Int -> BSERValue
forall n. Integral n => n -> BSERValue
compactBSERInt (Seq BSERValue -> Int
forall a. Seq a -> Int
Seq.length Seq BSERValue
elements))
        (BSERValue -> Put) -> Seq BSERValue -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ BSERValue -> Put
forall t. Binary t => t -> Put
put Seq BSERValue
elements
    put (BSERObject Map ByteString BSERValue
o) = do
        Word8 -> Put
putWord8 Word8
0x01
        BSERValue -> Put
forall t. Binary t => t -> Put
put (Int -> BSERValue
forall n. Integral n => n -> BSERValue
compactBSERInt (Map ByteString BSERValue -> Int
forall k a. Map k a -> Int
M.size Map ByteString BSERValue
o))
        [(ByteString, BSERValue)]
-> ((ByteString, BSERValue) -> Put) -> Put
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (Map ByteString BSERValue -> [(ByteString, BSERValue)]
forall k a. Map k a -> [(k, a)]
M.assocs Map ByteString BSERValue
o) (((ByteString, BSERValue) -> Put) -> Put)
-> ((ByteString, BSERValue) -> Put) -> Put
forall a b. (a -> b) -> a -> b
$ \(ByteString
k, BSERValue
v) -> do
            BSERValue -> Put
forall t. Binary t => t -> Put
put (ByteString -> BSERValue
BSERString ByteString
k)
            BSERValue -> Put
forall t. Binary t => t -> Put
put BSERValue
v
    put (BSERString ByteString
str) = do
        Word8 -> Put
putWord8 Word8
0x02
        BSERValue -> Put
forall t. Binary t => t -> Put
put (Int -> BSERValue
forall n. Integral n => n -> BSERValue
compactBSERInt (ByteString -> Int
B.length ByteString
str))
        ByteString -> Put
putByteString ByteString
str
    put (BSERInt8 Int8
n) = do
        Word8 -> Put
putWord8 Word8
0x03
        Int8 -> Put
putInt8 Int8
n
    put (BSERInt16 Int16
n) = do
        Word8 -> Put
putWord8 Word8
0x04
        Int16 -> Put
putInt16host Int16
n
    put (BSERInt32 Int32
n) = do
        Word8 -> Put
putWord8 Word8
0x05
        Int32 -> Put
putInt32host Int32
n
    put (BSERInt64 Int64
n) = do
        Word8 -> Put
putWord8 Word8
0x06
        Int64 -> Put
putInt64host Int64
n
    put (BSERReal Double
r) = do
        Word8 -> Put
putWord8 Word8
0x07
        Double -> Put
putDoublehost Double
r
    put (BSERBool Bool
True) =
        Word8 -> Put
putWord8 Word8
0x08
    put (BSERBool Bool
False) =
        Word8 -> Put
putWord8 Word8
0x09
    put BSERValue
BSERNull =
        Word8 -> Put
putWord8 Word8
0x0a

    get :: Get BSERValue
get = do
        Word8
tag <- Get Word8
getWord8
        case Word8
tag of
            Word8
0x00 -> do
                BSERValue
numVal <- Get BSERValue
forall t. Binary t => Get t
get
                Int
num <- case BSERValue -> Either String Int
readBSERInt BSERValue
numVal of
                    Left String
err -> String -> Get Int
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
                    Right Int
n -> Int -> Get Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
n
                Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (Get () -> Get ()) -> Get () -> Get ()
forall a b. (a -> b) -> a -> b
$
                    String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Negative Array length"
                [BSERValue]
elements <- Int -> Get BSERValue -> Get [BSERValue]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
num Get BSERValue
forall t. Binary t => Get t
get
                BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Seq BSERValue -> BSERValue
BSERArray ([BSERValue] -> Seq BSERValue
forall a. [a] -> Seq a
Seq.fromList [BSERValue]
elements))
            Word8
0x01 -> do
                BSERValue
numVal <- Get BSERValue
forall t. Binary t => Get t
get
                Int
num <- case BSERValue -> Either String Int
readBSERInt BSERValue
numVal of
                    Left String
err -> String -> Get Int
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
                    Right Int
n -> Int -> Get Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
n
                Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
num Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (Get () -> Get ()) -> Get () -> Get ()
forall a b. (a -> b) -> a -> b
$
                    String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Negative number of properties for Object"
                [(ByteString, BSERValue)]
pairs <- Int -> Get (ByteString, BSERValue) -> Get [(ByteString, BSERValue)]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
num (Get (ByteString, BSERValue) -> Get [(ByteString, BSERValue)])
-> Get (ByteString, BSERValue) -> Get [(ByteString, BSERValue)]
forall a b. (a -> b) -> a -> b
$ do
                    BSERValue
key <- Get BSERValue
forall t. Binary t => Get t
get
                    BSERValue
val <- Get BSERValue
forall t. Binary t => Get t
get
                    ByteString
keyStr <- case BSERValue
key of
                        BSERString ByteString
str -> ByteString -> Get ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
str
                        BSERValue
_ -> String -> Get ByteString
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid Key type"
                    (ByteString, BSERValue) -> Get (ByteString, BSERValue)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString
keyStr, BSERValue
val)
                BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map ByteString BSERValue -> BSERValue
BSERObject ([(ByteString, BSERValue)] -> Map ByteString BSERValue
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(ByteString, BSERValue)]
pairs))
            Word8
0x02 -> do
                BSERValue
lenVal <- Get BSERValue
forall t. Binary t => Get t
get
                Int
len <- case BSERValue -> Either String Int
readBSERInt BSERValue
lenVal of
                    Left String
err -> String -> Get Int
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
                    Right Int
n -> Int -> Get Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
n
                Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (Get () -> Get ()) -> Get () -> Get ()
forall a b. (a -> b) -> a -> b
$
                    String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Negative String length"
                ByteString
str <- Int -> Get ByteString
getByteString Int
len
                BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> BSERValue
BSERString ByteString
str)
            Word8
0x03 -> Get Int8
getInt8 Get Int8 -> (Int8 -> Get BSERValue) -> Get BSERValue
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BSERValue -> Get BSERValue)
-> (Int8 -> BSERValue) -> Int8 -> Get BSERValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int8 -> BSERValue
BSERInt8
            Word8
0x04 -> Get Int16
getInt16host Get Int16 -> (Int16 -> Get BSERValue) -> Get BSERValue
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BSERValue -> Get BSERValue)
-> (Int16 -> BSERValue) -> Int16 -> Get BSERValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int16 -> BSERValue
BSERInt16
            Word8
0x05 -> Get Int32
getInt32host Get Int32 -> (Int32 -> Get BSERValue) -> Get BSERValue
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BSERValue -> Get BSERValue)
-> (Int32 -> BSERValue) -> Int32 -> Get BSERValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> BSERValue
BSERInt32
            Word8
0x06 -> Get Int64
getInt64host Get Int64 -> (Int64 -> Get BSERValue) -> Get BSERValue
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BSERValue -> Get BSERValue)
-> (Int64 -> BSERValue) -> Int64 -> Get BSERValue
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> BSERValue
BSERInt64
            Word8
0x07 -> do
                Double
r <- Get Double
getDoublehost
                BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double -> BSERValue
BSERReal Double
r)
            Word8
0x08 -> BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> BSERValue
BSERBool Bool
True)
            Word8
0x09 -> BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> BSERValue
BSERBool Bool
False)
            Word8
0x0a -> BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure BSERValue
BSERNull
            Word8
0x0b -> do
                BSERValue
h <- Get BSERValue
forall t. Binary t => Get t
get
                [ByteString]
keys <- case BSERValue
h of
                    BSERArray Seq BSERValue
keys -> [BSERValue] -> (BSERValue -> Get ByteString) -> Get [ByteString]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM (Seq BSERValue -> [BSERValue]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq BSERValue
keys) ((BSERValue -> Get ByteString) -> Get [ByteString])
-> (BSERValue -> Get ByteString) -> Get [ByteString]
forall a b. (a -> b) -> a -> b
$ \BSERValue
v -> do
                        case BSERValue
v of
                            BSERString ByteString
str -> ByteString -> Get ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure ByteString
str
                            BSERValue
_ -> String -> Get ByteString
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Array of Templated Object header has a key that is not a String"
                    BSERValue
_ -> String -> Get [ByteString]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Array of Templated Object header is not an Array"
                let numKeys :: Int
numKeys = [ByteString] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ByteString]
keys
                BSERValue
numV <- Get BSERValue
forall t. Binary t => Get t
get
                Int
numObjs <- case BSERValue -> Either String Int
readBSERInt BSERValue
numV of
                    Left String
err -> String -> Get Int
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
                    Right Int
n -> Int -> Get Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
n
                Bool -> Get () -> Get ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
numObjs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (Get () -> Get ()) -> Get () -> Get ()
forall a b. (a -> b) -> a -> b
$
                    String -> Get ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid number of values in Array of Templated Object"
                [BSERValue]
objs <- Int -> Get BSERValue -> Get [BSERValue]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
numObjs (Get BSERValue -> Get [BSERValue])
-> Get BSERValue -> Get [BSERValue]
forall a b. (a -> b) -> a -> b
$ do
                    [Maybe BSERValue]
vals <- Int -> Get (Maybe BSERValue) -> Get [Maybe BSERValue]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
numKeys (Get (Maybe BSERValue) -> Get [Maybe BSERValue])
-> Get (Maybe BSERValue) -> Get [Maybe BSERValue]
forall a b. (a -> b) -> a -> b
$ do
                        Get (Maybe BSERValue)
getTemplatedObjectValue
                    BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map ByteString BSERValue -> BSERValue
BSERObject ([ByteString] -> [Maybe BSERValue] -> Map ByteString BSERValue
forall k a. Ord k => [k] -> [Maybe a] -> Map k a
buildMap [ByteString]
keys [Maybe BSERValue]
vals))
                BSERValue -> Get BSERValue
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Seq BSERValue -> BSERValue
BSERArray ([BSERValue] -> Seq BSERValue
forall a. [a] -> Seq a
Seq.fromList [BSERValue]
objs))
            Word8
unknown -> String -> Get BSERValue
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Get BSERValue) -> String -> Get BSERValue
forall a b. (a -> b) -> a -> b
$ String
"Unknown tag: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word8 -> String
forall a. Show a => a -> String
show Word8
unknown

getTemplatedObjectValue :: Get (Maybe BSERValue)
getTemplatedObjectValue :: Get (Maybe BSERValue)
getTemplatedObjectValue = do
    Word8
tag <- Get Word8 -> Get Word8
forall a. Get a -> Get a
lookAhead Get Word8
getWord8
    if Word8
tag Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x0c then Maybe BSERValue -> Get (Maybe BSERValue)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe BSERValue
forall a. Maybe a
Nothing
        else do
            BSERValue
v <- Get BSERValue
forall t. Binary t => Get t
get
            Maybe BSERValue -> Get (Maybe BSERValue)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (BSERValue -> Maybe BSERValue
forall a. a -> Maybe a
Just BSERValue
v)

buildMap :: Ord k => [k] -> [Maybe a] -> Map k a
buildMap :: [k] -> [Maybe a] -> Map k a
buildMap [k]
keys [Maybe a]
vals = [(k, a)] -> Map k a
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(k, a)]
validPairs
    where
    pairs :: [(k, Maybe a)]
pairs = [k] -> [Maybe a] -> [(k, Maybe a)]
forall a b. [a] -> [b] -> [(a, b)]
zip [k]
keys [Maybe a]
vals
    validPairs :: [(k, a)]
validPairs = ((k, Maybe a) -> Maybe (k, a)) -> [(k, Maybe a)] -> [(k, a)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (k, Maybe a) -> Maybe (k, a)
forall a b. (a, Maybe b) -> Maybe (a, b)
choose [(k, Maybe a)]
pairs
    choose :: (a, Maybe b) -> Maybe (a, b)
choose (a
_, Maybe b
Nothing) = Maybe (a, b)
forall a. Maybe a
Nothing
    choose (a
k, Just b
v) = (a, b) -> Maybe (a, b)
forall a. a -> Maybe a
Just (a
k, b
v)