{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Eventium.TH.SumTypeSerializer
( mkSumTypeSerializer,
)
where
import Data.Char (toLower)
import Language.Haskell.TH
import SumTypesX.TH
mkSumTypeSerializer :: String -> Name -> Name -> Q [Dec]
mkSumTypeSerializer :: String -> Name -> Name -> Q [Dec]
mkSumTypeSerializer String
serializerName Name
sourceType Name
targetType = do
let serializeFuncName :: String
serializeFuncName = String -> String
firstCharToLower (Name -> String
nameBase Name
sourceType) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"To" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Name -> String
nameBase Name
targetType
deserializeFuncName :: String
deserializeFuncName = String -> String
firstCharToLower (Name -> String
nameBase Name
targetType) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"To" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Name -> String
nameBase Name
sourceType
[Dec]
serializeDecls <- String -> Name -> Name -> Q [Dec]
sumTypeConverter String
serializeFuncName Name
sourceType Name
targetType
[Dec]
deserializeDecls <- String -> Name -> Name -> Q [Dec]
partialSumTypeConverter String
deserializeFuncName Name
targetType Name
sourceType
Type
serializerTypeDecl <- [t|$(Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT (Name -> Q Type) -> Name -> Q Type
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
"Serializer") $(Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT Name
sourceType) $(Name -> Q Type
forall (m :: * -> *). Quote m => Name -> m Type
conT Name
targetType)|]
Exp
serializerExp <- [e|$(Name -> Q Exp
forall (m :: * -> *). Quote m => Name -> m Exp
varE (Name -> Q Exp) -> Name -> Q Exp
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
"simpleSerializer") $(Name -> Q Exp
forall (m :: * -> *). Quote m => Name -> m Exp
varE (Name -> Q Exp) -> Name -> Q Exp
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
serializeFuncName) $(Name -> Q Exp
forall (m :: * -> *). Quote m => Name -> m Exp
varE (Name -> Q Exp) -> Name -> Q Exp
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
deserializeFuncName)|]
let serializerClause :: Clause
serializerClause = [Pat] -> Body -> [Dec] -> Clause
Clause [] (Exp -> Body
NormalB Exp
serializerExp) []
[Dec] -> Q [Dec]
forall a. a -> Q a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Dec] -> Q [Dec]) -> [Dec] -> Q [Dec]
forall a b. (a -> b) -> a -> b
$
[ Name -> Type -> Dec
SigD (String -> Name
mkName String
serializerName) Type
serializerTypeDecl,
Name -> [Clause] -> Dec
FunD (String -> Name
mkName String
serializerName) [Clause
serializerClause]
]
[Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
++ [Dec]
serializeDecls
[Dec] -> [Dec] -> [Dec]
forall a. [a] -> [a] -> [a]
++ [Dec]
deserializeDecls
firstCharToLower :: String -> String
firstCharToLower :: String -> String
firstCharToLower [] = []
firstCharToLower (Char
x : String
xs) = Char -> Char
toLower Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String
xs