module Rattletrap.Type.Dictionary ( Dictionary(..) , dictionaryLookup ) where import Rattletrap.Type.Common import Rattletrap.Type.Str import qualified Control.Monad as Monad import qualified Data.Aeson as Json import qualified Data.Aeson.Types as Json import qualified Data.Map as Map import qualified Data.Text as Text data Dictionary a = DictionaryElement Str a (Dictionary a) | DictionaryEnd Str deriving (Eq, Ord, Show) instance Json.FromJSON a => Json.FromJSON (Dictionary a) where parseJSON = Json.withObject "Dictionary" (\o -> do keys <- get o "keys" lastKey <- get o "last_key" value <- get o "value" Monad.foldM (\d k -> case Map.lookup k value of Nothing -> fail (unwords ["missing key", show k]) Just v -> pure (DictionaryElement (Str k) v d)) (DictionaryEnd lastKey) (reverse keys)) instance Json.ToJSON a => Json.ToJSON (Dictionary a) where toJSON d = Json.object [ pair "keys" (dictionaryKeys d) , pair "last_key" (dictionaryLastKey d) , pair "value" (dictionaryValue d) ] dictionaryKeys :: Dictionary a -> [Str] dictionaryKeys = fmap fst . toList dictionaryLastKey :: Dictionary a -> Str dictionaryLastKey x = case x of DictionaryElement _ _ y -> dictionaryLastKey y DictionaryEnd y -> y dictionaryLookup :: Str -> Dictionary a -> Maybe a dictionaryLookup k x = case x of DictionaryElement j v y -> if k == j then Just v else dictionaryLookup k y DictionaryEnd _ -> Nothing dictionaryValue :: Dictionary a -> Map Text a dictionaryValue = Map.mapKeys strValue . Map.fromList . toList get :: Json.FromJSON a => Json.Object -> String -> Json.Parser a get o k = o Json..: Text.pack k pair :: Json.ToJSON a => String -> a -> (Text, Json.Value) pair k v = (Text.pack k, Json.toJSON v) toList :: Dictionary a -> [(Str, a)] toList x = case x of DictionaryElement k v y -> (k, v) : toList y DictionaryEnd _ -> []