    {-# LANGUAGE ScopedTypeVariables #-}

    -- | Low-level bytestring builders. Most users want to use the more
    -- type-safe "Data.Csv.Incremental" module instead.
    module Data.Csv.Builder
        (
        -- * Encoding single records and headers
          encodeHeader
        , encodeRecord
        , encodeNamedRecord
        , encodeDefaultOrderedNamedRecord
        -- ** Encoding options
        , encodeHeaderWith
        , encodeRecordWith
        , encodeNamedRecordWith
        , encodeDefaultOrderedNamedRecordWith
        ) where

    import qualified Data.Monoid as Mon

    import Data.ByteString.Builder as Builder
    import Data.Csv.Conversion
    import qualified Data.Csv.Encoding as Encoding
    import Data.Csv.Encoding (EncodeOptions(..))
    import Data.Csv.Types hiding (toNamedRecord)

    -- | Encode a header.
    encodeHeader :: Header -> Builder.Builder
    encodeHeader :: Header -> Builder
    encodeHeader = Header -> Builder
    forall a. ToRecord a => a -> Builder
    encodeRecord

    -- | Encode a single record.
    encodeRecord :: ToRecord a => a -> Builder.Builder
    encodeRecord :: forall a. ToRecord a => a -> Builder
    encodeRecord = EncodeOptions -> a -> Builder
    forall a. ToRecord a => EncodeOptions -> a -> Builder
    encodeRecordWith EncodeOptions
    Encoding.defaultEncodeOptions

    -- | Encode a single named record, given the field order.
    encodeNamedRecord :: ToNamedRecord a =>
                         Header -> a -> Builder.Builder
    encodeNamedRecord :: forall a. ToNamedRecord a => Header -> a -> Builder
    encodeNamedRecord = EncodeOptions -> Header -> a -> Builder
    forall a.
    ToNamedRecord a =>
    EncodeOptions -> Header -> a -> Builder
    encodeNamedRecordWith EncodeOptions
    Encoding.defaultEncodeOptions

    -- | Encode a single named record, using the default field order.
    encodeDefaultOrderedNamedRecord ::
        (DefaultOrdered a, ToNamedRecord a) => a -> Builder.Builder
    encodeDefaultOrderedNamedRecord :: forall a. (DefaultOrdered a, ToNamedRecord a) => a -> Builder
    encodeDefaultOrderedNamedRecord =
        EncodeOptions -> a -> Builder
    forall a.
    (DefaultOrdered a, ToNamedRecord a) =>
    EncodeOptions -> a -> Builder
    encodeDefaultOrderedNamedRecordWith EncodeOptions
    Encoding.defaultEncodeOptions

    -- | Like 'encodeHeader', but lets you customize how the CSV data is
    -- encoded.
    encodeHeaderWith :: EncodeOptions -> Header -> Builder.Builder
    encodeHeaderWith :: EncodeOptions -> Header -> Builder
    encodeHeaderWith = EncodeOptions -> Header -> Builder
    forall a. ToRecord a => EncodeOptions -> a -> Builder
    encodeRecordWith

    -- | Like 'encodeRecord', but lets you customize how the CSV data is
    -- encoded.
    encodeRecordWith :: ToRecord a => EncodeOptions -> a -> Builder.Builder
    encodeRecordWith :: forall a. ToRecord a => EncodeOptions -> a -> Builder
    encodeRecordWith EncodeOptions
    opts a
    r =
        Quoting -> Word8 -> Header -> Builder
    Encoding.encodeRecord (EncodeOptions -> Quoting
    encQuoting EncodeOptions
    opts) (EncodeOptions -> Word8
    encDelimiter EncodeOptions
    opts) (a -> Header
    forall a. ToRecord a => a -> Header
    toRecord a
    r)
        Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> Bool -> Builder
    Encoding.recordSep (EncodeOptions -> Bool
    encUseCrLf EncodeOptions
    opts)

    -- | Like 'encodeNamedRecord', but lets you customize how the CSV data
    -- is encoded.
    encodeNamedRecordWith :: ToNamedRecord a =>
                             EncodeOptions -> Header -> a -> Builder.Builder
    encodeNamedRecordWith :: forall a.
    ToNamedRecord a =>
    EncodeOptions -> Header -> a -> Builder
    encodeNamedRecordWith EncodeOptions
    opts Header
    hdr a
    nr =
        Header -> Quoting -> Word8 -> NamedRecord -> Builder
    Encoding.encodeNamedRecord Header
    hdr (EncodeOptions -> Quoting
    encQuoting EncodeOptions
    opts) (EncodeOptions -> Word8
    encDelimiter EncodeOptions
    opts)
        (a -> NamedRecord
    forall a. ToNamedRecord a => a -> NamedRecord
    toNamedRecord a
    nr) Builder -> Builder -> Builder
    forall a. Semigroup a => a -> a -> a
    Mon.<> Bool -> Builder
    Encoding.recordSep (EncodeOptions -> Bool
    encUseCrLf EncodeOptions
    opts)

    -- | Like 'encodeDefaultOrderedNamedRecord', but lets you customize
    -- how the CSV data is encoded.
    encodeDefaultOrderedNamedRecordWith ::
        forall a. (DefaultOrdered a, ToNamedRecord a) =>
        EncodeOptions -> a -> Builder.Builder
    encodeDefaultOrderedNamedRecordWith :: forall a.
    (DefaultOrdered a, ToNamedRecord a) =>
    EncodeOptions -> a -> Builder
    encodeDefaultOrderedNamedRecordWith EncodeOptions
    opts =
        EncodeOptions -> Header -> a -> Builder
    forall a.
    ToNamedRecord a =>
    EncodeOptions -> Header -> a -> Builder
    encodeNamedRecordWith EncodeOptions
    opts (a -> Header
    forall a. DefaultOrdered a => a -> Header
    headerOrder (a
    forall a. HasCallStack => a
    undefined :: a))