-- | An efficient implementation of ByteString builder.
--
-- In many cases, this module works as a drop-in replacement for
-- Data.ByteString.Builder, and should improve speed.
--
-- = Performance tips
--
-- fast-builder should be faster than the standard builder in most situations.
-- However, by following certain code patterns, you can often achive even
-- more efficient code, with almost no memory allocation aside from the
-- resulting 'ByteString' itself. The below are a list of hints for writing
-- efficient code for constructing builders.
--
-- == Return builders directly from your function
--
-- Once you construct a builder, it's usually a good idea to just return it from
-- your function. Avoid storing it in a data structure or passing it to another
-- function, unless they are going to be eliminated by the compiler.
-- Schematically, prefer this:
--
-- @
-- good :: YourDataStructure -> Builder
-- good d = serializeThis (this d) <> serializeThat (that d)
-- @
--
-- over:
--
-- @
-- bad0 :: YourDataStructure -> (Int, Builder)
-- bad0 d
--    = (compute d, serializeThis (this d) <> serializeThat (that d))
-- @
--
-- or:
--
-- @
-- bad1 :: YourDataStructure -> Builder
-- bad1 d = serializeMore d (serializeThis (this d))
-- @
--
-- An important special case of this general rule is to prefer foldr over
-- foldl' when serializing a list, and to prefer structural recursion over
-- tail recursion in general.
--
-- === Use 'rebuild'
--
-- When your function returns a different builder depending on the input,
-- it's usually a good idea to use 'rebuild' to wrap the whole body of your
-- function.  See the documentation for 'rebuild' for details.
--
-- === Background
--
-- Why is it good to return builders directly? It is because they are
-- implemented as functions. When storing a function in a data structure or
-- passing it around, you need to first allocate a closure for it. However,
-- if you are just returning it, the returned function can be merged with your
-- function, creating a function with a larger arity. For example, GHC can
-- compile the @good@ function above into a 5-ary function, which requires
-- no runtime allocation (the exact arity depends on the library version).
--
-- == Watch out for lazy ByteString generation
--
-- When using 'toLazyByteString', if you consume the result
-- in a bound thread, performance degrades significantly. See the
-- documentation for 'toLazyByteString' for details.
module Data.ByteString.FastBuilder
  (
  -- * The type

  Builder

  -- * Running a builder
  , toLazyByteString
  , toLazyByteStringWith
  , toStrictByteString
  , hPutBuilder
  , hPutBuilderLen
  , hPutBuilderWith

  -- * Performance tuning
  , rebuild

  -- * Basic builders
  , primBounded
  , primFixed
  , byteString
  , byteStringInsert
  , byteStringCopy
  , byteStringThreshold

  -- * Single byte
  , int8
  , word8

  -- * Little endian
  , int16LE
  , int32LE
  , int64LE

  , word16LE
  , word32LE
  , word64LE

  , floatLE
  , doubleLE

  -- * Big endian
  , int16BE
  , int32BE
  , int64BE

  , word16BE
  , word32BE
  , word64BE

  , floatBE
  , doubleBE

  -- * Host-dependent size and byte order, non-portable
  , intHost
  , int16Host
  , int32Host
  , int64Host

  , wordHost
  , word16Host
  , word32Host
  , word64Host

  , floatHost
  , doubleHost

  -- * Decimal
  , intDec
  , int8Dec
  , int16Dec
  , int32Dec
  , int64Dec

  , wordDec
  , word8Dec
  , word16Dec
  , word32Dec
  , word64Dec

  , integerDec
  , floatDec
  , doubleDec

  -- * Hexadecimal
  , wordHex
  , word8Hex
  , word16Hex
  , word32Hex
  , word64Hex

  -- * Fixed-width hexadecimal
  , int8HexFixed
  , int16HexFixed
  , int32HexFixed
  , int64HexFixed

  , word8HexFixed
  , word16HexFixed
  , word32HexFixed
  , word64HexFixed

  , floatHexFixed
  , doubleHexFixed

  -- * UTF-8
  , charUtf8
  , stringUtf8

  -- * ASCII
  , char7
  , string7

  -- * ISO-8859-1
  , char8
  , string8
  ) where

import Data.ByteString.FastBuilder.Internal
import Data.ByteString.FastBuilder.Internal.Prim