@@ -0,0 +1,44 @@
1+-- | A collection of utility functions for dealing with 'Enumerator's.
2+module Network.Wai.Enumerator
3+ ( -- * Lazy byte strings
4+ toLBS
5+ , fromLBS
6+ , fromLBS'
7+ -- * Source
8+ , toSource
9+ ) where
10+
11+import Network.Wai (Enumerator)
12+import qualified Data.ByteString.Lazy as L
13+import qualified Data.ByteString as B
14+import System.IO.Unsafe (unsafeInterleaveIO)
15+
16+-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
17+-- normal lazy I/O warnings apply.
18+toLBS :: Enumerator (Maybe B.ByteString) -> IO L.ByteString
19+toLBS e = L.fromChunks `fmap` helper where
20+ helper = unsafeInterleaveIO $ do
21+ x <- toSource e
22+ case x of
23+ Nothing -> return []
24+ Just x' -> do
25+ xs <- helper
26+ return $ x' : xs
27+
28+fromLBS :: L.ByteString -> Enumerator a
29+fromLBS lbs iter a0 = helper a0 $ L.toChunks lbs where
30+ helper a [] = return a
31+ helper a (x:xs) = do
32+ ea <- iter a x
33+ case ea of
34+ Left a' -> return a'
35+ Right a' -> helper a' xs
36+
37+fromLBS' :: IO L.ByteString -> Enumerator a
38+fromLBS' lbs' iter a0 = lbs' >>= \lbs -> fromLBS lbs iter a0
39+
40+-- | A source is a more standard way of accessing data from an 'Enumerator'.
41+-- Each time you call it, it returns the next chunk of data if available, or
42+-- 'Nothing' if the data has been completely consumed.
43+toSource :: Enumerator (Maybe B.ByteString) -> IO (Maybe B.ByteString)
44+toSource e = e (const $ return . Left . Just) Nothing