{-# language StandaloneKindSignatures #-}

module Rel8.Type.JSONEncoded ( JSONEncoded(..) ) where

-- aeson
import Data.Aeson ( FromJSON, ToJSON, parseJSON, toJSON )
import Data.Aeson.Types ( parseEither )

-- base
import Data.Kind ( Type )
import Prelude

-- rel8
import Rel8.Type ( DBType(..) )
import Rel8.Type.Information ( parseTypeInformation )


-- | A deriving-via helper type for column types that store a Haskell value
-- using a JSON encoding described by @aeson@'s 'ToJSON' and 'FromJSON' type
-- classes.
type JSONEncoded :: Type -> Type
newtype JSONEncoded a = JSONEncoded { forall a. JSONEncoded a -> a
fromJSONEncoded :: a }


instance (FromJSON a, ToJSON a) => DBType (JSONEncoded a) where
  typeInformation :: TypeInformation (JSONEncoded a)
typeInformation = forall a b.
(a -> Either String b)
-> (b -> a) -> TypeInformation a -> TypeInformation b
parseTypeInformation Value -> Either String (JSONEncoded a)
f JSONEncoded a -> Value
g forall a. DBType a => TypeInformation a
typeInformation
    where
      f :: Value -> Either String (JSONEncoded a)
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. a -> JSONEncoded a
JSONEncoded forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> Parser b) -> a -> Either String b
parseEither forall a. FromJSON a => Value -> Parser a
parseJSON
      g :: JSONEncoded a -> Value
g = forall a. ToJSON a => a -> Value
toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. JSONEncoded a -> a
fromJSONEncoded