HORIZON HASKELLDocslts/ghc-9.10.x248f8f02026-10-05Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · 248f8f0 · 2026-10-05

Modulererebase-1.21.2Haskell2010

Data.ByteString.Builder.Internal

  • 8 types
  • 43 values
  • Packagererebase-1.21.2
  • Exports51
  • LanguageHaskell2010
  • LicenceMIT
  • SourceInternal.hs
newtypenewtype Builder
#

Builders denote sequences of bytes. They are Monoids where mempty is the zero-length sequence and mappend is concatenation, which runs in O(1).

Instances6IsList, Show, IsString, Semigroup, Monoid, Item
  • IsList BuilderDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal

    For long or infinite lists use fromList because it uses LazyByteString otherwise use fromListN which uses StrictByteString.

  • Show BuilderDefined in bytestring-0.12.2.0 · Data.ByteString.Builder · orphan
  • IsString BuilderDefined in bytestring-0.12.2.0 · Data.ByteString.Builder · orphan
  • Semigroup BuilderDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
  • Monoid BuilderDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
  • type Item Builder = Word8Defined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
datadata Buffer
#

A Buffer together with the BufferRange of free bytes. The filled space starts at offset 0 and ends at the first free byte.

Instances1NFData
  • NFData BufferDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal

    Like the NFData instance for StrictByteString, this does not force the ForeignPtrContents field of the underlying ForeignPtr.

valueempty :: Builder
#

The Builder denoting a zero-length sequence of bytes. This function is only exported for use in rewriting rules. Use mempty otherwise.

valueput
  1. :: (forall r. (a -> BuildStep r) -> BuildStep r)

    A function that fills a BufferRange, calls the continuation with the updated BufferRange and its computed value once its done, and signals its caller how to proceed using done, bufferFull, or insertChunk signals.

    This function must be referentially transparent; i.e., calling it multiple times with equally sized BufferRanges must result in the same sequence of bytes being written and the same value being computed. If you need mutable state, then you must allocate it anew upon each call of this function. Moreover, this function must call the continuation once its done. Otherwise, monadic sequencing of Puts does not work. Finally, this function must write to all bytes that it claims it has written. Otherwise, the resulting Put is not guaranteed to be referentially transparent and sensitive data might leak.

  2. -> Put a
#

Construct a Put action. In contrast to BuildSteps, Puts are referentially transparent in the sense that sequencing the same Put multiple times yields every time the same value with the same side-effect.

newtypenewtype Put a
#

A Put action denotes a computation of a value that writes a stream of bytes as a side-effect. Puts are strict in their side-effect; i.e., the stream of bytes will always be written before the computed value is returned.

Puts are a generalization of Builders. The typical use case is the implementation of an encoding that might fail (e.g., an interface to the zlib compression library or the conversion from Base64 encoded data to 8-bit data). For a Builder, the only way to handle and report such a failure is ignore it or call error. In contrast, Put actions are expressive enough to allow reporting and handling such a failure in a pure fashion.

Put () actions are isomorphic to Builders. The functions putBuilder and fromPut convert between these two types. Where possible, you should use Builders, as sequencing them is slightly cheaper than sequencing Puts because they do not carry around a computed value.

Instances3Monad, Functor, Applicative
  • Monad PutDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
  • Functor PutDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
  • Applicative PutDefined in bytestring-0.12.2.0 · Data.ByteString.Builder.Internal
datadata BufferRange
#

A range of bytes in a buffer represented by the pointer to the first byte of the range and the pointer to the first byte after the range.

Constructors

Instances1NFData
valuehPut :: Handle -> Put a -> IO a
#

Run a Put action redirecting the produced output to a Handle.

The output is buffered using the Handles associated buffer. If this buffer is too small to execute one step of the Put action, then it is replaced with a large enough buffer.

valuedefaultChunkSize :: Int
#

The chunk size used for I/O. Currently set to 32k, less the memory management overhead

valuesmallChunkSize :: Int
#

The recommended chunk size. Currently set to 4k, less the memory management overhead

valueflush :: Builder
#

Flush the current buffer. This introduces a chunk boundary.

valuechunkOverhead :: Int
#

The memory management overhead. Currently this is tuned for GHC only.

valuebuilder
  1. :: (forall r. BuildStep r -> BuildStep r)

    A function that fills a BufferRange, calls the continuation with the updated BufferRange once its done, and signals its caller how to proceed using done, bufferFull, or insertChunk.

    This function must be referentially transparent; i.e., calling it multiple times with equally sized BufferRanges must result in the same sequence of bytes being written. If you need mutable state, then you must allocate it anew upon each call of this function. Moreover, this function must call the continuation once its done. Otherwise, concatenation of Builders does not work. Finally, this function must write to all bytes that it claims it has written. Otherwise, the resulting Builder is not guaranteed to be referentially transparent and sensitive data might leak.

  2. -> Builder
#

Construct a Builder. In contrast to BuildSteps, Builders are referentially transparent.

Construct a Builder that copies the StrictByteStrings, if it is smaller than the treshold, and inserts it directly otherwise.

For example, byteStringThreshold 1024 copies StrictByteStrings whose size is less or equal to 1kb, and inserts them directly otherwise. This implies that the average chunk-size of the generated LazyByteString may be as low as 513 bytes, as there could always be just a single byte between the directly inserted 1025 byte, StrictByteStrings.

valuecustomStrategy
  1. :: (Maybe (Buffer, Int) -> IO Buffer)

    Buffer allocation function.

    • If Nothing is given, then a new first buffer should be allocated.

    • If Just (oldBuf, minSize) is given, then a buffer with minimal size minSize must be returned. The strategy may reuse oldBuf only if oldBuf is large enough and the consumer can guarantee that this will not result in a violation of referential transparency.

    Warning: for multithreaded programs, it is generally unsafe to reuse buffers when using the consumers of Builder in this package. For example, if toLazyByteStringWith is called with an AllocationStrategy that reuses buffers, evaluating the result by multiple threads simultaneously may lead to corrupted output.

  2. -> Int

    Default buffer size.

  3. -> (Int -> Int -> Bool)

    A predicate trim used allocated returning True, if the buffer should be trimmed before it is returned.

  4. -> AllocationStrategy
#

Create a custom allocation strategy. See the code for safeStrategy and untrimmedStrategy for examples.

valueputToLazyByteString
  1. :: Put a

    Put to execute

  2. -> (a, LazyByteString)

    Result and LazyByteString written as its side-effect

#

Execute a Put and return the computed result and the bytes written during the computation as a LazyByteString.

This function is strict in the computed result and lazy in the writing of the bytes. For example, given

infinitePut = sequence_ (repeat (putBuilder (word8 1))) >> return 0
 

evaluating the expression

fst $ putToLazyByteString infinitePut
 

does not terminate, while evaluating the expression

L.head $ snd $ putToLazyByteString infinitePut
 

does terminate and yields the value 1 :: Word8.

An illustrative example for these strictness properties is the implementation of Base64 decoding (http://en.wikipedia.org/wiki/Base64).

type DecodingState = ...

decodeBase64 :: StrictByteString -> DecodingState -> Put (Maybe DecodingState)
decodeBase64 = ...
 

The above function takes a StrictByteString supposed to represent Base64 encoded data and the current decoding state. It writes the decoded bytes as the side-effect of the Put and returns the new decoding state, if the decoding of all data in the StrictByteString was successful. The checking if the StrictByteString represents Base64 encoded data and the actual decoding are fused. This makes the common case, where all data represents Base64 encoded data, more efficient. It also implies that all data must be decoded before the final decoding state can be returned. Puts are intended for implementing such fused checking and decoding/encoding, which is reflected in their strictness properties.

valueputToLazyByteStringWith
  1. :: AllocationStrategy

    Buffer allocation strategy to use

  2. -> (a -> (b, LazyByteString))

    Continuation to use for computing the final result and the tail of its side-effect (the written bytes).

  3. -> Put a

    Put to execute

  4. -> (b, LazyByteString)

    Resulting LazyByteString

#

Execute a Put with a buffer-allocation strategy and a continuation. For example, putToLazyByteString is implemented as follows.

putToLazyByteString = putToLazyByteStringWith
    (safeStrategy smallChunkSize defaultChunkSize) (x -> (x, L.empty))
 
valuesafeStrategy
  1. :: Int

    Size of first buffer

  2. -> Int

    Size of successive buffers

  3. -> AllocationStrategy

    An allocation strategy that guarantees that at least half of the allocated memory is used for live data

#

Use this strategy for generating LazyByteStrings whose chunks are likely to survive one garbage collection. This strategy trims buffers that are filled less than half in order to avoid spilling too much memory.

valuetoLazyByteStringWith
  1. :: AllocationStrategy

    Buffer allocation strategy to use

  2. -> LazyByteString

    LazyByteString to use as the tail of the generated lazy LazyByteString

  3. -> Builder

    Builder to execute

  4. -> LazyByteString

    Resulting LazyByteString

#

Heavy inlining. Execute a Builder with custom execution parameters.

This function is inlined despite its heavy code-size to allow fusing with the allocation strategy. For example, the default Builder execution function toLazyByteString is defined as follows.

{-# NOINLINE toLazyByteString #-}
toLazyByteString =
  toLazyByteStringWith (safeStrategy smallChunkSize defaultChunkSize) L.Empty

where L.Empty is the zero-length LazyByteString.

In most cases, the parameters used by toLazyByteString give good performance. A sub-performing case of toLazyByteString is executing short (<128 bytes) Builders. In this case, the allocation overhead for the first 4kb buffer and the trimming cost dominate the cost of executing the Builder. You can avoid this problem using

toLazyByteStringWith (safeStrategy 128 smallChunkSize) L.Empty

This reduces the allocation and trimming overhead, as all generated LazyByteStrings fit into the first buffer and there is no trimming required, if more than 64 bytes and less than 128 bytes are written.

valueuntrimmedStrategy
  1. :: Int

    Size of the first buffer

  2. -> Int

    Size of successive buffers

  3. -> AllocationStrategy

    An allocation strategy that does not trim any of the filled buffers before converting it to a chunk

#

Use this strategy for generating LazyByteStrings whose chunks are discarded right after they are generated. For example, if you just generate them to write them to a network socket.