{-# LANGUAGE StandaloneDeriving, DerivingVia, TypeApplications, TypeSynonymInstances, ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
--Serialise instances for ProjectM36.Base data types- orphan instance city
module ProjectM36.Serialise.Base where
import Codec.Winery hiding (Schema)
import Codec.Winery.Internal
import Control.Monad
import ProjectM36.Base
import ProjectM36.MerkleHash
import ProjectM36.Relation
import ProjectM36.Tuple
import ProjectM36.TupleSet
import Data.UUID
import Data.Proxy
import Data.Word
import ProjectM36.Attribute as A
import qualified Data.Vector as V
import Data.Time.Calendar (Day,toGregorian,fromGregorian)
#if MIN_VERSION_winery(1,4,0)
#else
import qualified Data.List.NonEmpty as NE
#endif

deriving via WineryVariant Atom instance Serialise Atom
deriving via WineryVariant AtomType instance Serialise AtomType
deriving via WineryVariant Attribute instance Serialise Attribute
deriving via WineryVariant RelationTuple instance Serialise RelationTuple
deriving via WineryVariant RelationCardinality instance Serialise RelationCardinality
deriving via WineryVariant (RelationalExprBase a) instance Serialise a => Serialise (RelationalExprBase a)
deriving via WineryVariant (WithNameExprBase a) instance Serialise a => Serialise (WithNameExprBase a)
deriving via WineryVariant Notification instance Serialise Notification
deriving via WineryVariant TypeConstructorDef instance Serialise TypeConstructorDef
deriving via WineryVariant (TypeConstructorBase a) instance Serialise a => Serialise (TypeConstructorBase a)
deriving via WineryVariant DataConstructorDef instance Serialise DataConstructorDef
deriving via WineryVariant DataConstructorDefArg instance Serialise DataConstructorDefArg
deriving via WineryVariant GraphRefTransactionMarker instance Serialise GraphRefTransactionMarker
deriving via WineryVariant SchemaIsomorph instance Serialise SchemaIsomorph
deriving via WineryVariant InclusionDependency instance Serialise InclusionDependency
deriving via WineryVariant (DatabaseContextExprBase a) instance Serialise a => Serialise (DatabaseContextExprBase a)
deriving via WineryVariant (DatabaseContextIOExprBase a) instance Serialise a => Serialise (DatabaseContextIOExprBase a)
deriving via WineryVariant (RestrictionPredicateExprBase a) instance Serialise a => Serialise (RestrictionPredicateExprBase a)
deriving via WineryVariant TransactionInfo instance Serialise TransactionInfo
deriving via WineryVariant (AtomExprBase a) instance Serialise a => Serialise (AtomExprBase a)
deriving via WineryVariant MerkleHash instance Serialise MerkleHash
deriving via WineryVariant (AttributeExprBase a) instance Serialise a => Serialise (AttributeExprBase a)
deriving via WineryVariant (TupleExprsBase a) instance Serialise a => Serialise (TupleExprsBase a)
deriving via WineryVariant (TupleExprBase a) instance Serialise a => Serialise (TupleExprBase a)
deriving via WineryVariant (AttributeNamesBase a) instance Serialise a => Serialise (AttributeNamesBase a)
deriving via WineryVariant (ExtendTupleExprBase a) instance Serialise a => Serialise (ExtendTupleExprBase a)
deriving via WineryVariant Schema instance Serialise Schema
deriving via WineryVariant MergeStrategy instance Serialise MergeStrategy

fromWordsTup :: (Word32, Word32, Word32, Word32) -> TransactionId
fromWordsTup :: (Word32, Word32, Word32, Word32) -> TransactionId
fromWordsTup (Word32
a,Word32
b,Word32
c,Word32
d) = Word32 -> Word32 -> Word32 -> Word32 -> TransactionId
fromWords Word32
a Word32
b Word32
c Word32
d

instance Serialise TransactionId where
  schemaGen :: Proxy TransactionId -> SchemaGen Schema
schemaGen Proxy TransactionId
_ = forall (proxy :: * -> *) a.
Serialise a =>
proxy a -> SchemaGen Schema
getSchema (forall {k} (t :: k). Proxy t
Proxy @(Word32, Word32, Word32, Word32))
  toBuilder :: TransactionId -> Builder
toBuilder TransactionId
uuid = forall a. Serialise a => a -> Builder
toBuilder (TransactionId -> (Word32, Word32, Word32, Word32)
toWords TransactionId
uuid)
  extractor :: Extractor TransactionId
extractor = (Word32, Word32, Word32, Word32) -> TransactionId
fromWordsTup forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Extractor a
extractor
  decodeCurrent :: Decoder TransactionId
decodeCurrent = (Word32, Word32, Word32, Word32) -> TransactionId
fromWordsTup forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Decoder a
decodeCurrent

#if MIN_VERSION_winery(1,4,0)
#else
instance Serialise a => Serialise (NE.NonEmpty a) where
  schemaGen _ = SVector <$> getSchema (Proxy @a)
  toBuilder xs = varInt (length xs) <> foldMap toBuilder xs
  extractor = NE.fromList . V.toList <$> extractListBy extractor --use nonempty instead to replace error with winery error
  decodeCurrent = do
    n <- decodeVarInt
    l <- replicateM n decodeCurrent
    pure (NE.fromList l)
#endif

fromGregorianTup :: (Integer, Int, Int) -> Day
fromGregorianTup :: (Integer, Int, Int) -> Day
fromGregorianTup (Integer
a, Int
b, Int
c) = Integer -> Int -> Int -> Day
fromGregorian Integer
a Int
b Int
c

instance Serialise Day where
  schemaGen :: Proxy Day -> SchemaGen Schema
schemaGen Proxy Day
_ = forall (proxy :: * -> *) a.
Serialise a =>
proxy a -> SchemaGen Schema
getSchema (forall {k} (t :: k). Proxy t
Proxy @(Integer, Int, Int))
  toBuilder :: Day -> Builder
toBuilder Day
day = forall a. Serialise a => a -> Builder
toBuilder (Day -> (Integer, Int, Int)
toGregorian Day
day)
  extractor :: Extractor Day
extractor = (Integer, Int, Int) -> Day
fromGregorianTup forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Extractor a
extractor
  decodeCurrent :: Decoder Day
decodeCurrent = (Integer, Int, Int) -> Day
fromGregorianTup forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Decoder a
decodeCurrent

instance Serialise Attributes where
  schemaGen :: Proxy Attributes -> SchemaGen Schema
schemaGen Proxy Attributes
_ = forall a. SchemaP a -> SchemaP a
SVector forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (proxy :: * -> *) a.
Serialise a =>
proxy a -> SchemaGen Schema
getSchema (forall {k} (t :: k). Proxy t
Proxy @Attribute)
  toBuilder :: Attributes -> Builder
toBuilder Attributes
attrs = forall a. (Bits a, Integral a) => a -> Builder
varInt (forall a. Vector a -> Int
V.length (Attributes -> Vector Attribute
attributesVec Attributes
attrs)) forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap forall a. Serialise a => a -> Builder
toBuilder (forall a. Vector a -> [a]
V.toList (Attributes -> Vector Attribute
attributesVec Attributes
attrs))
  extractor :: Extractor Attributes
extractor =
    [Attribute] -> Attributes
attributesFromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Vector a -> [a]
V.toList forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Typeable a => Extractor a -> Extractor (Vector a)
extractListBy forall a. Serialise a => Extractor a
extractor

  decodeCurrent :: Decoder Attributes
decodeCurrent = do
    Int
n <- forall a. (Num a, Bits a) => Decoder a
decodeVarInt
    [Attribute]
l <- forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
n forall a. Serialise a => Decoder a
decodeCurrent
    forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Attribute] -> Attributes
A.attributesFromList [Attribute]
l)

-- | A special instance of Serialise which cuts down on duplicate attributes- we should only serialise the attributes at the top-level and not duplicate them per tuple.
instance Serialise Relation where
  schemaGen :: Proxy Relation -> SchemaGen Schema
schemaGen Proxy Relation
_ = forall (proxy :: * -> *) a.
Serialise a =>
proxy a -> SchemaGen Schema
getSchema (forall {k} (t :: k). Proxy t
Proxy @(Attributes, [V.Vector Atom]))
  toBuilder :: Relation -> Builder
toBuilder Relation
rel = forall a. Serialise a => a -> Builder
toBuilder (Relation -> Attributes
attributes Relation
rel, forall a b. (a -> b) -> [a] -> [b]
map RelationTuple -> Vector Atom
tupleAtoms (Relation -> [RelationTuple]
tuplesList Relation
rel))
  extractor :: Extractor Relation
extractor = (Attributes, [Vector Atom]) -> Relation
makeRelation forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Extractor a
extractor
   where
    makeRelation :: (Attributes, [Vector Atom]) -> Relation
makeRelation (Attributes
attrs, [Vector Atom]
atomList) =  Attributes -> RelationTupleSet -> Relation
Relation Attributes
attrs ([RelationTuple] -> RelationTupleSet
RelationTupleSet (forall a b. (a -> b) -> [a] -> [b]
map (Attributes -> Vector Atom -> RelationTuple
RelationTuple Attributes
attrs) [Vector Atom]
atomList))
  decodeCurrent :: Decoder Relation
decodeCurrent = do
    (Attributes
attrs, [Vector Atom]
atomList) <- forall a. Serialise a => Decoder a
decodeCurrent
    forall (f :: * -> *) a. Applicative f => a -> f a
pure (Attributes -> RelationTupleSet -> Relation
Relation Attributes
attrs ([RelationTuple] -> RelationTupleSet
RelationTupleSet (forall a b. (a -> b) -> [a] -> [b]
map (Attributes -> Vector Atom -> RelationTuple
RelationTuple Attributes
attrs) [Vector Atom]
atomList)))   

type SlimTupleSet = Either () (Attributes, [V.Vector Atom])

slimTupleSet :: RelationTupleSet -> SlimTupleSet
slimTupleSet :: RelationTupleSet -> SlimTupleSet
slimTupleSet RelationTupleSet
tupSet =
  case RelationTupleSet -> [RelationTuple]
asList RelationTupleSet
tupSet of
    [] -> forall a b. a -> Either a b
Left ()
    RelationTuple
tup:[RelationTuple]
tups -> forall a b. b -> Either a b
Right (RelationTuple -> Attributes
tupleAttributes RelationTuple
tup, forall a b. (a -> b) -> [a] -> [b]
map RelationTuple -> Vector Atom
tupleAtoms (RelationTuple
tupforall a. a -> [a] -> [a]
:[RelationTuple]
tups))

-- | restore slimmed tuple set to include single shared attributes list
fattenTupleSet :: SlimTupleSet -> RelationTupleSet
fattenTupleSet :: SlimTupleSet -> RelationTupleSet
fattenTupleSet Left{} = RelationTupleSet
emptyTupleSet
fattenTupleSet (Right (Attributes
attrs, [Vector Atom]
vtups)) = [RelationTuple] -> RelationTupleSet
RelationTupleSet forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (Attributes -> Vector Atom -> RelationTuple
RelationTuple Attributes
attrs) [Vector Atom]
vtups

-- | A special instance of Serialise which cuts down on duplicate attributes- we should only serialise the attributes at the top-level and not duplicate them per tuple. If we have an empty tupleset, we lack all attributes which is fine in this case.
instance Serialise RelationTupleSet where
  schemaGen :: Proxy RelationTupleSet -> SchemaGen Schema
schemaGen Proxy RelationTupleSet
_ = forall (proxy :: * -> *) a.
Serialise a =>
proxy a -> SchemaGen Schema
getSchema (forall {k} (t :: k). Proxy t
Proxy @SlimTupleSet)
  toBuilder :: RelationTupleSet -> Builder
toBuilder RelationTupleSet
tupSet = forall a. Serialise a => a -> Builder
toBuilder (RelationTupleSet -> SlimTupleSet
slimTupleSet RelationTupleSet
tupSet)
  extractor :: Extractor RelationTupleSet
extractor = SlimTupleSet -> RelationTupleSet
fattenTupleSet forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Extractor a
extractor
  decodeCurrent :: Decoder RelationTupleSet
decodeCurrent = SlimTupleSet -> RelationTupleSet
fattenTupleSet forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Serialise a => Decoder a
decodeCurrent