@@ -17,7 +17,7 @@ module Network.Wai.Enumerator
1717 , fromEitherFile
1818 ) where
1919
20−import Network.Wai (Enumerator)
20+import Network.Wai (Enumerator (..))
2121import qualified Data.ByteString.Lazy as L
2222import qualified Data.ByteString as B
2323import System.IO.Unsafe (unsafeInterleaveIO)
@@ -28,13 +28,13 @@ import Control.Concurrent.MVar
2828
2929-- | Performs a specified conversion on each 'B.ByteString' output by an
3030-- enumerator.
31−mapE :: (B.ByteString -> B.ByteString) -> Enumerator a -> Enumerator a
32−mapE f e iter = e iter' where
33− iter' a = iter a . f
31+mapE :: (B.ByteString -> B.ByteString) -> Enumerator -> Enumerator
32+mapE f (Enumerator e) = Enumerator $ \iter -> e (iter' iter) where
33+ iter' iter a = iter a . f
3434
3535-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
3636-- normal lazy I/O warnings apply.
37−toLBS :: Enumerator () -> IO L.ByteString
37+toLBS :: Enumerator -> IO L.ByteString
3838toLBS e = do
3939 source <- toSource e
4040 L.fromChunks `fmap` helper source
@@ -48,26 +48,27 @@ toLBS e = do
4848 return $ x' : xs
4949
5050-- | This function safely converts a lazy bytestring into an enumerator.
51−fromLBS :: L.ByteString -> (forall a. Enumerator a)
52−fromLBS lbs iter a0 = helper a0 $ L.toChunks lbs where
53− helper a [] = return $ Right a
54− helper a (x:xs) = do
51+fromLBS :: L.ByteString -> Enumerator
52+fromLBS lbs = Enumerator $ \iter a0 -> helper iter a0 $ L.toChunks lbs where
53+ helper _ a [] = return $ Right a
54+ helper iter a (x:xs) = do
5555 ea <- iter a x
5656 case ea of
5757 Left a' -> return $ Left a'
58− Right a' -> helper a' xs
58+ Right a' -> helper iter a' xs
5959
6060-- | Same as 'fromLBS', but the lazy bytestring is in the IO monad. This allows
6161-- you to lazily read a file into memory, perform some mapping on the data and
6262-- convert it into an enumerator.
63−fromLBS' :: IO L.ByteString -> (forall a. Enumerator a)
64−fromLBS' lbs' iter a0 = lbs' >>= \lbs -> fromLBS lbs iter a0
63+fromLBS' :: IO L.ByteString -> Enumerator
64+fromLBS' lbs' = Enumerator $ \iter a0 -> lbs' >>= \lbs ->
65+ runEnumerator (fromLBS lbs) iter a0
6566
6667-- | A source is a more standard way of accessing data from an 'Enumerator'.
6768-- Each time you call it, it returns the next chunk of data if available, or
6869-- 'Nothing' if the data has been completely consumed.
69−toSource :: Enumerator () -> IO (IO (Maybe B.ByteString))
70−toSource e = do
70+toSource :: Enumerator -> IO (IO (Maybe B.ByteString))
71+toSource (Enumerator e) = do
7172 buffer <- newEmptyMVar
7273 _ <- forkIO $ e (helper buffer) () >> putMVar buffer Nothing
7374 return $ source buffer
@@ -93,8 +94,8 @@ toSource e = do
9394-- | Read a chunk of data from the given 'Handle' at a time. We use
9495-- 'defaultChunkSize' from the bytestring package to determine the largest
9596-- chunk to take.
96−fromHandle :: Handle -> Enumerator a
97−fromHandle h iter a = do
97+fromHandle :: Handle -> Enumerator
98+fromHandle h = Enumerator $ \iter a -> do
9899 eof <- hIsEOF h
99100 if eof
100101 then return $ Right a
@@ -103,14 +104,15 @@ fromHandle h iter a = do
103104 ea' <- iter a bs
104105 case ea' of
105106 Left a' -> return $ Left a'
106− Right a' -> fromHandle h iter a'
107+ Right a' -> runEnumerator (fromHandle h) iter a'
107108
108109-- | A little wrapper around 'fromHandle' which first opens a file for reading.
109−fromFile :: FilePath -> Enumerator a
110−fromFile fp iter a0 = withBinaryFile fp ReadMode $ \h -> fromHandle h iter a0
110+fromFile :: FilePath -> Enumerator
111+fromFile fp = Enumerator $ \iter a0 -> withBinaryFile fp ReadMode $ \h ->
112+ runEnumerator (fromHandle h) iter a0
111113
112114-- | Since the response body is defined as an 'Either' 'FilePath' 'Enumerator',
113115-- this function simply reduces the whole operator to an enumerator. This can
114116-- be convenient for server implementations not optimizing file sending.
115−fromEitherFile :: Either FilePath (Enumerator a) -> Enumerator a
117+fromEitherFile :: Either FilePath Enumerator -> Enumerator
116118fromEitherFile = either fromFile id