The use of this function depends on how the resulting bytestrings are
consumed. flush is possibly not very useful in non-interactive scenarios.
However, it is kept for compatibility with the builder provided by
Data.Binary.Builder.

When using toLazyByteString to extract a lazy ByteString from a
Builder, this means that a new chunk will be started in the resulting lazy
ByteString. The remaining part of the buffer is spilled, if the
reamining free space is smaller than the minimal desired buffer size.

Use this function for integrating the Builder type with other libraries
that generate lazy bytestrings.

Note that the builders should guarantee that on average the desired chunk
size is attained. Builders may decide to start a new buffer and not
completely fill the existing buffer, if this is faster. However, they should
not spill too much of the buffer, if they cannot compensate for it.

A call toLazyByteStringWith bufSize minBufSize firstBufSize will generate
a lazy bytestring according to the following strategy. First, we allocate
a buffer of size firstBufSize and start filling it. If it overflows, we
allocate a buffer of size minBufSize and copy the first buffer to it in
order to avoid generating a too small chunk. Finally, every next buffer will
be of size bufSize. This, slow startup strategy is required to achieve
good speed for short (<200 bytes) resulting bytestrings, as for them the
allocation cost is of a large buffer cannot be compensated. Moreover, this
strategy also allows us to avoid spilling too much memory for short
resulting bytestrings.

Note that setting firstBufSize >= minBufSize implies that the first buffer
is no longer copied but allocated and filled directly. Hence, setting
firstBufSize = bufSize means that all chunks will use an underlying buffer
of size bufSize. This is recommended, if you know that you always output
more than minBufSize bytes.

Run the builder to construct a strict bytestring containing the sequence
of bytes denoted by the builder. This is done by first serializing to a lazy bytestring and then packing its
chunks to a appropriately sized strict bytestring.

toByteStringIOWith bufSize io b runs the builder b with a buffer of
at least the size bufSize and executes the IO action io whenever the
buffer is full.

Compared to toLazyByteStringWith this function requires less allocation,
as the output buffer is only allocated once at the start of the
serialization and whenever something bigger than the current buffer size has
to be copied into the buffer, which should happen very seldomly for the
default buffer size of 32kb. Hence, the pressure on the garbage collector is
reduced, which can be an advantage when building long sequences of bytes.

The maximal number of bytes for that copying is cheaper than direct
insertion into the output stream. This takes into account the fragmentation
that may occur in the output buffer due to the early flush implied by the
direct bytestring insertion.