Convert a stream of blaze-builder
Builders into a stream of
Adapted from blaze-builder-enumerator, written by myself and Simon Meier.
Note that the functions here can work in any monad built on top of
- data Buffer
- freeSize :: Buffer -> Int
- sliceSize :: Buffer -> Int
- bufferSize :: Buffer -> Int
- allocBuffer :: Int -> IO Buffer
- reuseBuffer :: Buffer -> Buffer
- nextSlice :: Int -> Buffer -> Maybe Buffer
- unsafeFreezeBuffer :: Buffer -> ByteString
- unsafeFreezeNonEmptyBuffer :: Buffer -> Maybe ByteString
- type BufferAllocStrategy = (IO Buffer, Int -> Buffer -> IO (IO Buffer))
- allNewBuffersStrategy :: Int -> BufferAllocStrategy
- reuseBufferStrategy :: IO Buffer -> BufferAllocStrategy
- builderToByteString :: MonadUnsafeIO m => Conduit Builder m ByteString
- unsafeBuilderToByteString :: MonadUnsafeIO m => IO Buffer -> Conduit Builder m ByteString
- builderToByteStringWith :: MonadUnsafeIO m => BufferAllocStrategy -> Conduit Builder m ByteString
- builderToByteStringFlush :: MonadUnsafeIO m => Conduit (Flush Builder) m (Flush ByteString)
- builderToByteStringWithFlush :: MonadUnsafeIO m => BufferAllocStrategy -> Conduit (Flush Builder) m (Flush ByteString)
Buffer fpbuf p0 op ope describes a buffer with the underlying
fpbuf..ope, the currently written slice
p0..op and the free
Creation and modification
Resets the beginning of the next slice and the next free byte such that the whole buffer can be filled again.
Move the beginning of the slice to the next free byte such that the remaining free space of the buffer can be filled further. This operation is safe and can be used to fill the remaining part of the buffer after a direct insertion of a bytestring or a flush.
Conversion to bytestings
Convert the buffer to a bytestring. This operation is unsafe in the sense that created bytestring shares the underlying byte array with the buffer. Hence, depending on the later use of this buffer (e.g., if it gets reset and filled again) referential transparency may be lost.
Convert a buffer to a non-empty bytestring. See
the explanation of why this operation may be unsafe.
Buffer allocation strategies
A buffer allocation strategy
(buf0, nextBuf) specifies the initial
buffer to use and how to compute a new buffer
nextBuf minSize buf with at
minSize from a filled buffer
buf. The double nesting of the
IO monad helps to ensure that the reference to the filled buffer
lost as soon as possible, but the new buffer doesn't have to be allocated
The simplest buffer allocation strategy: whenever a buffer is requested, allocate a new one that is big enough for the next build step to execute.
NOTE that this allocation strategy may spill quite some memory upon direct insertion of a bytestring by the builder. Thats no problem for garbage collection, but it may lead to unreasonably high memory consumption in special circumstances.
An unsafe, but possibly more efficient buffer allocation strategy: reuse the buffer, if it is big enough for the next build step to execute.
Conduits from builders to bytestrings
Incrementally execute builders and pass on the filled chunks as bytestrings.
Incrementally execute builders on the given buffer and pass on the filled chunks as bytestrings. Note that, if the given buffer is too small for the execution of a build step, a larger one will be allocated.
WARNING: This conduit yields bytestrings that are NOT referentially transparent. Their content will be overwritten as soon as control is returned from the inner sink!
A conduit that incrementally executes builders and passes on the filled chunks as bytestrings to an inner sink.
INV: All bytestrings passed to the inner sink are non-empty.