@@ -17,7 +17,7 @@ module Network.Wai.Enumerator
17 , fromEitherFile
17 , fromEitherFile
20−import Network.Wai (Enumerator)
20+import Network.Wai (Enumerator (..))
21import qualified Data.ByteString.Lazy as L
21import qualified Data.ByteString.Lazy as L
22import qualified Data.ByteString as B
22import qualified Data.ByteString as B
23import System.IO.Unsafe (unsafeInterleaveIO)
23import System.IO.Unsafe (unsafeInterleaveIO)
@@ -28,13 +28,13 @@ import Control.Concurrent.MVar
29-- | Performs a specified conversion on each 'B.ByteString' output by an
29-- | Performs a specified conversion on each 'B.ByteString' output by an
30-- enumerator.
30-- enumerator.
31−mapE :: (B.ByteString -> B.ByteString) -> Enumerator a -> Enumerator a
31+mapE :: (B.ByteString -> B.ByteString) -> Enumerator -> Enumerator
32−mapE f e iter = e iter' where
32+mapE f (Enumerator e) = Enumerator $ \iter -> e (iter' iter) where
33− iter' a = iter a . f
33+ iter' iter a = iter a . f
35-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
35-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
36-- normal lazy I/O warnings apply.
36-- normal lazy I/O warnings apply.
37−toLBS :: Enumerator () -> IO L.ByteString
37+toLBS :: Enumerator -> IO L.ByteString
38toLBS e = do
38toLBS e = do
39 source <- toSource e
39 source <- toSource e
40 L.fromChunks `fmap` helper source
40 L.fromChunks `fmap` helper source
@@ -48,26 +48,27 @@ toLBS e = do
48 return $ x' : xs
48 return $ x' : xs
50-- | This function safely converts a lazy bytestring into an enumerator.
50-- | This function safely converts a lazy bytestring into an enumerator.
51−fromLBS :: L.ByteString -> (forall a. Enumerator a)
51+fromLBS :: L.ByteString -> Enumerator
52−fromLBS lbs iter a0 = helper a0 $ L.toChunks lbs where
52+fromLBS lbs = Enumerator $ \iter a0 -> helper iter a0 $ L.toChunks lbs where
53− helper a [] = return $ Right a
53+ helper _ a [] = return $ Right a
54− helper a (x:xs) = do
54+ helper iter a (x:xs) = do
55 ea <- iter a x
55 ea <- iter a x
56 case ea of
56 case ea of
57 Left a' -> return $ Left a'
57 Left a' -> return $ Left a'
58− Right a' -> helper a' xs
58+ Right a' -> helper iter a' xs
60-- | Same as 'fromLBS', but the lazy bytestring is in the IO monad. This allows
60-- | Same as 'fromLBS', but the lazy bytestring is in the IO monad. This allows
61-- you to lazily read a file into memory, perform some mapping on the data and
61-- you to lazily read a file into memory, perform some mapping on the data and
62-- convert it into an enumerator.
62-- convert it into an enumerator.
63−fromLBS' :: IO L.ByteString -> (forall a. Enumerator a)
63+fromLBS' :: IO L.ByteString -> Enumerator
64−fromLBS' lbs' iter a0 = lbs' >>= \lbs -> fromLBS lbs iter a0
64+fromLBS' lbs' = Enumerator $ \iter a0 -> lbs' >>= \lbs ->
65+ runEnumerator (fromLBS lbs) iter a0
66-- | A source is a more standard way of accessing data from an 'Enumerator'.
67-- | A source is a more standard way of accessing data from an 'Enumerator'.
67-- Each time you call it, it returns the next chunk of data if available, or
68-- Each time you call it, it returns the next chunk of data if available, or
68-- 'Nothing' if the data has been completely consumed.
69-- 'Nothing' if the data has been completely consumed.
69−toSource :: Enumerator () -> IO (IO (Maybe B.ByteString))
70+toSource :: Enumerator -> IO (IO (Maybe B.ByteString))
70−toSource e = do
71+toSource (Enumerator e) = do
71 buffer <- newEmptyMVar
72 buffer <- newEmptyMVar
72 _ <- forkIO $ e (helper buffer) () >> putMVar buffer Nothing
73 _ <- forkIO $ e (helper buffer) () >> putMVar buffer Nothing
73 return $ source buffer
74 return $ source buffer
@@ -93,8 +94,8 @@ toSource e = do
93-- | Read a chunk of data from the given 'Handle' at a time. We use
94-- | Read a chunk of data from the given 'Handle' at a time. We use
94-- 'defaultChunkSize' from the bytestring package to determine the largest
95-- 'defaultChunkSize' from the bytestring package to determine the largest
95-- chunk to take.
96-- chunk to take.
96−fromHandle :: Handle -> Enumerator a
97+fromHandle :: Handle -> Enumerator
97−fromHandle h iter a = do
98+fromHandle h = Enumerator $ \iter a -> do
98 eof <- hIsEOF h
99 eof <- hIsEOF h
100 then return $ Right a
101 then return $ Right a
@@ -103,14 +104,15 @@ fromHandle h iter a = do
103 ea' <- iter a bs
104 ea' <- iter a bs
104 case ea' of
105 case ea' of
105 Left a' -> return $ Left a'
106 Left a' -> return $ Left a'
106− Right a' -> fromHandle h iter a'
107+ Right a' -> runEnumerator (fromHandle h) iter a'
108-- | A little wrapper around 'fromHandle' which first opens a file for reading.
109-- | A little wrapper around 'fromHandle' which first opens a file for reading.
109−fromFile :: FilePath -> Enumerator a
110+fromFile :: FilePath -> Enumerator
110−fromFile fp iter a0 = withBinaryFile fp ReadMode $ \h -> fromHandle h iter a0
111+fromFile fp = Enumerator $ \iter a0 -> withBinaryFile fp ReadMode $ \h ->
112+ runEnumerator (fromHandle h) iter a0
112-- | Since the response body is defined as an 'Either' 'FilePath' 'Enumerator',
114-- | Since the response body is defined as an 'Either' 'FilePath' 'Enumerator',
113-- this function simply reduces the whole operator to an enumerator. This can
115-- this function simply reduces the whole operator to an enumerator. This can
114-- be convenient for server implementations not optimizing file sending.
116-- be convenient for server implementations not optimizing file sending.
115−fromEitherFile :: Either FilePath (Enumerator a) -> Enumerator a
117+fromEitherFile :: Either FilePath Enumerator -> Enumerator
116fromEitherFile = either fromFile id
118fromEitherFile = either fromFile id