module Blaze.ByteString.Builder.Enumerator (
Buffer
, freeSize
, sliceSize
, bufferSize
, allocBuffer
, reuseBuffer
, nextSlice
, unsafeFreezeBuffer
, unsafeFreezeNonEmptyBuffer
, BufferAllocStrategy
, allNewBuffersStrategy
, reuseBufferStrategy
, builderToByteString
, unsafeBuilderToByteString
, builderToByteStringWith
) where
import qualified Data.ByteString as S
import Data.Enumerator hiding (map)
import Data.Monoid
import Control.Monad.IO.Class
#if MIN_VERSION_blaze_builder(0,4,0)
import Blaze.ByteString.Builder
import Data.ByteString.Builder.Extra
import Data.Streaming.ByteString.Builder.Buffer
import Foreign.Ptr
#else /* !MIN_VERSION_blaze_builder(0,4,0) */
import Blaze.ByteString.Builder.Internal
import Blaze.ByteString.Builder.Internal.Types
import Blaze.ByteString.Builder.Internal.Buffer
#endif /* !MIN_VERSION_blaze_builder(0,4,0) */
builderToByteString :: MonadIO m => Enumeratee Builder S.ByteString m a
builderToByteString =
#if MIN_VERSION_blaze_builder(0,4,0)
builderToByteStringWith (allNewBuffersStrategy defaultChunkSize)
#else /* !MIN_VERSION_blaze_builder(0,4,0) */
builderToByteStringWith (allNewBuffersStrategy defaultBufferSize)
#endif /* !MIN_VERSION_blaze_builder(0,4,0) */
unsafeBuilderToByteString :: MonadIO m
=> IO Buffer
-> Enumeratee Builder S.ByteString m a
unsafeBuilderToByteString = builderToByteStringWith . reuseBufferStrategy
builderToByteStringWith :: MonadIO m
=> BufferAllocStrategy
-> Enumeratee Builder S.ByteString m a
#if MIN_VERSION_blaze_builder(0,4,0)
builderToByteStringWith (ioBuf0, nextBuf) step0 = do
loop ioBuf0 step0
where
loop ioBuf = checkDone $ continue . step ioBuf
step :: MonadIO m => IO (Buffer)
-> (Stream S.ByteString -> Iteratee S.ByteString m b)
-> Stream Builder
-> Iteratee Builder m (Step S.ByteString m b)
step ioBuf k EOF = do
buf <- liftIO ioBuf
case unsafeFreezeNonEmptyBuffer buf of
Nothing -> yield (Continue k) EOF
Just bs -> k (Chunks [bs]) >>== flip yield EOF
step ioBuf k0 (Chunks xs) =
go (runBuilder (mconcat xs)) ioBuf k0
go bWriter ioBuf k = do
!buf@(Buffer _ _ op ope) <- liftIO ioBuf
(bytes, next) <- liftIO (bWriter op (ope `minusPtr` op))
let op' = op `plusPtr` bytes
case next of
Done -> continue $ step (return (updateEndOfSlice buf op')) k
More minSize bWriter' -> do
let buf' = updateEndOfSlice buf op'
cont k' = do
ioBuf' <- liftIO $ nextBuf minSize buf'
go bWriter' ioBuf' k'
case unsafeFreezeNonEmptyBuffer buf' of
Nothing -> cont k
Just bs ->
k (Chunks [bs]) >>== \step' ->
case step' of
Continue k' -> cont k'
_ -> return step'
Chunk bs bWriter' -> do
let buf' = updateEndOfSlice buf op'
bsk = maybe id (:) $ unsafeFreezeNonEmptyBuffer buf'
k (Chunks (bsk [bs])) >>== \step' ->
case step' of
Continue k' -> do
ioBuf' <- liftIO $ nextBuf 1 buf'
go bWriter' ioBuf' k'
_ -> return step'
#else /* !MIN_VERSION_blaze_builder(0,4,0) */
builderToByteStringWith (ioBuf0, nextBuf) step0 = do
loop ioBuf0 step0
where
loop ioBuf = checkDone $ continue . step ioBuf
step :: MonadIO m => IO (Buffer)
-> (Stream S.ByteString -> Iteratee S.ByteString m b)
-> Stream Builder
-> Iteratee Builder m (Step S.ByteString m b)
step ioBuf k EOF = do
buf <- liftIO ioBuf
case unsafeFreezeNonEmptyBuffer buf of
Nothing -> yield (Continue k) EOF
Just bs -> k (Chunks [bs]) >>== flip yield EOF
step ioBuf k0 (Chunks xs) =
go (unBuilder (mconcat xs) (buildStep finalStep)) ioBuf k0
where
finalStep !(BufRange pf _) = return $ Done pf ()
go bStep ioBuf k = do
!buf <- liftIO ioBuf
signal <- liftIO (execBuildStep bStep buf)
case signal of
Done op' _ -> continue $ step (return (updateEndOfSlice buf op')) k
BufferFull minSize op' bStep' -> do
let buf' = updateEndOfSlice buf op'
cont k' = do
ioBuf' <- liftIO $ nextBuf minSize buf'
go bStep' ioBuf' k'
case unsafeFreezeNonEmptyBuffer buf' of
Nothing -> cont k
Just bs ->
k (Chunks [bs]) >>== \step' ->
case step' of
Continue k' -> cont k'
_ -> return step'
InsertByteString op' bs bStep' -> do
let buf' = updateEndOfSlice buf op'
bsk = maybe id (:) $ unsafeFreezeNonEmptyBuffer buf'
k (Chunks (bsk [bs])) >>== \step' ->
case step' of
Continue k' -> do
ioBuf' <- liftIO $ nextBuf 1 buf'
go bStep' ioBuf' k'
_ -> return step'
#endif /* !MIN_VERSION_blaze_builder(0,4,0) */