    -- | This module implements encoding and decoding
    -- of [comma-separated values (CSV)](https://en.wikipedia.org/wiki/Comma-separated_values)
    -- data. The implementation is [RFC 4180](https://tools.ietf.org/html/rfc4180)
    -- compliant, with the following extensions:
    --
    --  * Empty lines are ignored.
    --
    --  * Non-escaped fields may contain any characters except
    --    double-quotes, commas, carriage returns, and newlines.
    --
    --  * Escaped fields may contain any characters (but double-quotes
    --    need to be escaped).
    module Data.Csv
        (
        -- * Usage examples
        -- $example

        -- ** Encoding and decoding custom data types
        -- $example-instance

        -- *** Index-based record conversion
        -- $example-indexed-instance

        -- *** Name-based record conversion
        -- $example-named-instance

        -- ** Reading/writing CSV files
        -- $example-file

        -- * Treating CSV data as opaque byte strings
        -- $generic-processing

        -- * Custom type conversions for fields
        -- $customtypeconversions

        -- ** Dealing with bad data
        -- $baddata

        -- * Encoding and decoding
        -- $encoding
          HasHeader(..)
        , decode
        , decodeByName
        , encode
        , encodeByName
        , encodeDefaultOrderedByName
        , DefaultOrdered(..)

        -- ** Encoding and decoding options
        -- $options
        , DecodeOptions(..)
        , defaultDecodeOptions
        , decodeWith
        , decodeWithP
        , decodeByNameWith
        , decodeByNameWithP
        , EncodeOptions(..)
        , Quoting(..)
        , defaultEncodeOptions
        , encodeWith
        , encodeByNameWith
        , encodeDefaultOrderedByNameWith

        -- * Core CSV types
        , Csv
        , Record
        , Field
        , Header
        , Name
        , NamedRecord

        -- * Type conversion
        -- $typeconversion

        -- ** Index-based record conversion
        -- $indexbased
        , FromRecord(..)
        , Parser
        , runParser
        , index
        , (.!)
        , unsafeIndex
        , ToRecord(..)
        , record
        , Only(..)

        -- ** Name-based record conversion
        -- $namebased
        , FromNamedRecord(..)
        , lookup
        , (.:)
        , ToNamedRecord(..)
        , namedRecord
        , namedField
        , (.=)
        , header

        -- ** Field conversion
        -- $fieldconversion
        , FromField(..)
        , ToField(..)

        -- ** 'Generic' record conversion
        -- $genericconversion
        , genericParseRecord
        , genericToRecord
        , genericParseNamedRecord
        , genericToNamedRecord
        , genericHeaderOrder

        -- *** 'Generic' type conversion options
        , Options
        , defaultOptions
        , fieldLabelModifier

        -- *** 'Generic' type conversion class name
        -- $genericconversionclass
        , GFromRecord
        , GToRecord
        , GFromNamedRecord
        , GToNamedRecordHeader
        ) where

    import Prelude hiding (lookup)

    import Data.Csv.Conversion
    import Data.Csv.Encoding
    import Data.Csv.Types

    -- $example
    --
    -- Encoding standard Haskell types:
    --
    -- >>> :set -XOverloadedStrings
    -- >>> import Data.Text (Text)
    -- >>> encode [("John" :: Text, 27 :: Int), ("Jane", 28)]
    -- "John,27\r\nJane,28\r\n"
    --
    -- Since we enabled the [-XOverloadedStrings extension](https://downloads.haskell.org/~ghc/8.2.1/docs/html/users_guide/glasgow_exts.html#overloaded-string-literals),
    -- string literals are polymorphic and we have to supply a type
    -- signature as the compiler couldn't deduce which string type (i.e.
    -- 'String', 'Data.Text.Short.ShortText', or 'Data.Text.Text') we want to use. In most cases
    -- type inference will infer the type from the context and you can
    -- omit type signatures.
    --
    -- Decoding standard Haskell types:
    --
    -- >>> import Data.Vector (Vector)
    -- >>> decode NoHeader "John,27\r\nJane,28\r\n" :: Either String (Vector (Text, Int))
    -- Right [("John",27),("Jane",28)]
    --
    -- We pass 'NoHeader' as the first argument to indicate that the CSV
    -- input data isn't preceded by a header.
    --
    -- In practice, the return type of 'decode' rarely needs to be given,
    -- as it can often be inferred from the context.

    -- $example-file
    --
    -- Demonstration of reading from a CSV file/ writing to a CSV file
    -- using the incremental API:
    --
    -- > {-# LANGUAGE BangPatterns      #-}
    -- > {-# LANGUAGE DeriveGeneric     #-}
    -- > {-# LANGUAGE LambdaCase        #-}
    -- > {-# LANGUAGE OverloadedStrings #-}
    -- >
    -- > -- from base
    -- > import GHC.Generics
    -- > import System.IO
    -- > import System.Exit (exitFailure)
    -- > -- from bytestring
    -- > import Data.ByteString (ByteString, hGetSome, empty)
    -- > import qualified Data.ByteString.Lazy as BL
    -- > -- from cassava
    -- > import Data.Csv.Incremental
    -- > import Data.Csv (FromRecord, ToRecord)
    -- >
    -- > data Person = Person
    -- >   { name :: !ByteString
    -- >   , age  :: !Int
    -- >   } deriving (Show, Eq, Generic)
    -- >
    -- > instance FromRecord Person
    -- > instance ToRecord Person
    -- >
    -- > persons :: [Person]
    -- > persons = [Person "John Doe" 19, Person "Smith" 20]
    -- >
    -- > writeToFile :: IO ()
    -- > writeToFile = do
    -- >   BL.writeFile "persons.csv" $ encode $
    -- >     foldMap encodeRecord persons
    -- >
    -- > feed :: (ByteString -> Parser Person) -> Handle -> IO (Parser Person)
    -- > feed k csvFile = do
    -- >   hIsEOF csvFile >>= \case
    -- >     True  -> return $ k empty
    -- >     False -> k <$> hGetSome csvFile 4096
    -- >
    -- > readFromFile :: IO ()
    -- > readFromFile = do
    -- >   withFile "persons.csv" ReadMode $ \ csvFile -> do
    -- >     let loop !_ (Fail _ errMsg) = do putStrLn errMsg; exitFailure
    -- >         loop acc (Many rs k)    = loop (acc <> rs) =<< feed k csvFile
    -- >         loop acc (Done rs)      = print (acc <> rs)
    -- >     loop [] (decode NoHeader)
    -- >
    -- > main :: IO ()
    -- > main = do
    -- >   writeToFile
    -- >   readFromFile
    -- >

    -- $example-instance
    --
    -- To encode and decode your own data types you need to defined
    -- instances of either 'ToRecord' and 'FromRecord' or 'ToNamedRecord'
    -- and 'FromNamedRecord'. The former is used for encoding/decoding
    -- using the column index and the latter using the column name.
    --
    -- There are two ways to to define these instances, either by manually
    -- defining them or by using GHC generics to derive them automatically.

    -- $example-indexed-instance
    --
    -- "GHC.Generics"-derived:
    --
    -- > {-# LANGUAGE DeriveGeneric #-}
    -- >
    -- > import Data.Text    (Text)
    -- > import GHC.Generics (Generic)
    -- >
    -- > data Person = Person { name :: !Text , salary :: !Int }
    -- >     deriving (Generic, Show)
    -- >
    -- > instance FromRecord Person
    -- > instance ToRecord Person
    --
    -- Manually defined:
    --
    -- > import Control.Monad (mzero)
    -- >
    -- > data Person = Person { name :: !Text , salary :: !Int }
    -- >     deriving (Show)
    -- >
    -- > instance FromRecord Person where
    -- >     parseRecord v
    -- >         | length v == 2 = Person <$> v .! 0 <*> v .! 1
    -- >         | otherwise     = mzero
    -- > instance ToRecord Person where
    -- >     toRecord (Person name' age') = record [
    -- >         toField name', toField age']
    --
    -- We can now use e.g. 'encode' and 'decode' to encode and decode our
    -- data type.
    --
    -- Encoding:
    --
    -- >>> encode [Person ("John" :: Text) 27]
    -- "John,27\r\n"
    --
    -- Decoding:
    --
    -- >>> decode NoHeader "John,27\r\n" :: Either String (Vector Person)
    -- Right [Person {name = "John", salary = 27}]
    --

    -- $example-named-instance
    --
    -- "GHC.Generics"-derived:
    --
    -- > {-# LANGUAGE DeriveGeneric #-}
    -- >
    -- > import Data.Text    (Text)
    -- > import GHC.Generics (Generic)
    -- >
    -- > data Person = Person { name :: !Text , salary :: !Int }
    -- >     deriving (Generic, Show)
    -- >
    -- > instance FromNamedRecord Person
    -- > instance ToNamedRecord Person
    -- > instance DefaultOrdered Person
    --
    -- Manually defined:
    --
    -- > data Person = Person { name :: !Text , salary :: !Int }
    -- >     deriving (Show)
    -- >
    -- > instance FromNamedRecord Person where
    -- >     parseNamedRecord m = Person <$> m .: "name" <*> m .: "salary"
    -- > instance ToNamedRecord Person where
    -- >     toNamedRecord (Person name salary) = namedRecord [
    -- >         "name" .= name, "salary" .= salary]
    -- > instance DefaultOrdered Person where
    -- >     headerOrder _ = header ["name", "salary"]
    --
    -- We can now use e.g. 'encodeDefaultOrderedByName' (or 'encodeByName'
    -- with an explicit header order) and 'decodeByName' to encode and
    -- decode our data type.
    --
    -- Encoding:
    --
    -- >>> encodeDefaultOrderedByName [Person ("John" :: Text) 27]
    -- "name,salary\r\nJohn,27\r\n"
    --
    -- Decoding:
    --
    -- >>> decodeByName "name,salary\r\nJohn,27\r\n" :: Either String (Header, Vector Person)
    -- Right (["name","salary"],[Person {name = "John", salary = 27}])
    --

    -- $generic-processing
    --
    -- Sometimes you might want to work with a CSV file which contents is
    -- unknown to you. For example, you might want remove the second
    -- column of a file without knowing anything about its content. To
    -- parse a CSV file to a generic representation, just convert each
    -- record to a @'Vector' 'ByteString'@ value, like so:
    --
    -- >>> import Data.ByteString (ByteString)
    -- >>> decode NoHeader "John,27\r\nJane,28\r\n" :: Either String (Vector (Vector ByteString))
    -- Right [["John","27"],["Jane","28"]]
    --
    -- As the example output above shows, all the fields are returned as
    -- uninterpreted 'ByteString' values.

    -- $customtypeconversions
    --
    -- Most of the time the existing 'FromField' and 'ToField' instances
    -- do what you want. However, if you need to parse a different format
    -- (e.g. hex) but use a type (e.g. 'Int') for which there's already a
    -- 'FromField' instance, you need to use a @newtype@. Example:
    --
    -- > newtype Hex = Hex Int
    -- >
    -- > parseHex :: ByteString -> Parser Int
    -- > parseHex = ...
    -- >
    -- > instance FromField Hex where
    -- >     parseField s = Hex <$> parseHex s
    --
    -- Other than giving an explicit type signature, you can pattern match
    -- on the @newtype@ constructor to indicate which type conversion you
    -- want to have the library use:
    --
    -- > case decode NoHeader "0xff,0xaa\r\n0x11,0x22\r\n" of
    -- >     Left err -> putStrLn err
    -- >     Right v  -> forM_ v $ \ (Hex val1, Hex val2) ->
    -- >         print (val1, val2)
    --
    -- If a field might be in one several different formats, you can use a
    -- newtype to normalize the result:
    --
    -- > newtype HexOrDecimal = HexOrDecimal Int
    -- >
    -- > instance FromField DefaultToZero where
    -- >     parseField s = case runParser (parseField s :: Parser Hex) of
    -- >         Left err -> HexOrDecimal <$> parseField s  -- Uses Int instance
    -- >         Right n  -> pure $ HexOrDecimal n
    --
    -- You can use the unit type, @()@, to ignore a column. The
    -- 'parseField' method for @()@ doesn't look at the 'Field' and thus
    -- always decodes successfully. Note that it lacks a corresponding
    -- 'ToField' instance. Example:
    --
    -- > case decode NoHeader "foo,1\r\nbar,22" of
    -- >     Left  err -> putStrLn err
    -- >     Right v   -> forM_ v $ \ ((), i) -> print (i :: Int)

    -- $baddata
    --
    -- If your input might contain invalid fields, you can write a custom
    -- 'FromField' instance to deal with them. Example:
    --
    -- > newtype DefaultToZero = DefaultToZero Int
    -- >
    -- > instance FromField DefaultToZero where
    -- >     parseField s = case runParser (parseField s) of
    -- >         Left err -> pure $ DefaultToZero 0
    -- >         Right n  -> pure $ DefaultToZero n

    -- $encoding
    --
    -- Encoding and decoding is a two step process. To encode a value, it
    -- is first converted to a generic representation, using either
    -- 'ToRecord' or 'ToNamedRecord'. The generic representation is then
    -- encoded as CSV data. To decode a value the process is reversed and
    -- either 'FromRecord' or 'FromNamedRecord' is used instead. Both
    -- these steps are combined in the 'encode' and 'decode' functions.

    -- $typeconversion
    --
    -- There are two ways to convert CSV records to and from and
    -- user-defined data types: index-based conversion and name-based
    -- conversion.

    -- $indexbased
    --
    -- Index-based conversion lets you convert CSV records to and from
    -- user-defined data types by referring to a field's position (its
    -- index) in the record. The first column in a CSV file is given index
    -- 0, the second index 1, and so on.

    -- $namebased
    --
    -- Name-based conversion lets you convert CSV records to and from
    -- user-defined data types by referring to a field's name. The names
    -- of the fields are defined by the first line in the file, also known
    -- as the header. Name-based conversion is more robust to changes in
    -- the file structure e.g. to reording or addition of columns, but can
    -- be a bit slower.

    -- $options
    --
    -- These functions can be used to control how data is encoded and
    -- decoded. For example, they can be used to encode data in a
    -- tab-separated format instead of in a comma-separated format.

    -- $fieldconversion
    --
    -- The 'FromField' and 'ToField' classes define how to convert between
    -- 'Field's and values you care about (e.g. 'Int's). Most of the time
    -- you don't need to write your own instances as the standard ones
    -- cover most use cases.

    -- $genericconversion
    --
    -- There may be times that you do not want to manually write out class
    -- instances for record conversion, but you can't rely upon the
    -- default instances (e.g. you can't create field names that match the
    -- actual column names in expected data).
    --
    -- For example, consider you have a type @MyType@ where you have
    -- prefixed certain columns with an underscore, but in the actual data
    -- they're not.  You can then write:
    --
    -- > myOptions :: Options
    -- > myOptions = defaultOptions { fieldLabelModifier = rmUnderscore }
    -- >   where
    -- >     rmUnderscore ('_':str) = str
    -- >     rmUnderscore str       = str
    -- >
    -- > instance ToNamedRecord MyType where
    -- >   toNamedRecord = genericToNamedRecord myOptions
    -- >
    -- > instance FromNamedRecord MyType where
    -- >   parseNamedRecord = genericParseNamedRecord myOptions
    -- >
    -- > instance DefaultOrdered MyType where
    -- >   headerOrder = genericHeaderOrder myOptions

    -- $genericconversionclass
    --
    -- __NOTE__: Only the class /names/ are exposed in order to make it possible to write type signatures referring to these classes

    -- $setup
    -- >>> :set -XOverloadedStrings -XDeriveGeneric
    -- >>> import Data.Text (Text)
    -- >>> import Data.Vector (Vector)
    -- >>> import GHC.Generics (Generic)
    -- >>>
    -- >>> data Person = Person { name :: !Text, salary :: !Int } deriving (Generic, Show)
    -- >>> instance FromRecord Person
    -- >>> instance ToRecord Person
    -- >>> instance FromNamedRecord Person
    -- >>> instance ToNamedRecord Person
    -- >>> instance DefaultOrdered Person