packages feed

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 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