module Hasql.RowParser where import Hasql.Prelude import Language.Haskell.TH import qualified Hasql.Backend as Backend import qualified Data.Vector as Vector import qualified Hasql.TH as THUtil class RowParser b r where parseRow :: Vector.Vector (Backend.Result b) -> Either Text r instance RowParser b () where parseRow row = if Vector.null row then Right () else $bug "Not an empty row" instance Backend.Mapping b v => RowParser b (Identity v) where parseRow row = do Identity <$> Backend.parseResult (Vector.unsafeHead row) -- Generate tuple instaces using Template Haskell: return $ flip map [2 .. 24] $ \arity -> let varNames = [1 .. arity] >>= \i -> return (mkName ('v' : show i)) varTypes = map VarT varNames connectionType = VarT (mkName "b") constraints = map (\t -> ClassP ''Backend.Mapping [connectionType, t]) varTypes head = AppT (AppT (ConT ''RowParser) connectionType) (foldl AppT (TupleT arity) varTypes) parseRowDec = FunD 'parseRow [Clause [VarP rowVarName] (NormalB e) []] where rowVarName = mkName "row" e = THUtil.applicativeE (ConE (tupleDataName arity)) lookups where lookups = do i <- [0 .. pred arity] return $ THUtil.purify $ [| Backend.parseResult (Vector.unsafeIndex $(varE rowVarName) $(litE (IntegerL $ fromIntegral i)) ) |] in InstanceD constraints head [parseRowDec]