module Hasql.Private.Encoders.Array where

import Hasql.Private.Prelude
import qualified PostgreSQL.Binary.Encoding as A
import qualified Hasql.Private.PTI as B
import qualified Text.Builder as C


data Array a =
  Array B.OID B.OID (Bool -> a -> A.Array) (a -> C.Builder)

instance Contravariant Array where
  contramap :: (a -> b) -> Array b -> Array a
contramap a -> b
fn (Array OID
valueOid OID
arrayOid Bool -> b -> Array
encoder b -> Builder
renderer) =
    OID -> OID -> (Bool -> a -> Array) -> (a -> Builder) -> Array a
forall a.
OID -> OID -> (Bool -> a -> Array) -> (a -> Builder) -> Array a
Array OID
valueOid OID
arrayOid (\ Bool
intDateTimes -> Bool -> b -> Array
encoder Bool
intDateTimes (b -> Array) -> (a -> b) -> a -> Array
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> b
fn) (b -> Builder
renderer (b -> Builder) -> (a -> b) -> a -> Builder
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> b
fn)

{-# INLINE value #-}
value :: B.OID -> B.OID -> (Bool -> a -> A.Encoding) -> (a -> C.Builder) -> Array a
value :: OID -> OID -> (Bool -> a -> Encoding) -> (a -> Builder) -> Array a
value OID
valueOID OID
arrayOID Bool -> a -> Encoding
encoder =
  OID -> OID -> (Bool -> a -> Array) -> (a -> Builder) -> Array a
forall a.
OID -> OID -> (Bool -> a -> Array) -> (a -> Builder) -> Array a
Array OID
valueOID OID
arrayOID (\Bool
params -> Encoding -> Array
A.encodingArray (Encoding -> Array) -> (a -> Encoding) -> a -> Array
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Bool -> a -> Encoding
encoder Bool
params)

{-# INLINE nullableValue #-}
nullableValue :: B.OID -> B.OID -> (Bool -> a -> A.Encoding) -> (a -> C.Builder) -> Array (Maybe a)
nullableValue :: OID
-> OID
-> (Bool -> a -> Encoding)
-> (a -> Builder)
-> Array (Maybe a)
nullableValue OID
valueOID OID
arrayOID Bool -> a -> Encoding
encoder a -> Builder
renderer =
  let
    maybeEncoder :: Bool -> Maybe a -> Array
maybeEncoder Bool
params =
      Array -> (a -> Array) -> Maybe a -> Array
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Array
A.nullArray (Encoding -> Array
A.encodingArray (Encoding -> Array) -> (a -> Encoding) -> a -> Array
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Bool -> a -> Encoding
encoder Bool
params)
    maybeRenderer :: Maybe a -> Builder
maybeRenderer =
      Builder -> (a -> Builder) -> Maybe a -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Builder
C.string String
"null") a -> Builder
renderer
    in OID
-> OID
-> (Bool -> Maybe a -> Array)
-> (Maybe a -> Builder)
-> Array (Maybe a)
forall a.
OID -> OID -> (Bool -> a -> Array) -> (a -> Builder) -> Array a
Array OID
valueOID OID
arrayOID Bool -> Maybe a -> Array
maybeEncoder Maybe a -> Builder
maybeRenderer

{-# INLINE dimension #-}
dimension :: (forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c
dimension :: (forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c
dimension forall a. (a -> b -> a) -> a -> c -> a
fold (Array OID
valueOID OID
arrayOID Bool -> b -> Array
elEncoder b -> Builder
elRenderer) =
  let
    encoder :: Bool -> c -> Array
encoder Bool
el =
      (forall a. (a -> b -> a) -> a -> c -> a)
-> (b -> Array) -> c -> Array
forall a c.
(forall b. (b -> a -> b) -> b -> c -> b)
-> (a -> Array) -> c -> Array
A.dimensionArray forall a. (a -> b -> a) -> a -> c -> a
fold (Bool -> b -> Array
elEncoder Bool
el)
    renderer :: c -> Builder
renderer c
els =
      let
        folded :: Builder
folded =
          let
            step :: Builder -> b -> Builder
step Builder
builder b
el =
              if Builder -> Bool
C.null Builder
builder
                then Char -> Builder
C.char Char
'[' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> b -> Builder
elRenderer b
el
                else Builder
builder Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
C.string String
", " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> b -> Builder
elRenderer b
el
            in (Builder -> b -> Builder) -> Builder -> c -> Builder
forall a. (a -> b -> a) -> a -> c -> a
fold Builder -> b -> Builder
step Builder
forall a. Monoid a => a
mempty c
els
        in if Builder -> Bool
C.null Builder
folded
          then String -> Builder
C.string String
"[]"
          else Builder
folded Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
C.char Char
']'
    in OID -> OID -> (Bool -> c -> Array) -> (c -> Builder) -> Array c
forall a.
OID -> OID -> (Bool -> a -> Array) -> (a -> Builder) -> Array a
Array OID
valueOID OID
arrayOID Bool -> c -> Array
encoder c -> Builder
renderer