{-# LANGUAGE CPP #-}

-- | This module provides wrappers for compatibility between versions of @aeson@
-- prior to and after 2.0.  It is not necessarily stable.
--
module Data.API.JSON.Compat
    ( Key
    , KeyMap

    , lookupKey
    , listToObject
    , objectToList
    , matchSingletonObject
    , singletonObject
    , insertKey
    , deleteKey
    , objectToMap
    , mapToObject
    , traverseObjectWithKey
    , adjustObject

    , fieldNameToKey
    , keyToFieldName
    , textToKey
    , keyToText
    ) where

import           Data.API.Types

import qualified Data.Map.Strict                as Map
import qualified Data.Text                      as T

#if MIN_VERSION_aeson(2,0,0)

import           Data.Aeson.Key (Key)
import qualified Data.Aeson.Key                 as Key
import           Data.Aeson.KeyMap (KeyMap)
import qualified Data.Aeson.KeyMap              as KeyMap

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

listToObject :: [(T.Text, a)] -> KeyMap a
listToObject :: forall a. [(Text, a)] -> KeyMap a
listToObject = forall v. [(Key, v)] -> KeyMap v
KeyMap.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (\ (Text
x, a
y) -> (Text -> Key
Key.fromText Text
x, a
y))

objectToList :: KeyMap a -> [(T.Text, a)]
objectToList :: forall a. KeyMap a -> [(Text, a)]
objectToList = forall a b. (a -> b) -> [a] -> [b]
map (\ (Key
x, a
y) -> (Key -> Text
Key.toText Key
x, a
y)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall v. KeyMap v -> [(Key, v)]
KeyMap.toList

matchSingletonObject :: KeyMap a -> Maybe (T.Text, a)
matchSingletonObject :: forall a. KeyMap a -> Maybe (Text, a)
matchSingletonObject KeyMap a
km = case forall a. KeyMap a -> [(Text, a)]
objectToList KeyMap a
km of
                            [(Text
k, a
v)] -> forall a. a -> Maybe a
Just (Text
k, a
v)
                            [(Text, a)]
_        -> forall a. Maybe a
Nothing

singletonObject :: T.Text -> a -> KeyMap a
singletonObject :: forall a. Text -> a -> KeyMap a
singletonObject Text
k = forall v. Key -> v -> KeyMap v
KeyMap.singleton (Text -> Key
Key.fromText Text
k)

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

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

objectToMap :: KeyMap a -> Map.Map T.Text a
objectToMap :: forall a. KeyMap a -> Map Text a
objectToMap = forall a. KeyMap a -> Map Text a
KeyMap.toMapText

mapToObject :: Map.Map T.Text a -> KeyMap a
mapToObject :: forall a. Map Text a -> KeyMap a
mapToObject = forall a. Map Text a -> KeyMap a
KeyMap.fromMapText

traverseObjectWithKey :: Applicative f => (T.Text -> v1 -> f v2) -> KeyMap v1 -> f (KeyMap v2)
traverseObjectWithKey :: forall (f :: * -> *) v1 v2.
Applicative f =>
(Text -> v1 -> f v2) -> KeyMap v1 -> f (KeyMap v2)
traverseObjectWithKey Text -> v1 -> f v2
f = forall (f :: * -> *) v1 v2.
Applicative f =>
(Key -> v1 -> f v2) -> KeyMap v1 -> f (KeyMap v2)
KeyMap.traverseWithKey (\ Key
k -> Text -> v1 -> f v2
f (Key -> Text
Key.toText Key
k))

fieldNameToKey :: FieldName -> Key
fieldNameToKey :: FieldName -> Key
fieldNameToKey = Text -> Key
Key.fromText forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldName -> Text
_FieldName

textToKey :: T.Text -> Key
textToKey :: Text -> Key
textToKey = Text -> Key
Key.fromText

keyToFieldName :: Key -> FieldName
keyToFieldName :: Key -> FieldName
keyToFieldName = Text -> FieldName
FieldName forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> Text
Key.toText

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

adjustObject :: (v -> v) -> Key -> KeyMap v -> KeyMap v
adjustObject :: forall v. (v -> v) -> Key -> KeyMap v -> KeyMap v
adjustObject v -> v
f Key
k KeyMap v
m = case forall v. Key -> KeyMap v -> Maybe v
KeyMap.lookup Key
k KeyMap v
m of
                       Maybe v
Nothing -> KeyMap v
m
                       Just v
v  -> forall v. Key -> v -> KeyMap v -> KeyMap v
KeyMap.insert Key
k (v -> v
f v
v) KeyMap v
m

#else

import qualified Data.HashMap.Strict as HMap

type Key = T.Text

type KeyMap = HMap.HashMap Key

lookupKey :: T.Text -> KeyMap a -> Maybe a
lookupKey = HMap.lookup

listToObject :: [(T.Text, a)] -> KeyMap a
listToObject = HMap.fromList

objectToList :: KeyMap a -> [(T.Text, a)]
objectToList = HMap.toList

matchSingletonObject :: KeyMap a -> Maybe (T.Text, a)
matchSingletonObject km = case objectToList km of
                            [(k, v)] -> Just (k, v)
                            _        -> Nothing

singletonObject :: T.Text -> a -> KeyMap a
singletonObject = HMap.singleton

insertKey :: T.Text -> a -> KeyMap a -> KeyMap a
insertKey = HMap.insert

deleteKey :: T.Text -> KeyMap a -> KeyMap a
deleteKey = HMap.delete

objectToMap :: KeyMap a -> Map.Map T.Text a
objectToMap = Map.fromList . HMap.toList

mapToObject :: Map.Map T.Text a -> KeyMap a
mapToObject = HMap.fromList . Map.toList

traverseObjectWithKey :: Applicative f => (T.Text -> v1 -> f v2) -> KeyMap v1 -> f (KeyMap v2)
traverseObjectWithKey = HMap.traverseWithKey

adjustObject :: (v -> v) -> Key -> KeyMap v -> KeyMap v
adjustObject = HMap.adjust

fieldNameToKey :: FieldName -> Key
fieldNameToKey = _FieldName

keyToFieldName :: Key -> FieldName
keyToFieldName = FieldName

textToKey :: T.Text -> Key
textToKey = id

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

#endif