{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Hercules.Formats.Common where import Control.Monad import Data.Aeson ( (.:), (.:?), ) import Data.Aeson.Types ( Object, Parser, Value, withObject, ) import Data.Coerce (coerce) import qualified Data.List import Data.Text (Text) import qualified Data.Text as T import Prelude withKind :: Text -> (Object -> Parser a) -> Value -> Parser a withKind k f = withObject (T.unpack k) $ \o -> do k' <- o .: "kind" when (k' /= k) $ fail $ "kind field must be " <> show k <> ", not " <> show k' f o newtype VersionParser a = VersionParser { fromVersionParser :: (Maybe Text, Object -> Parser a) } deriving (Functor) noVersion :: (Object -> Parser a) -> VersionParser a noVersion = VersionParser . (Nothing,) version :: Text -> (Object -> Parser a) -> VersionParser a version t p = VersionParser (Just t, p) withVersions :: forall a. [VersionParser a] -> Object -> Parser a withVersions vps' o = do let vps = coerce vps' :: [(Maybe Text, Object -> Parser a)] v <- o .:? "apiVersion" case Data.List.lookup v vps of Just p -> p o Nothing -> let vs = map fst vps in case vs of [Nothing] -> fail "Unexpected apiVersion field. " _ -> fail $ "Expected apiVersion to be one of " <> unwords (map showVersion vs) where showVersion Nothing = "" showVersion (Just t) = show t