module Hasql.Comms.RowDecoder
  ( RowDecoder,
    nullableColumn,
    nonNullableColumn,

    -- * Relations

    -- ** Expected OIDs
    toExpectedOids,

    -- ** Decoder
    Decoder,
    toDecoder,

    -- * Errors
    Error,
  )
where

import Hasql.Comms.RowReader qualified as RowReader
import Hasql.Platform.Prelude
import Hasql.Pq qualified as Pq

-- * RowDecoder

data RowDecoder a
  = RowDecoder
      [Maybe Pq.Oid]
      (RowReader.RowReader a)
  deriving stock ((forall a b. (a -> b) -> RowDecoder a -> RowDecoder b)
-> (forall a b. a -> RowDecoder b -> RowDecoder a)
-> Functor RowDecoder
forall a b. a -> RowDecoder b -> RowDecoder a
forall a b. (a -> b) -> RowDecoder a -> RowDecoder b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> RowDecoder a -> RowDecoder b
fmap :: forall a b. (a -> b) -> RowDecoder a -> RowDecoder b
$c<$ :: forall a b. a -> RowDecoder b -> RowDecoder a
<$ :: forall a b. a -> RowDecoder b -> RowDecoder a
Functor)

instance Applicative RowDecoder where
  pure :: forall a. a -> RowDecoder a
pure a
a = [Maybe Oid] -> RowReader a -> RowDecoder a
forall a. [Maybe Oid] -> RowReader a -> RowDecoder a
RowDecoder [] (a -> RowReader a
forall a. a -> RowReader a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a)
  RowDecoder [Maybe Oid]
lOids RowReader (a -> b)
lDec <*> :: forall a b. RowDecoder (a -> b) -> RowDecoder a -> RowDecoder b
<*> RowDecoder [Maybe Oid]
rOids RowReader a
rDec =
    [Maybe Oid] -> RowReader b -> RowDecoder b
forall a. [Maybe Oid] -> RowReader a -> RowDecoder a
RowDecoder ([Maybe Oid]
lOids [Maybe Oid] -> [Maybe Oid] -> [Maybe Oid]
forall a. Semigroup a => a -> a -> a
<> [Maybe Oid]
rOids) (RowReader (a -> b)
lDec RowReader (a -> b) -> RowReader a -> RowReader b
forall a b. RowReader (a -> b) -> RowReader a -> RowReader b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> RowReader a
rDec)

instance Filterable RowDecoder where
  mapMaybe :: forall a b. (a -> Maybe b) -> RowDecoder a -> RowDecoder b
mapMaybe a -> Maybe b
fn (RowDecoder [Maybe Oid]
oids RowReader a
dec) =
    [Maybe Oid] -> RowReader b -> RowDecoder b
forall a. [Maybe Oid] -> RowReader a -> RowDecoder a
RowDecoder [Maybe Oid]
oids ((a -> Maybe b) -> RowReader a -> RowReader b
forall a b. (a -> Maybe b) -> RowReader a -> RowReader b
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe a -> Maybe b
fn RowReader a
dec)

-- * Functions

-- |
-- Next value, decoded using the provided value decoder.
{-# INLINE nullableColumn #-}
nullableColumn :: Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder (Maybe a)
nullableColumn :: forall a.
Maybe Word32
-> (ByteString -> Either Text a) -> RowDecoder (Maybe a)
nullableColumn Maybe Word32
oid ByteString -> Either Text a
decoder =
  [Maybe Oid] -> RowReader (Maybe a) -> RowDecoder (Maybe a)
forall a. [Maybe Oid] -> RowReader a -> RowDecoder a
RowDecoder
    [CUInt -> Oid
Pq.Oid (CUInt -> Oid) -> (Word32 -> CUInt) -> Word32 -> Oid
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
. Word32 -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Oid) -> Maybe Word32 -> Maybe Oid
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Word32
oid]
    ((ByteString -> Either Text a) -> RowReader (Maybe a)
forall a. (ByteString -> Either Text a) -> RowReader (Maybe a)
RowReader.nullableColumn ByteString -> Either Text a
decoder)

-- |
-- Next value, decoded using the provided value decoder.
{-# INLINE nonNullableColumn #-}
nonNullableColumn :: Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder a
nonNullableColumn :: forall a.
Maybe Word32 -> (ByteString -> Either Text a) -> RowDecoder a
nonNullableColumn Maybe Word32
oid ByteString -> Either Text a
decoder =
  [Maybe Oid] -> RowReader a -> RowDecoder a
forall a. [Maybe Oid] -> RowReader a -> RowDecoder a
RowDecoder
    [CUInt -> Oid
Pq.Oid (CUInt -> Oid) -> (Word32 -> CUInt) -> Word32 -> Oid
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
. Word32 -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Oid) -> Maybe Word32 -> Maybe Oid
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Word32
oid]
    ((ByteString -> Either Text a) -> RowReader a
forall a. (ByteString -> Either Text a) -> RowReader a
RowReader.nonNullableColumn ByteString -> Either Text a
decoder)

-- * Relations

-- ** Expected OIDs

toExpectedOids :: RowDecoder a -> [Maybe Pq.Oid]
toExpectedOids :: forall a. RowDecoder a -> [Maybe Oid]
toExpectedOids (RowDecoder [Maybe Oid]
oids RowReader a
_) = [Maybe Oid]
oids

-- ** Decoder

type Decoder a = Pq.Result -> Pq.Row -> IO (Either Error a)

toDecoder :: RowDecoder a -> Decoder a
toDecoder :: forall a. RowDecoder a -> Decoder a
toDecoder (RowDecoder [Maybe Oid]
_ RowReader a
dec) Result
result Row
row =
  RowReader a -> Result -> Row -> IO (Either Error a)
forall a. RowReader a -> Result -> Row -> IO (Either Error a)
RowReader.toHandler RowReader a
dec Result
result Row
row

-- * Errors

type Error = RowReader.Error