blaze-builder-enumerator 0.1 → 0.2.0.0
raw patch · 2 files changed
+194/−33 lines, 2 filesdep +transformersdep ~blaze-builderdep ~enumeratornew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: transformers
Dependency ranges changed: blaze-builder, enumerator
API changes (from Hackage documentation)
- Blaze.ByteString.Builder.Enumerator: iterBuilder :: Monad m => (a -> Builder) -> Iteratee a m ByteString
+ Blaze.ByteString.Builder.Enumerator: allNewBuffersStrategy :: Int -> BufferAllocStrategy
+ Blaze.ByteString.Builder.Enumerator: allocBuffer :: Int -> IO Buffer
+ Blaze.ByteString.Builder.Enumerator: bufferSize :: Buffer -> Int
+ Blaze.ByteString.Builder.Enumerator: builderToByteString :: MonadIO m => Enumeratee Builder ByteString m a
+ Blaze.ByteString.Builder.Enumerator: builderToByteStringWith :: MonadIO m => BufferAllocStrategy -> Enumeratee Builder ByteString m a
+ Blaze.ByteString.Builder.Enumerator: data Buffer :: *
+ Blaze.ByteString.Builder.Enumerator: freeSize :: Buffer -> Int
+ Blaze.ByteString.Builder.Enumerator: nextSlice :: Int -> Buffer -> Maybe Buffer
+ Blaze.ByteString.Builder.Enumerator: reuseBuffer :: Buffer -> Buffer
+ Blaze.ByteString.Builder.Enumerator: reuseBufferStrategy :: IO Buffer -> BufferAllocStrategy
+ Blaze.ByteString.Builder.Enumerator: sliceSize :: Buffer -> Int
+ Blaze.ByteString.Builder.Enumerator: type BufferAllocStrategy = (IO Buffer, Int -> Buffer -> IO (IO Buffer))
+ Blaze.ByteString.Builder.Enumerator: unsafeBuilderToByteString :: MonadIO m => IO Buffer -> Enumeratee Builder ByteString m a
+ Blaze.ByteString.Builder.Enumerator: unsafeFreezeBuffer :: Buffer -> ByteString
+ Blaze.ByteString.Builder.Enumerator: unsafeFreezeNonEmptyBuffer :: Buffer -> Maybe ByteString
Files
- Blaze/ByteString/Builder/Enumerator.hs +174/−19
- blaze-builder-enumerator.cabal +20/−14
Blaze/ByteString/Builder/Enumerator.hs view
@@ -1,28 +1,183 @@+{-# LANGUAGE BangPatterns #-} --------------------------------------------------------------------------------- | +-- | -- Module : Blaze.ByteString.Builder.Enumerator+-- Copyright : (c) 2010 Simon Meier -- License : BSD3--- Maintainer : Thomas Sutton <me@thomas-sutton.id.au>+--+-- Maintainer : Simon Meier <iridcode@gmail.com> -- Stability : Experimental--- Portability : Unknown+-- Portability : Tested on GHC only ----- Simplify the process of using @blaze-builder@ with @enumerator@ by --- converting functions that construct 'Builder's into 'Iteratee's.+-- Infrastructure and enumeratees for the incremental execution of builders and+-- passing on of the filled chunks as bytestrings to an inner iteratee.+--+-- Note that the @Buffer@ code is likely to move/change in order to+-- reconciliate it with the rest of the blaze-builder library.+-- ------------------------------------------------------------------------------ -module Blaze.ByteString.Builder.Enumerator where -import Blaze.ByteString.Builder-import qualified Data.ByteString as B-import Data.Enumerator+module Blaze.ByteString.Builder.Enumerator ( --- | Convert a function that returns a @blaze-builder@ 'Builder' into an --- 'Iteratee'. Each incoming value will be converted into a 'ByteString'.-iterBuilder :: Monad m => (a -> Builder) -> Iteratee a m B.ByteString-iterBuilder builder = continue (step builder)- where- step :: Monad m => (a -> Builder) -> Stream a -> Iteratee a m B.ByteString- step b input = case input of- EOF -> yield (B.empty) EOF- Chunks [] -> continue (step b)- Chunks (v:vs) -> yield (toByteString $ b v) (Chunks vs)+ -- * Buffers+ Buffer++ -- ** Status information+ , freeSize + , sliceSize + , bufferSize ++ -- ** Creation and modification+ , allocBuffer + , reuseBuffer + , nextSlice ++ -- ** Conversion to bytestings+ , unsafeFreezeBuffer + , unsafeFreezeNonEmptyBuffer ++ -- * Buffer allocation strategies+ , BufferAllocStrategy+ , allNewBuffersStrategy + , reuseBufferStrategy ++ -- * Enumeratees from builders to bytestrings+ , builderToByteString + , unsafeBuilderToByteString + , builderToByteStringWith ++ ) where++import qualified Data.ByteString as S+import Data.Enumerator hiding (map)+import Data.Monoid++import Control.Monad.IO.Class++import Blaze.ByteString.Builder.Internal+import Blaze.ByteString.Builder.Internal.Types+import Blaze.ByteString.Builder.Internal.Buffer++------------------------------------------------------------------------------+-- Enumeratees for converting builders incrementally to bytestrings+------------------------------------------------------------------------------++-- Simple default instances+---------------------------++-- | Incrementally execute builders and pass on the filled chunks as+-- bytestrings.+builderToByteString :: MonadIO m => Enumeratee Builder S.ByteString m a+builderToByteString = + builderToByteStringWith (allNewBuffersStrategy defaultBufferSize)++-- | 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 enumeratee yields bytestrings that are NOT+-- referentially transparent. Their content will be overwritten as soon+-- as control is returned from the inner iteratee!+unsafeBuilderToByteString :: MonadIO m+ => IO Buffer -- action yielding the inital buffer.+ -> Enumeratee Builder S.ByteString m a+unsafeBuilderToByteString = builderToByteStringWith . reuseBufferStrategy+++-- | An enumeratee that incrementally executes builders and passes on the+-- filled chunks as bytestrings to an inner iteratee.+--+-- INV: All bytestrings passed to the inner iteratee are non-empty.++--+-- based on the enumeratee code by Michael Snoyman <michael@snoyman.com>+--+builderToByteStringWith :: MonadIO m + => BufferAllocStrategy+ -> Enumeratee Builder S.ByteString m a+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'+ {-# INLINE cont #-}+ cont k' = do+ -- sequencing the computation of the next buffer+ -- construction here ensures that the reference to the+ -- foreign pointer `fp` is lost as soon as possible.+ 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' -- FIXME: Check that we don't loose any input here!+ 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' -- FIXME: Check that we don't loose any input here!++++{- Old testing code:+ +main :: IO ()+main = main1 >> main2 >> main3++main1 :: IO ()+main1 = do+ builder <- fromLazyByteString `fmap` L.readFile "test-input"+ withBinaryFile "test-output1" WriteMode $ \h -> run_ (go h builder)+ where+ go h builder = enumList 1 [builder]+ $$ joinI $ blaze+ $$ iterHandle h++main2 :: IO ()+main2 =+ withBinaryFile "test-output2" WriteMode $ \h -> run_ (go h)+ where+ go h = enumFile "test-input"+ $$ joinI $ E.map fromByteString+ $$ joinI $ blaze+ $$ iterHandle h++main3 :: IO ()+main3 =+ withBinaryFile "test-output3" WriteMode $ \h -> run_ (go h)+ where+ go h = enumList 1 (map S.singleton $ concat $ replicate 1000 [65..90])+ $$ joinI $ E.map (mconcat . map fromWord8 . S.unpack)+ $$ joinI $ blaze+ $$ iterHandle h++-}
blaze-builder-enumerator.cabal view
@@ -1,34 +1,40 @@ Name : blaze-builder-enumerator-Version : 0.1-Synopsis : Use blaze-builder Builder's in an Iteratee.+Version : 0.2.0.0+Synopsis : Enumeratees for the incremental conversion of builders to+ bytestrings. Description : - This package simplifies the process of using blaze-builder with the- enumerator package by converting a function that constructs a Builder into- an Iteratee.+ This package integrates the builders from the blaze-builder package with+ the enumerator package. It provides infrastructure and enumeratees for+ incrementally executing builders and pass the filled chunks to a bytestring+ iteratee. -Author : Thomas Sutton <me@thomas-sutton.id.au>-Maintainer : me@thomas-sutton.id.au-Copyright : Copyright (c) Thomas Sutton 2010+Author : Simon Meier <iridcode@gmail.com>+Maintainer : Simon Meier <iridcode@gmail.com>+Copyright : Copyright (c) 2010 Simon Meier+ + original package by Thomas Sutton <me@thomas-sutton.id.au>+ License : BSD3 License-file : LICENSE Build-type : Simple Cabal-version : >=1.6-Category : Data, Text, Enumerator+Category : Data, Enumerator Stability : Experimental-Bug-reports : mailto:me@thomas-sutton.id.au-Homepage : http://github.com/thsutton/blaze-builder-enumerator+Bug-reports : https://github.com/meiersi/blaze-builder-enumerator+Homepage : https://github.com/meiersi/blaze-builder-enumerator Source-repository head Type: git- Location: https://github.com/thsutton/blaze-builder-enumerator.git+ Location: https://github.com/meiersi/blaze-builder-enumerator.git Library GHC-options: -Wall -fno-warn-unused-do-bind Build-depends: base >= 4 && < 5- , blaze-builder >= 0.2 && < 0.3+ , blaze-builder >= 0.2.1 && < 0.3 , bytestring >= 0.9 && < 0.10- , enumerator >= 0.4 && < 0.5+ , enumerator >= 0.4.3.1 && < 0.5+ , transformers >= 0.2 && < 0.3 Exposed-modules: Blaze.ByteString.Builder.Enumerator