packages feed

blaze-builder-conduit (empty) → 0.0.0

raw patch · 5 files changed

+239/−0 lines, 5 filesdep +HUnitdep +QuickCheckdep +basesetup-changed

Dependencies added: HUnit, QuickCheck, base, blaze-builder, blaze-builder-conduit, bytestring, conduit, containers, hspec, text, transformers

Files

+ Data/Conduit/Blaze.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE BangPatterns #-}+-- | Convert a stream of blaze-builder @Builder@s into a stream of @ByteString@s.+--+-- 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 @IO@ or+-- @ST@.+module Data.Conduit.Blaze+    (++  -- * 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 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++-- | Incrementally execute builders and pass on the filled chunks as+-- bytestrings.+builderToByteString :: ResourceUnsafeIO m => Conduit Builder m S.ByteString+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 conduit yields bytestrings that are NOT+-- referentially transparent. Their content will be overwritten as soon+-- as control is returned from the inner sink!+unsafeBuilderToByteString :: ResourceUnsafeIO m+                          => IO Buffer  -- action yielding the inital buffer.+                          -> Conduit Builder m S.ByteString+unsafeBuilderToByteString = builderToByteStringWith . reuseBufferStrategy+++-- | 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.+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'+                    {-# INLINE cont #-}+                    cont front' = 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' <- 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'
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Michael Snoyman++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Michael Snoyman nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,7 @@+#!/usr/bin/env runhaskell++> module Main where+> import Distribution.Simple++> main :: IO ()+> main = defaultMain
+ blaze-builder-conduit.cabal view
@@ -0,0 +1,44 @@+Name:                blaze-builder-conduit+Version:             0.0.0+Synopsis:            Convert streams of builders to streams of bytestrings.+Description:         Convert streams of builders to streams of bytestrings.+License:             BSD3+License-file:        LICENSE+Author:              Michael Snoyman+Maintainer:          michael@snoyman.com+Category:            Data, Conduit+Build-type:          Simple+Cabal-version:       >=1.8+Homepage:            http://github.com/snoyberg/conduit+extra-source-files:  test/main.hs++Library+  Exposed-modules:     Data.Conduit.Blaze+  Build-depends:       base                     >= 4            && < 5+                     , containers+                     , transformers             >= 0.2.2        && < 0.3+                     , bytestring               >= 0.9+                     , text                     >= 0.11+                     , blaze-builder            >= 0.2.1.4      && < 0.4+                     , conduit                  >= 0.0          && < 0.1+  ghc-options:     -Wall++test-suite test+    hs-source-dirs: test+    main-is: main.hs+    type: exitcode-stdio-1.0+    cpp-options:   -DTEST+    build-depends:   conduit+                   , base+                   , hspec+                   , HUnit+                   , QuickCheck+                   , bytestring+                   , blaze-builder+                   , blaze-builder-conduit+                   , transformers+    ghc-options:     -Wall++source-repository head+  type:     git+  location: git://github.com/snoyberg/conduit.git
+ test/main.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}+import Test.Hspec.Monadic+import Test.Hspec.HUnit ()+import Test.Hspec.QuickCheck (prop)+import Test.HUnit++import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import Data.ByteString.Char8 ()+import Data.Conduit.Blaze (builderToByteString)+import Data.Conduit (runResourceT)+import Control.Monad.ST (runST)+import Data.Monoid+import qualified Data.ByteString as S+import Blaze.ByteString.Builder (fromByteString, toLazyByteString, insertLazyByteString)+import qualified Data.ByteString.Lazy as L+import Data.ByteString.Lazy.Char8 ()+import Control.Monad.IO.Class (liftIO)++main :: IO ()+main = hspecX $ do+    describe "blaze" $ do+        prop "idempotent to toLazyByteString" $ \bss' -> runST $ runResourceT $ do+            let bss = map S.pack bss'+            let builders = map fromByteString bss+            let lbs = toLazyByteString $ mconcat builders+            let src = mconcat $ map (CL.sourceList . return) builders+            outBss <- src C.$= builderToByteString C.$$ CL.consume+            return $ lbs == L.fromChunks outBss++        it "works for large input" $ runResourceT $ do+            let builders = replicate 10000 (fromByteString "hello world!")+            let lbs = toLazyByteString $ mconcat builders+            let src = mconcat $ map (CL.sourceList . return) builders+            outBss <- src C.$= builderToByteString C.$$ CL.consume :: C.ResourceT IO [S.ByteString]+            liftIO $ lbs @=? L.fromChunks outBss++        it "works for lazy bytestring insertion" $ runResourceT $ do+            let builders = replicate 10000 (insertLazyByteString "hello world!")+            let lbs = toLazyByteString $ mconcat builders+            let src = mconcat $ map (CL.sourceList . return) builders+            outBss <- src C.$= builderToByteString C.$$ CL.consume :: C.ResourceT IO [S.ByteString]+            liftIO $ lbs @=? L.fromChunks outBss