{-# language OverloadedStrings #-}
{-# language StandaloneKindSignatures #-}

module Rel8.Type.JSONBEncoded
  ( JSONBEncoded(..)
  )
where

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

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

-- hasql
import qualified Hasql.Decoders as Hasql

-- rel8
import Rel8.Type ( DBType(..) )
import Rel8.Type.Decoder (Decoder (..))
import Rel8.Type.Information ( TypeInformation(..) )

-- text
import Data.Text ( pack )


-- | Like 'Rel8.JSONEncoded', but works for @jsonb@ columns.
type JSONBEncoded :: Type -> Type
newtype JSONBEncoded a = JSONBEncoded { forall a. JSONBEncoded a -> a
fromJSONBEncoded :: a }
  deriving (Int -> JSONBEncoded a -> ShowS
[JSONBEncoded a] -> ShowS
JSONBEncoded a -> String
(Int -> JSONBEncoded a -> ShowS)
-> (JSONBEncoded a -> String)
-> ([JSONBEncoded a] -> ShowS)
-> Show (JSONBEncoded a)
forall a. Show a => Int -> JSONBEncoded a -> ShowS
forall a. Show a => [JSONBEncoded a] -> ShowS
forall a. Show a => JSONBEncoded a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> JSONBEncoded a -> ShowS
showsPrec :: Int -> JSONBEncoded a -> ShowS
$cshow :: forall a. Show a => JSONBEncoded a -> String
show :: JSONBEncoded a -> String
$cshowList :: forall a. Show a => [JSONBEncoded a] -> ShowS
showList :: [JSONBEncoded a] -> ShowS
Show, JSONBEncoded a -> JSONBEncoded a -> Bool
(JSONBEncoded a -> JSONBEncoded a -> Bool)
-> (JSONBEncoded a -> JSONBEncoded a -> Bool)
-> Eq (JSONBEncoded a)
forall a. Eq a => JSONBEncoded a -> JSONBEncoded a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => JSONBEncoded a -> JSONBEncoded a -> Bool
== :: JSONBEncoded a -> JSONBEncoded a -> Bool
$c/= :: forall a. Eq a => JSONBEncoded a -> JSONBEncoded a -> Bool
/= :: JSONBEncoded a -> JSONBEncoded a -> Bool
Eq, Eq (JSONBEncoded a)
Eq (JSONBEncoded a) =>
(JSONBEncoded a -> JSONBEncoded a -> Ordering)
-> (JSONBEncoded a -> JSONBEncoded a -> Bool)
-> (JSONBEncoded a -> JSONBEncoded a -> Bool)
-> (JSONBEncoded a -> JSONBEncoded a -> Bool)
-> (JSONBEncoded a -> JSONBEncoded a -> Bool)
-> (JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a)
-> (JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a)
-> Ord (JSONBEncoded a)
JSONBEncoded a -> JSONBEncoded a -> Bool
JSONBEncoded a -> JSONBEncoded a -> Ordering
JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (JSONBEncoded a)
forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Bool
forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Ordering
forall a.
Ord a =>
JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a
$ccompare :: forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Ordering
compare :: JSONBEncoded a -> JSONBEncoded a -> Ordering
$c< :: forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Bool
< :: JSONBEncoded a -> JSONBEncoded a -> Bool
$c<= :: forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Bool
<= :: JSONBEncoded a -> JSONBEncoded a -> Bool
$c> :: forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Bool
> :: JSONBEncoded a -> JSONBEncoded a -> Bool
$c>= :: forall a. Ord a => JSONBEncoded a -> JSONBEncoded a -> Bool
>= :: JSONBEncoded a -> JSONBEncoded a -> Bool
$cmax :: forall a.
Ord a =>
JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a
max :: JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a
$cmin :: forall a.
Ord a =>
JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a
min :: JSONBEncoded a -> JSONBEncoded a -> JSONBEncoded a
Ord)

instance (FromJSON a, ToJSON a) => DBType (JSONBEncoded a) where
  typeInformation :: TypeInformation (JSONBEncoded a)
typeInformation = TypeInformation
    { encode :: JSONBEncoded a -> PrimExpr
encode = TypeInformation Value -> Value -> PrimExpr
forall a. TypeInformation a -> a -> PrimExpr
encode TypeInformation Value
forall a. DBType a => TypeInformation a
typeInformation (Value -> PrimExpr)
-> (JSONBEncoded a -> Value) -> JSONBEncoded a -> PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Value
forall a. ToJSON a => a -> Value
toJSON (a -> Value) -> (JSONBEncoded a -> a) -> JSONBEncoded a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JSONBEncoded a -> a
forall a. JSONBEncoded a -> a
fromJSONBEncoded
    , decode :: Decoder (JSONBEncoded a)
decode =
        Decoder
          { binary :: Value (JSONBEncoded a)
binary = (Value -> Either Text (JSONBEncoded a))
-> Value Value -> Value (JSONBEncoded a)
forall a b. (a -> Either Text b) -> Value a -> Value b
Hasql.refine ((String -> Text)
-> Either String (JSONBEncoded a) -> Either Text (JSONBEncoded a)
forall a b c. (a -> b) -> Either a c -> Either b c
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first String -> Text
pack (Either String (JSONBEncoded a) -> Either Text (JSONBEncoded a))
-> (Value -> Either String (JSONBEncoded a))
-> Value
-> Either Text (JSONBEncoded a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> JSONBEncoded a)
-> Either String a -> Either String (JSONBEncoded a)
forall a b. (a -> b) -> Either String a -> Either String b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> JSONBEncoded a
forall a. a -> JSONBEncoded a
JSONBEncoded (Either String a -> Either String (JSONBEncoded a))
-> (Value -> Either String a)
-> Value
-> Either String (JSONBEncoded a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Value -> Parser a) -> Value -> Either String a
forall a b. (a -> Parser b) -> a -> Either String b
parseEither Value -> Parser a
forall a. FromJSON a => Value -> Parser a
parseJSON) Value Value
Hasql.jsonb
          , parser :: Parser (JSONBEncoded a)
parser = (a -> JSONBEncoded a)
-> Either String a -> Either String (JSONBEncoded a)
forall a b. (a -> b) -> Either String a -> Either String b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> JSONBEncoded a
forall a. a -> JSONBEncoded a
JSONBEncoded (Either String a -> Either String (JSONBEncoded a))
-> (ByteString -> Either String a) -> Parser (JSONBEncoded a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
eitherDecodeStrict
          , delimiter :: Char
delimiter = Char
','
          }
    , typeName :: TypeName
typeName = TypeName
"jsonb"
    }