module Sqel.Codec.Sum where
import Data.Functor.Contravariant.Divisible (choose)
import Data.Functor.Invariant (Invariant (invmap))
import Exon (exon)
import Generics.SOP (
All2,
HIndex (hindex),
I,
NP (Nil, (:*)),
NS (S, Z),
SListI,
SListI2,
SOP (SOP),
Top,
hcfoldMap,
hctraverse_,
hmap,
hsequence,
unSOP,
)
import Generics.SOP.GGP (gfrom, gto)
import Hasql.Decoders (Row)
import qualified Hasql.Encoders as Encoders
import qualified Hasql.Encoders as Encoder
import Hasql.Encoders (Params)
import Lens.Micro ((^.))
import Lens.Micro.Extras (view)
import qualified Sqel.Data.Codec as Codec
import Sqel.Data.Codec (Codec (Codec), Decoder (Decoder), Encoder (Encoder), FullCodec)
import Sqel.Data.Dd (ConCol (ConCol, unConCol))
import Sqel.SOP.Constraint (ConstructSOP, ReifySOP)
import Sqel.Codec.Product (prodParams)
unconsNS ::
NS (NP I) (ds : dss) ->
Either (NP I ds) (NS (NP I) dss)
unconsNS :: forall (ds :: [*]) (dss :: [[*]]).
NS (NP I) (ds : dss) -> Either (NP I ds) (NS (NP I) dss)
unconsNS = \case
Z NP I x
x -> forall a b. a -> Either a b
Left NP I x
x
S NS (NP I) xs
x -> forall a b. b -> Either a b
Right NS (NP I) xs
x
newtype ConB b as =
ConB { forall (b :: * -> *) (as :: [*]). ConB b as -> b (NP I as)
unConB :: b (NP I as) }
readNull ::
∀ as .
Decoder (NP I as) ->
Row ()
readNull :: forall (as :: [*]). Decoder (NP I as) -> Row ()
readNull Decoder (NP I as)
rs =
Decoder (NP I as)
rs forall s a. s -> Getting a s a -> a
^. forall a. IsLabel "decodeNulls" a => a
#decodeNulls
readNulls ::
∀ ass .
SListI2 ass =>
NP (ConB Decoder) ass ->
Row ()
readNulls :: forall (ass :: [[*]]).
SListI2 ass =>
NP (ConB Decoder) ass -> Row ()
readNulls NP (ConB Decoder) ass
cons =
forall k l (h :: (k -> *) -> l -> *) (c :: k -> Constraint)
(xs :: l) (g :: * -> *) (proxy :: (k -> Constraint) -> *)
(f :: k -> *).
(HTraverse_ h, AllN h c xs, Applicative g) =>
proxy c -> (forall (a :: k). c a => f a -> g ()) -> h f xs -> g ()
hctraverse_ (forall {k} (t :: k). Proxy t
Proxy @SListI) (forall (as :: [*]). Decoder (NP I as) -> Row ()
readNull forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: * -> *) (as :: [*]). ConB b as -> b (NP I as)
unConB) NP (ConB Decoder) ass
cons
sumRows ::
All2 Top ass =>
NP (ConB Decoder) ass ->
Int64 ->
Row (NS (NP I) ass)
sumRows :: forall (ass :: [[*]]).
All2 Top ass =>
NP (ConB Decoder) ass -> Int64 -> Row (NS (NP I) ass)
sumRows (ConB Decoder (NP I x)
con :* NP (ConB Decoder) xs
cons) Int64
0 =
forall {k} (a :: k -> *) (x :: k) (xs :: [k]). a x -> NS a (x : xs)
Z forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Decoder (NP I x)
con forall s a. s -> Getting a s a -> a
^. forall a. IsLabel "decodeValue" a => a
#decodeValue) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall (ass :: [[*]]).
SListI2 ass =>
NP (ConB Decoder) ass -> Row ()
readNulls NP (ConB Decoder) xs
cons
sumRows (ConB Decoder (NP I x)
con :* NP (ConB Decoder) xs
cons) Int64
index = do
forall (as :: [*]). Decoder (NP I as) -> Row ()
readNull Decoder (NP I x)
con
forall {k} (a :: k -> *) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
S forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (ass :: [[*]]).
All2 Top ass =>
NP (ConB Decoder) ass -> Int64 -> Row (NS (NP I) ass)
sumRows NP (ConB Decoder) xs
cons (Int64
index forall a. Num a => a -> a -> a
- Int64
1)
sumRows NP (ConB Decoder) ass
Nil Int64
index =
forall (m :: * -> *) a. MonadFail m => String -> m a
fail [exon|invalid index into sum type in database: #{show index}|]
ignoreEncoder :: Encoder.Value a -> Params b
ignoreEncoder :: forall a b. Value a -> Params b
ignoreEncoder Value a
v =
forall a b. a -> b -> a
const forall a. Maybe a
Nothing forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
>$< forall a. NullableOrNot Value a -> Params a
Encoders.param (forall (encoder :: * -> *) a.
encoder a -> NullableOrNot encoder (Maybe a)
Encoders.nullable Value a
v)
writeNull ::
∀ a as .
ConB Encoder as ->
Params a
writeNull :: forall a (as :: [*]). ConB Encoder as -> Params a
writeNull (ConB Encoder (NP I as)
enc) =
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
contramap forall (f :: * -> *). Applicative f => f ()
unit (Encoder (NP I as)
enc forall s a. s -> Getting a s a -> a
^. forall a. IsLabel "encodeNulls" a => a
#encodeNulls)
writeNulls ::
∀ a ass .
SListI2 ass =>
NP (ConB Encoder) ass ->
Params a
writeNulls :: forall a (ass :: [[*]]).
SListI2 ass =>
NP (ConB Encoder) ass -> Params a
writeNulls =
forall {k} {l} (h :: (k -> *) -> l -> *) (c :: k -> Constraint)
(xs :: l) m (proxy :: (k -> Constraint) -> *) (f :: k -> *).
(HTraverse_ h, AllN h c xs, Monoid m) =>
proxy c -> (forall (a :: k). c a => f a -> m) -> h f xs -> m
hcfoldMap (forall {k} (t :: k). Proxy t
Proxy @SListI) forall a (as :: [*]). ConB Encoder as -> Params a
writeNull
sumParams ::
All2 Top ass =>
NP (ConB Encoder) ass ->
Params (NS (NP I) ass)
sumParams :: forall (ass :: [[*]]).
All2 Top ass =>
NP (ConB Encoder) ass -> Params (NS (NP I) ass)
sumParams = \case
ConB Encoder x
con :* NP (ConB Encoder) xs
cons ->
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose forall (ds :: [*]) (dss :: [[*]]).
NS (NP I) (ds : dss) -> Either (NP I ds) (NS (NP I) dss)
unconsNS Params (NP I x)
inhabited Params (NS (NP I) xs)
uninhabited
where
inhabited :: Params (NP I x)
inhabited = (forall (b :: * -> *) (as :: [*]). ConB b as -> b (NP I as)
unConB ConB Encoder x
con) forall s a. s -> Getting a s a -> a
^. forall a. IsLabel "encodeValue" a => a
#encodeValue forall a. Semigroup a => a -> a -> a
<> forall a (ass :: [[*]]).
SListI2 ass =>
NP (ConB Encoder) ass -> Params a
writeNulls NP (ConB Encoder) xs
cons
uninhabited :: Params (NS (NP I) xs)
uninhabited = forall a (as :: [*]). ConB Encoder as -> Params a
writeNull ConB Encoder x
con forall a. Semigroup a => a -> a -> a
<> forall (ass :: [[*]]).
All2 Top ass =>
NP (ConB Encoder) ass -> Params (NS (NP I) ass)
sumParams NP (ConB Encoder) xs
cons
NP (ConB Encoder) ass
Nil ->
forall a. Monoid a => a
mempty
type WrapConB :: (Type -> Type) -> [[Type]] -> [Type] -> Constraint
class WrapConB b ass as where
wrapConB :: NP b as -> NP (ConB b) ass
instance WrapConB b '[] '[] where
wrapConB :: NP b '[] -> NP (ConB b) '[]
wrapConB NP b '[]
Nil = forall {k} (a :: k -> *). NP a '[]
Nil
instance (
Invariant b,
WrapConB b ass as
) => WrapConB b (as' : ass) (ConCol name record fields as' : as) where
wrapConB :: NP b (ConCol name record fields as' : as)
-> NP (ConB b) (as' : ass)
wrapConB (b x
b :* NP b xs
bs) =
forall (b :: * -> *) (as :: [*]). b (NP I as) -> ConB b as
ConB (forall (f :: * -> *) a b.
Invariant f =>
(a -> b) -> (b -> a) -> f a -> f b
invmap forall (name :: Symbol) (record :: Bool) (fields :: [ProductField])
(as :: [*]).
ConCol name record fields as -> NP I as
unConCol forall (name :: Symbol) (record :: Bool) (fields :: [ProductField])
(as :: [*]).
NP I as -> ConCol name record fields as
ConCol b x
b) forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* forall (b :: * -> *) (ass :: [[*]]) (as :: [*]).
WrapConB b ass as =>
NP b as -> NP (ConB b) ass
wrapConB NP b xs
bs
encodeValue ::
ConstructSOP a ass =>
Encoder Int64 ->
NP (ConB Encoder) ass ->
Params a
encodeValue :: forall a (ass :: [[*]]).
ConstructSOP a ass =>
Encoder Int64 -> NP (ConB Encoder) ass -> Params a
encodeValue (Encoder Params Int64
indexParams Params ()
_) NP (ConB Encoder) ass
wrapped =
forall {k} (f :: k -> *) (xss :: [[k]]). SOP f xss -> NS (NP f) xss
unSOP forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (GFrom a, Generic a) => a -> SOP I (GCode a)
gfrom forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
>$< (Params (NS (NP I) ass)
indexEncoder forall a. Semigroup a => a -> a -> a
<> forall (ass :: [[*]]).
All2 Top ass =>
NP (ConB Encoder) ass -> Params (NS (NP I) ass)
sumParams NP (ConB Encoder) ass
wrapped)
where
indexEncoder :: Params (NS (NP I) ass)
indexEncoder = (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k l (h :: (k -> *) -> l -> *) (f :: k -> *) (xs :: l).
HIndex h =>
h f xs -> Int
hindex) forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
>$< Params Int64
indexParams
type SumCodec :: (Type -> Type) -> Type -> [Type] -> Constraint
class SumCodec b a as where
sumCodec :: NP b as -> b a
instance (
ReifySOP a ass,
ConstructSOP a ass,
WrapConB FullCodec ass as
) => SumCodec FullCodec a (Int64 : as) where
sumCodec :: NP FullCodec (Int64 : as) -> FullCodec a
sumCodec (Codec Encoder x
index (Decoder Row x
indexRow Row ()
_) :* NP FullCodec xs
conCodecs) =
Codec {
$sel:decoder:Codec :: Decoder a
decoder = forall a. Row a -> Row () -> Decoder a
Decoder Row a
decodeValue forall (f :: * -> *). Applicative f => f ()
unit,
$sel:encoder:Codec :: Encoder a
encoder = forall a. Params a -> Params () -> Encoder a
Encoder (forall a (ass :: [[*]]).
ConstructSOP a ass =>
Encoder Int64 -> NP (ConB Encoder) ass -> Params a
encodeValue Encoder x
index (forall {k} {l} (h :: (k -> *) -> l -> *) (xs :: l) (f :: k -> *)
(f' :: k -> *).
(SListIN (Prod h) xs, HAp h) =>
(forall (a :: k). f a -> f' a) -> h f xs -> h f' xs
hmap (forall (b :: * -> *) (as :: [*]). b (NP I as) -> ConB b as
ConB forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. Getting a s a -> s -> a
view forall a. IsLabel "encoder" a => a
#encoder forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: * -> *) (as :: [*]). ConB b as -> b (NP I as)
unConB) NP (ConB FullCodec) ass
wrapped)) forall a. Monoid a => a
mempty
}
where
decodeValue :: Row a
decodeValue =
forall a. (GTo a, Generic a) => SOP I (GCode a) -> a
gto forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k (f :: k -> *) (xss :: [[k]]). NS (NP f) xss -> SOP f xss
SOP forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall (ass :: [[*]]).
All2 Top ass =>
NP (ConB Decoder) ass -> Int64 -> Row (NS (NP I) ass)
sumRows NP (ConB Decoder) ass
decs forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Row x
indexRow)
decs :: NP (ConB Decoder) ass
decs =
forall {k} {l} (h :: (k -> *) -> l -> *) (xs :: l) (f :: k -> *)
(f' :: k -> *).
(SListIN (Prod h) xs, HAp h) =>
(forall (a :: k). f a -> f' a) -> h f xs -> h f' xs
hmap (forall (b :: * -> *) (as :: [*]). b (NP I as) -> ConB b as
ConB forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. Getting a s a -> s -> a
view forall a. IsLabel "decoder" a => a
#decoder forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: * -> *) (as :: [*]). ConB b as -> b (NP I as)
unConB) NP (ConB FullCodec) ass
wrapped
wrapped :: NP (ConB FullCodec) ass
wrapped =
forall (b :: * -> *) (ass :: [[*]]) (as :: [*]).
WrapConB b ass as =>
NP b as -> NP (ConB b) ass
wrapConB NP FullCodec xs
conCodecs
instance (
ConstructSOP a ass,
WrapConB Encoder ass as
) => SumCodec Encoder a (Int64 : as) where
sumCodec :: NP Encoder (Int64 : as) -> Encoder a
sumCodec (Encoder x
index :* NP Encoder xs
conCodecs) =
forall a. Params a -> Params () -> Encoder a
Encoder (forall a (ass :: [[*]]).
ConstructSOP a ass =>
Encoder Int64 -> NP (ConB Encoder) ass -> Params a
encodeValue Encoder x
index NP (ConB Encoder) ass
wrapped) forall a. Monoid a => a
mempty
where
wrapped :: NP (ConB Encoder) ass
wrapped = forall (b :: * -> *) (ass :: [[*]]) (as :: [*]).
WrapConB b ass as =>
NP b as -> NP (ConB b) ass
wrapConB NP Encoder xs
conCodecs
type ConCodec :: (Type -> Type) -> [Type] -> Constraint
class ConCodec b as where
conCodec :: NP b as -> b (ConCol name record fields as)
instance SListI as => ConCodec FullCodec as where
conCodec :: forall (name :: Symbol) (record :: Bool)
(fields :: [ProductField]).
NP FullCodec as -> FullCodec (ConCol name record fields as)
conCodec NP FullCodec as
np =
Codec {
$sel:decoder:Codec :: Decoder (ConCol name record fields as)
decoder = forall (name :: Symbol) (record :: Bool) (fields :: [ProductField])
(as :: [*]).
NP I as -> ConCol name record fields as
ConCol forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {l} (h :: (* -> *) -> l -> *) (xs :: l) (f :: * -> *).
(SListIN h xs, SListIN (Prod h) xs, HSequence h, Applicative f) =>
h f xs -> f (h I xs)
hsequence (forall {k} {l} (h :: (k -> *) -> l -> *) (xs :: l) (f :: k -> *)
(f' :: k -> *).
(SListIN (Prod h) xs, HAp h) =>
(forall (a :: k). f a -> f' a) -> h f xs -> h f' xs
hmap (forall a s. Getting a s a -> s -> a
view forall a. IsLabel "decoder" a => a
#decoder) NP FullCodec as
np),
$sel:encoder:Codec :: Encoder (ConCol name record fields as)
encoder = forall (name :: Symbol) (record :: Bool) (fields :: [ProductField])
(as :: [*]).
ConCol name record fields as -> NP I as
unConCol forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
>$< forall (as :: [*]) (b :: * -> *).
(Contravariant b, forall x. Monoid (b x), All Top as) =>
NP b as -> b (NP I as)
prodParams (forall {k} {l} (h :: (k -> *) -> l -> *) (xs :: l) (f :: k -> *)
(f' :: k -> *).
(SListIN (Prod h) xs, HAp h) =>
(forall (a :: k). f a -> f' a) -> h f xs -> h f' xs
hmap (forall a s. Getting a s a -> s -> a
view forall a. IsLabel "encoder" a => a
#encoder) NP FullCodec as
np)
}
instance SListI as => ConCodec Encoder as where
conCodec :: forall (name :: Symbol) (record :: Bool)
(fields :: [ProductField]).
NP Encoder as -> Encoder (ConCol name record fields as)
conCodec NP Encoder as
np = forall (name :: Symbol) (record :: Bool) (fields :: [ProductField])
(as :: [*]).
ConCol name record fields as -> NP I as
unConCol forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
>$< forall (as :: [*]) (b :: * -> *).
(Contravariant b, forall x. Monoid (b x), All Top as) =>
NP b as -> b (NP I as)
prodParams NP Encoder as
np