module Hasql.Codecs.Decoders
  ( -- * Nullability
    NullableOrNot.NullableOrNot (..),
    NullableOrNot.nonNullable,
    NullableOrNot.nullable,

    -- * Value
    Value.Value (..),
    Value.bool,
    Value.int2,
    Value.int4,
    Value.int8,
    Value.float4,
    Value.float8,
    Value.numeric,
    Value.char,
    Value.text,
    Value.varchar,
    Value.bpchar,
    Value.bytea,
    Value.date,
    Value.timestamp,
    Value.timestamptz,
    Value.time,
    Value.timetz,
    Value.interval,
    Value.uuid,
    Value.inet,
    Value.macaddr,
    Value.json,
    Value.jsonBytes,
    Value.jsonb,
    Value.jsonbBytes,
    Value.int4range,
    Value.int8range,
    Value.numrange,
    Value.tsrange,
    Value.tstzrange,
    Value.daterange,
    Value.int4multirange,
    Value.int8multirange,
    Value.nummultirange,
    Value.tsmultirange,
    Value.tstzmultirange,
    Value.datemultirange,
    Value.citext,
    array,
    listArray,
    vectorArray,
    composite,
    record,
    Value.hstore,
    Value.enum,
    Value.custom,
    Value.refine,

    -- * Array
    Array.Array,
    Array.dimension,
    Array.element,

    -- * Composite
    Composite.Composite (..),
    Composite.field,
  )
where

import Data.Vector.Generic qualified as GenericVector
import Hasql.Codecs.Decoders.Array qualified as Array
import Hasql.Codecs.Decoders.Composite qualified as Composite
import Hasql.Codecs.Decoders.NullableOrNot qualified as NullableOrNot
import Hasql.Codecs.Decoders.Value qualified as Value
import Hasql.Codecs.TypeInfo qualified as TypeInfo
import Hasql.Platform.Prelude

-- * Value

-- |
-- Lift an 'Array.Array' decoder to a 'Value.Value' decoder.
{-# INLINEABLE array #-}
array :: Array.Array a -> Value.Value a
array :: forall a. Array a -> Value a
array Array a
decoder = Maybe Text
-> Text
-> Maybe Word32
-> Maybe Word32
-> Word
-> RequestingOid (Value a)
-> Value a
forall a.
Maybe Text
-> Text
-> Maybe Word32
-> Maybe Word32
-> Word
-> RequestingOid (Value a)
-> Value a
Value.Value (Array a -> Maybe Text
forall a. Array a -> Maybe Text
Array.toSchema Array a
decoder) (Array a -> Text
forall a. Array a -> Text
Array.toTypeName Array a
decoder) (Array a -> Maybe Word32
forall a. Array a -> Maybe Word32
Array.toBaseOid Array a
decoder) (Array a -> Maybe Word32
forall a. Array a -> Maybe Word32
Array.toArrayOid Array a
decoder) (Array a -> Word
forall a. Array a -> Word
Array.toDimensionality Array a
decoder) (Array a -> RequestingOid (Value a)
forall a. Array a -> RequestingOid (Value a)
Array.toValueDecoder Array a
decoder)

-- |
-- Lift a value decoder of element into a unidimensional array decoder producing a list.
--
-- This function is merely a shortcut to the following expression:
--
-- @
-- ('array' . 'dimension' Control.Monad.'replicateM' . 'element')
-- @
--
-- Please notice that in case of multidimensional arrays nesting 'listArray' decoder
-- won't work. You have to explicitly construct the array decoder using 'array'.
{-# INLINE listArray #-}
listArray :: NullableOrNot.NullableOrNot Value.Value element -> Value.Value [element]
listArray :: forall element. NullableOrNot Value element -> Value [element]
listArray = Array [element] -> Value [element]
forall a. Array a -> Value a
array (Array [element] -> Value [element])
-> (NullableOrNot Value element -> Array [element])
-> NullableOrNot Value element
-> Value [element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (forall (m :: * -> *). Monad m => Int -> m element -> m [element])
-> Array element -> Array [element]
forall a b.
(forall (m :: * -> *). Monad m => Int -> m a -> m b)
-> Array a -> Array b
Array.dimension Int -> m element -> m [element]
forall (m :: * -> *). Monad m => Int -> m element -> m [element]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM (Array element -> Array [element])
-> (NullableOrNot Value element -> Array element)
-> NullableOrNot Value element
-> Array [element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NullableOrNot Value element -> Array element
forall a. NullableOrNot Value a -> Array a
Array.element

-- |
-- Lift a value decoder of element into a unidimensional array decoder producing a generic vector.
--
-- This function is merely a shortcut to the following expression:
--
-- @
-- ('array' . 'dimension' Data.Vector.Generic.'GenericVector.replicateM' . 'element')
-- @
--
-- Please notice that in case of multidimensional arrays nesting 'vectorArray' decoder
-- won't work. You have to explicitly construct the array decoder using 'array'.
{-# INLINE vectorArray #-}
vectorArray :: (GenericVector.Vector vector element) => NullableOrNot.NullableOrNot Value.Value element -> Value.Value (vector element)
vectorArray :: forall (vector :: * -> *) element.
Vector vector element =>
NullableOrNot Value element -> Value (vector element)
vectorArray = Array (vector element) -> Value (vector element)
forall a. Array a -> Value a
array (Array (vector element) -> Value (vector element))
-> (NullableOrNot Value element -> Array (vector element))
-> NullableOrNot Value element
-> Value (vector element)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (forall (m :: * -> *).
 Monad m =>
 Int -> m element -> m (vector element))
-> Array element -> Array (vector element)
forall a b.
(forall (m :: * -> *). Monad m => Int -> m a -> m b)
-> Array a -> Array b
Array.dimension Int -> m element -> m (vector element)
forall (m :: * -> *).
Monad m =>
Int -> m element -> m (vector element)
forall (m :: * -> *) (v :: * -> *) a.
(Monad m, Vector v a) =>
Int -> m a -> m (v a)
GenericVector.replicateM (Array element -> Array (vector element))
-> (NullableOrNot Value element -> Array element)
-> NullableOrNot Value element
-> Array (vector element)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. NullableOrNot Value element -> Array element
forall a. NullableOrNot Value a -> Array a
Array.element

-- |
-- Lift a 'Composite.Composite' decoder to a 'Value.Value' decoder for named composite types.
--
-- This function is for named composite types where the type name is known.
-- For anonymous composite types (like those created with ROW constructor),
-- use 'record' instead.
{-# INLINEABLE composite #-}
composite :: Maybe Text -> Text -> Composite.Composite a -> Value.Value a
composite :: forall a. Maybe Text -> Text -> Composite a -> Value a
composite Maybe Text
schema Text
typeName Composite a
composite =
  Maybe Text
-> Text
-> Maybe Word32
-> Maybe Word32
-> Word
-> RequestingOid (Value a)
-> Value a
forall a.
Maybe Text
-> Text
-> Maybe Word32
-> Maybe Word32
-> Word
-> RequestingOid (Value a)
-> Value a
Value.Value
    Maybe Text
schema
    Text
typeName
    Maybe Word32
forall a. Maybe a
Nothing
    Maybe Word32
forall a. Maybe a
Nothing
    Word
0
    (Composite a -> RequestingOid (Value a)
forall a. Composite a -> RequestingOid (Value a)
Composite.toValueDecoder Composite a
composite)

-- |
-- Lift a 'Composite.Composite' decoder to a 'Value.Value' decoder for unnamed composite types.
--
-- This is useful for decoding anonymous composites (like those created with ROW constructor)
-- where no type name is required. Postgres will handle the type automatically.
{-# INLINEABLE record #-}
record :: Composite.Composite a -> Value.Value a
record :: forall a. Composite a -> Value a
record Composite a
composite =
  Maybe Text
-> Text
-> Maybe Word32
-> Maybe Word32
-> Word
-> RequestingOid (Value a)
-> Value a
forall a.
Maybe Text
-> Text
-> Maybe Word32
-> Maybe Word32
-> Word
-> RequestingOid (Value a)
-> Value a
Value.Value
    Maybe Text
forall a. Maybe a
Nothing
    Text
"record"
    (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just (TypeInfo -> Word32
TypeInfo.toBaseOid TypeInfo
typeInfo))
    (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just (TypeInfo -> Word32
TypeInfo.toArrayOid TypeInfo
typeInfo))
    Word
0
    (Composite a -> RequestingOid (Value a)
forall a. Composite a -> RequestingOid (Value a)
Composite.toValueDecoder Composite a
composite)
  where
    typeInfo :: TypeInfo
typeInfo = TypeInfo
TypeInfo.record