{-# LANGUAGE CPP #-}

-- |
-- The LaunchDarkly SDK supports a subset of Aeson 1.x and 2.x. These two
-- versions differ in their type signatures, but are otherwise largely
-- compatible. To support both versions, we provide this compatibility module.
--
-- Depending on the version of Aeson you have installed, this module will
-- expose a KeyMap type that is either
--
-- - In the case of 1.x, a HashMap T.Text, or
-- - In the case of 2.x, the new KeyMap type
--
-- The compatibility layer exposes common map operations that the SDK needs and
-- may prove useful to customers. In nearly all instances, these are simple
-- aliases for the underlying Aeson equivalents.
--
-- The Aeson 2.x KeyMap is keyed by a new Key type that does not exist in 1.x.
-- To keep the API as consistent as possible, all functions requiring a key
-- will provide a Text value. In the 2.x compatibility layer, we will convert
-- it to a from the appropriate Key type as necessary.
module LaunchDarkly.AesonCompat where

#if MIN_VERSION_aeson(2,0,0)
import           Data.Aeson        (Key)
import qualified Data.Aeson.Key    as Key
import qualified Data.Aeson.KeyMap as KeyMap
import           Data.Functor.Identity      (Identity(..), runIdentity)
import qualified Data.Map.Strict as M
#else
import qualified Data.HashMap.Strict as HM
#endif
import qualified Data.Text as T

#if MIN_VERSION_aeson(2,0,0)
type KeyMap = KeyMap.KeyMap

null :: KeyMap v -> Bool
null :: forall v. KeyMap v -> Bool
null = KeyMap v -> Bool
forall v. KeyMap v -> Bool
KeyMap.null

emptyObject :: KeyMap v
emptyObject :: forall v. KeyMap v
emptyObject = KeyMap v
forall v. KeyMap v
KeyMap.empty

singleton :: T.Text -> v -> KeyMap v
singleton :: forall v. Text -> v -> KeyMap v
singleton Text
key = Key -> v -> KeyMap v
forall v. Key -> v -> KeyMap v
KeyMap.singleton (Text -> Key
Key.fromText Text
key)

fromList :: [(T.Text, v)] -> KeyMap v
fromList :: forall v. [(Text, v)] -> KeyMap v
fromList [(Text, v)]
list = [(Key, v)] -> KeyMap v
forall v. [(Key, v)] -> KeyMap v
KeyMap.fromList (((Text, v) -> (Key, v)) -> [(Text, v)] -> [(Key, v)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Text
k, v
v) -> ((Text -> Key
Key.fromText Text
k), v
v)) [(Text, v)]
list)

toList :: KeyMap v -> [(T.Text, v)]
toList :: forall v. KeyMap v -> [(Text, v)]
toList KeyMap v
m = ((Key, v) -> (Text, v)) -> [(Key, v)] -> [(Text, v)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Key
k, v
v) -> ((Key -> Text
Key.toText Key
k), v
v)) (KeyMap v -> [(Key, v)]
forall v. KeyMap v -> [(Key, v)]
KeyMap.toList KeyMap v
m)

deleteKey :: T.Text -> KeyMap.KeyMap v -> KeyMap.KeyMap v
deleteKey :: forall v. Text -> KeyMap v -> KeyMap v
deleteKey Text
key = Key -> KeyMap v -> KeyMap v
forall v. Key -> KeyMap v -> KeyMap v
KeyMap.delete (Text -> Key
Key.fromText Text
key)

lookupKey :: T.Text -> KeyMap.KeyMap v -> Maybe v
lookupKey :: forall v. Text -> KeyMap v -> Maybe v
lookupKey Text
key = Key -> KeyMap v -> Maybe v
forall v. Key -> KeyMap v -> Maybe v
KeyMap.lookup (Text -> Key
Key.fromText Text
key)

objectKeys :: KeyMap.KeyMap v -> [T.Text]
objectKeys :: forall v. KeyMap v -> [Text]
objectKeys = (Key -> Text) -> [Key] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Key -> Text
Key.toText ([Key] -> [Text]) -> (KeyMap v -> [Key]) -> KeyMap v -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KeyMap v -> [Key]
forall v. KeyMap v -> [Key]
KeyMap.keys

objectValues :: KeyMap.KeyMap v -> [v]
objectValues :: forall v. KeyMap v -> [v]
objectValues KeyMap v
m = ((Key, v) -> v) -> [(Key, v)] -> [v]
forall a b. (a -> b) -> [a] -> [b]
map (Key, v) -> v
forall a b. (a, b) -> b
snd ([(Key, v)] -> [v]) -> [(Key, v)] -> [v]
forall a b. (a -> b) -> a -> b
$ KeyMap v -> [(Key, v)]
forall v. KeyMap v -> [(Key, v)]
KeyMap.toList KeyMap v
m

keyToText :: Key -> T.Text
keyToText :: Key -> Text
keyToText = Key -> Text
Key.toText

insertKey :: T.Text -> v -> KeyMap.KeyMap v -> KeyMap.KeyMap v
insertKey :: forall v. Text -> v -> KeyMap v -> KeyMap v
insertKey Text
key = Key -> v -> KeyMap v -> KeyMap v
forall v. Key -> v -> KeyMap v -> KeyMap v
KeyMap.insert (Text -> Key
Key.fromText Text
key)

filterKeys :: (Key -> Bool) -> KeyMap.KeyMap a -> KeyMap.KeyMap a
filterKeys :: forall a. (Key -> Bool) -> KeyMap a -> KeyMap a
filterKeys Key -> Bool
p = (Key -> a -> Bool) -> KeyMap a -> KeyMap a
forall v. (Key -> v -> Bool) -> KeyMap v -> KeyMap v
KeyMap.filterWithKey (\Key
key a
_ -> Key -> Bool
p Key
key)

filterObject :: (v -> Bool) -> KeyMap.KeyMap v -> KeyMap.KeyMap v
filterObject :: forall v. (v -> Bool) -> KeyMap v -> KeyMap v
filterObject = (v -> Bool) -> KeyMap v -> KeyMap v
forall v. (v -> Bool) -> KeyMap v -> KeyMap v
KeyMap.filter

adjustKey :: (v -> v) -> Key -> KeyMap.KeyMap v -> KeyMap.KeyMap v
adjustKey :: forall v. (v -> v) -> Key -> KeyMap v -> KeyMap v
adjustKey v -> v
f Key
k = Identity (KeyMap v) -> KeyMap v
forall a. Identity a -> a
runIdentity (Identity (KeyMap v) -> KeyMap v)
-> (KeyMap v -> Identity (KeyMap v)) -> KeyMap v -> KeyMap v
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe v -> Identity (Maybe v))
-> Key -> KeyMap v -> Identity (KeyMap v)
forall (f :: * -> *) v.
Functor f =>
(Maybe v -> f (Maybe v)) -> Key -> KeyMap v -> f (KeyMap v)
KeyMap.alterF (Maybe v -> Identity (Maybe v)
forall a. a -> Identity a
Identity (Maybe v -> Identity (Maybe v))
-> (Maybe v -> Maybe v) -> Maybe v -> Identity (Maybe v)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v -> v) -> Maybe v -> Maybe v
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap v -> v
f) Key
k

mapValues :: (v1 -> v2) -> KeyMap.KeyMap v1 -> KeyMap.KeyMap v2
mapValues :: forall v1 v2. (v1 -> v2) -> KeyMap v1 -> KeyMap v2
mapValues = (v1 -> v2) -> KeyMap v1 -> KeyMap v2
forall v1 v2. (v1 -> v2) -> KeyMap v1 -> KeyMap v2
KeyMap.map

mapWithKey :: (T.Text -> v1 -> v2) -> KeyMap.KeyMap v1 -> KeyMap.KeyMap v2
mapWithKey :: forall v1 v2. (Text -> v1 -> v2) -> KeyMap v1 -> KeyMap v2
mapWithKey Text -> v1 -> v2
f KeyMap v1
m = Map Key v2 -> KeyMap v2
forall v. Map Key v -> KeyMap v
KeyMap.fromMap ((Key -> v1 -> v2) -> Map Key v1 -> Map Key v2
forall k a b. (k -> a -> b) -> Map k a -> Map k b
M.mapWithKey (\Key
k v1
v -> Text -> v1 -> v2
f (Key -> Text
keyToText Key
k) v1
v) (KeyMap v1 -> Map Key v1
forall v. KeyMap v -> Map Key v
KeyMap.toMap KeyMap v1
m))

mapMaybeValues :: (v1 -> Maybe v2) -> KeyMap.KeyMap v1 -> KeyMap.KeyMap v2
mapMaybeValues :: forall v1 v2. (v1 -> Maybe v2) -> KeyMap v1 -> KeyMap v2
mapMaybeValues = (v1 -> Maybe v2) -> KeyMap v1 -> KeyMap v2
forall v1 v2. (v1 -> Maybe v2) -> KeyMap v1 -> KeyMap v2
KeyMap.mapMaybe

keyMapUnion :: KeyMap.KeyMap v -> KeyMap.KeyMap v -> KeyMap.KeyMap v
keyMapUnion :: forall v. KeyMap v -> KeyMap v -> KeyMap v
keyMapUnion = KeyMap v -> KeyMap v -> KeyMap v
forall v. KeyMap v -> KeyMap v -> KeyMap v
KeyMap.union

foldrWithKey :: (T.Text -> v -> a -> a) -> a -> KeyMap.KeyMap v -> a
foldrWithKey :: forall v a. (Text -> v -> a -> a) -> a -> KeyMap v -> a
foldrWithKey Text -> v -> a -> a
f a
accum KeyMap v
initial = (Key -> v -> a -> a) -> a -> KeyMap v -> a
forall v a. (Key -> v -> a -> a) -> a -> KeyMap v -> a
KeyMap.foldrWithKey (\Key
k v
v a
a -> Text -> v -> a -> a
f (Key -> Text
keyToText Key
k) v
v a
a) a
accum KeyMap v
initial
#else
type KeyMap = HM.HashMap T.Text

null :: KeyMap v -> Bool
null = HM.null

emptyObject :: KeyMap v
emptyObject = HM.empty

singleton :: T.Text -> v -> HM.HashMap T.Text v
singleton = HM.singleton

fromList :: [(T.Text, v)] -> KeyMap v
fromList = HM.fromList

toList :: HM.HashMap T.Text v -> [(T.Text, v)]
toList = HM.toList

deleteKey :: T.Text -> HM.HashMap T.Text v -> HM.HashMap T.Text v
deleteKey = HM.delete

lookupKey :: T.Text -> HM.HashMap T.Text v -> Maybe v
lookupKey = HM.lookup

objectKeys :: HM.HashMap T.Text v -> [T.Text]
objectKeys = HM.keys

objectValues :: HM.HashMap T.Text v -> [v]
objectValues = HM.elems

keyToText :: T.Text -> T.Text
keyToText = id

insertKey :: T.Text -> v -> HM.HashMap T.Text v -> HM.HashMap T.Text v
insertKey = HM.insert

filterKeys :: (T.Text -> Bool) -> HM.HashMap T.Text a -> HM.HashMap T.Text a
filterKeys p = HM.filterWithKey (\key _ -> p key)

filterObject :: (v -> Bool) -> HM.HashMap T.Text v -> HM.HashMap T.Text v
filterObject = HM.filter

adjustKey :: (v -> v) -> T.Text -> HM.HashMap T.Text v -> HM.HashMap T.Text v
adjustKey = HM.adjust

mapValues :: (v1 -> v2) -> HM.HashMap T.Text v1 -> HM.HashMap T.Text v2
mapValues = HM.map

mapWithKey :: (T.Text -> v1 -> v2) -> HM.HashMap T.Text v1 -> HM.HashMap T.Text v2
mapWithKey = HM.mapWithKey

mapMaybeValues :: (v1 -> Maybe v2) -> HM.HashMap T.Text v1 -> HM.HashMap T.Text v2
mapMaybeValues = HM.mapMaybe

keyMapUnion :: HM.HashMap T.Text v -> HM.HashMap T.Text v -> HM.HashMap T.Text v
keyMapUnion = HM.union

foldrWithKey :: (T.Text -> v -> a -> a) -> a -> HM.HashMap T.Text v -> a
foldrWithKey = HM.foldrWithKey
#endif