module Data.Conduit.Blaze
(
Buffer
, freeSize
, sliceSize
, bufferSize
, allocBuffer
, reuseBuffer
, nextSlice
, unsafeFreezeBuffer
, unsafeFreezeNonEmptyBuffer
, BufferAllocStrategy
, allNewBuffersStrategy
, reuseBufferStrategy
, builderToByteString
, unsafeBuilderToByteString
, builderToByteStringWith
) where
import Data.Conduit hiding (SinkResult (Done))
import Control.Monad.Trans.Resource
import Control.Monad.Trans.Class
import qualified Data.ByteString as S
import Blaze.ByteString.Builder.Internal
import Blaze.ByteString.Builder.Internal.Types
import Blaze.ByteString.Builder.Internal.Buffer
builderToByteString :: ResourceUnsafeIO m => Conduit Builder m S.ByteString
builderToByteString =
builderToByteStringWith (allNewBuffersStrategy defaultBufferSize)
unsafeBuilderToByteString :: ResourceUnsafeIO m
=> IO Buffer
-> Conduit Builder m S.ByteString
unsafeBuilderToByteString = builderToByteStringWith . reuseBufferStrategy
builderToByteStringWith :: ResourceUnsafeIO m
=> BufferAllocStrategy
-> Conduit Builder m S.ByteString
builderToByteStringWith (ioBuf0, nextBuf) = conduitState
ioBuf0
push
close
where
finalStep !(BufRange pf _) = return $ Done pf ()
close ioBuf = lift $ unsafeFromIO $ do
buf <- ioBuf
return $ maybe [] return $ unsafeFreezeNonEmptyBuffer buf
push ioBuf x = lift $ unsafeFromIO $ do
(ioBuf', front) <- go (unBuilder x (buildStep finalStep)) ioBuf id
return (ioBuf', Producing $ front [])
go bStep ioBuf front = do
!buf <- ioBuf
signal <- (execBuildStep bStep buf)
case signal of
Done op' _ -> return (return $ updateEndOfSlice buf op', front)
BufferFull minSize op' bStep' -> do
let buf' = updateEndOfSlice buf op'
cont front' = do
ioBuf' <- nextBuf minSize buf'
go bStep' ioBuf' front'
case unsafeFreezeNonEmptyBuffer buf' of
Nothing -> cont front
Just bs -> cont (front . (bs:))
InsertByteString op' bs bStep' -> do
let buf' = updateEndOfSlice buf op'
bsk = maybe id (:) $ unsafeFreezeNonEmptyBuffer buf'
front' = front . bsk . (bs:)
ioBuf' <- nextBuf 1 buf'
go bStep' ioBuf' front'