fradrive/src/Utils/Csv.hs
2019-09-25 17:36:48 +02:00

74 lines
2.1 KiB
Haskell

{-# OPTIONS -fno-warn-orphans #-}
module Utils.Csv
( typeCsv, typeCsv', extensionCsv
, pathPieceCsv
, (.:??)
, CsvRendered(..)
, toCsvRendered
, toDefaultOrderedCsvRendered
) where
import ClassyPrelude hiding (lookup)
import Settings.Mime
import Data.Csv hiding (Name)
import Data.Csv.Conduit (CsvParseError)
import Language.Haskell.TH (Name)
import Language.Haskell.TH.Lib
import Yesod.Core.Content (ContentType, simpleContentType)
import qualified Data.Map as Map
deriving instance Typeable CsvParseError
instance Exception CsvParseError
typeCsv, typeCsv' :: ContentType
typeCsv = simpleContentType typeCsv'
typeCsv' = "text/csv; charset=UTF-8; header=present"
extensionCsv :: Extension
extensionCsv = fromMaybe "csv" $ listToMaybe [ ext | (ext, mime) <- Map.toList mimeMap, mime == typeCsv ]
pathPieceCsv :: Name -> DecsQ
pathPieceCsv (conT -> t) =
[d|
instance ToField $(t) where
toField = toField . toPathPiece
instance FromField $(t) where
parseField = maybe (fail "Could not unmarshal from PathPiece") return . fromPathPiece <=< parseField
|]
(.:??) :: FromField (Maybe a) => NamedRecord -> ByteString -> Parser (Maybe a)
m .:?? name = lookup m name <|> return Nothing
data CsvRendered = CsvRendered
{ csvRenderedHeader :: Header
, csvRenderedData :: [NamedRecord]
} deriving (Eq, Read, Show, Generic, Typeable)
toCsvRendered :: forall mono.
( ToNamedRecord (Element mono)
, MonoFoldable mono
)
=> Header
-> mono -> CsvRendered
toCsvRendered csvRenderedHeader (otoList -> csvs) = CsvRendered{..}
where
csvRenderedData = map toNamedRecord csvs
toDefaultOrderedCsvRendered :: forall mono.
( ToNamedRecord (Element mono)
, DefaultOrdered (Element mono)
, MonoFoldable mono
)
=> mono -> CsvRendered
toDefaultOrderedCsvRendered = toCsvRendered $ headerOrder (error "headerOrder" :: Element mono)