{-# 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 = KeyMap.null

emptyObject :: KeyMap v
emptyObject = KeyMap.empty

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

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

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

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

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

objectKeys :: KeyMap.KeyMap v -> [T.Text]
objectKeys = map Key.toText . KeyMap.keys

objectValues :: KeyMap.KeyMap v -> [v]
objectValues m = map snd $ KeyMap.toList m

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

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

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

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

adjustKey :: (v -> v) -> Key -> KeyMap.KeyMap v -> KeyMap.KeyMap v
adjustKey f k = runIdentity . KeyMap.alterF (Identity . fmap f) k

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

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

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

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

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

null :: KeyMap v -> Bool
null :: KeyMap v -> Bool
null = KeyMap v -> Bool
forall k v. HashMap k v -> Bool
HM.null

emptyObject :: KeyMap v
emptyObject :: KeyMap v
emptyObject = KeyMap v
forall k v. HashMap k v
HM.empty

singleton :: T.Text -> v -> HM.HashMap T.Text v
singleton :: Text -> v -> HashMap Text v
singleton = Text -> v -> HashMap Text v
forall k v. Hashable k => k -> v -> HashMap k v
HM.singleton

fromList :: [(T.Text, v)] -> KeyMap v
fromList :: [(Text, v)] -> KeyMap v
fromList = [(Text, v)] -> KeyMap v
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
HM.fromList

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

deleteKey :: T.Text -> HM.HashMap T.Text v -> HM.HashMap T.Text v
deleteKey :: Text -> HashMap Text v -> HashMap Text v
deleteKey = Text -> HashMap Text v -> HashMap Text v
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete

lookupKey :: T.Text -> HM.HashMap T.Text v -> Maybe v
lookupKey :: Text -> HashMap Text v -> Maybe v
lookupKey = Text -> HashMap Text v -> Maybe v
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup

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

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

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

insertKey :: T.Text -> v -> HM.HashMap T.Text v -> HM.HashMap T.Text v
insertKey :: Text -> v -> HashMap Text v -> HashMap Text v
insertKey = Text -> v -> HashMap Text v -> HashMap Text v
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert

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

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

adjustKey :: (v -> v) -> T.Text -> HM.HashMap T.Text v -> HM.HashMap T.Text v
adjustKey :: (v -> v) -> Text -> HashMap Text v -> HashMap Text v
adjustKey = (v -> v) -> Text -> HashMap Text v -> HashMap Text v
forall k v.
(Eq k, Hashable k) =>
(v -> v) -> k -> HashMap k v -> HashMap k v
HM.adjust

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

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

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

keyMapUnion :: HM.HashMap T.Text v -> HM.HashMap T.Text v -> HM.HashMap T.Text v
keyMapUnion :: HashMap Text v -> HashMap Text v -> HashMap Text v
keyMapUnion = HashMap Text v -> HashMap Text v -> HashMap Text v
forall k v.
(Eq k, Hashable k) =>
HashMap k v -> HashMap k v -> HashMap k v
HM.union

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