@@ -6,12 +6,18 @@ module Network.Wai.Enumerator
7 -- * Source
7 -- * Source
11import Network.Wai (Enumerator)
16import Network.Wai (Enumerator)
12import qualified Data.ByteString.Lazy as L
17import qualified Data.ByteString.Lazy as L
13import qualified Data.ByteString as B
18import qualified Data.ByteString as B
14import System.IO.Unsafe (unsafeInterleaveIO)
19import System.IO.Unsafe (unsafeInterleaveIO)
20+import System.IO (withBinaryFile, IOMode (ReadMode), Handle, hIsEOF)
16-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
22-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
17-- normal lazy I/O warnings apply.
23-- normal lazy I/O warnings apply.
@@ -27,11 +33,11 @@ toLBS e = L.fromChunks `fmap` helper where
28fromLBS :: L.ByteString -> Enumerator a
34fromLBS :: L.ByteString -> Enumerator a
29fromLBS lbs iter a0 = helper a0 $ L.toChunks lbs where
35fromLBS lbs iter a0 = helper a0 $ L.toChunks lbs where
30− helper a [] = return a
36+ helper a [] = return $ Right a
31 helper a (x:xs) = do
37 helper a (x:xs) = do
32 ea <- iter a x
38 ea <- iter a x
33 case ea of
39 case ea of
34− Left a' -> return a'
40+ Left a' -> return $ Left a'
35 Right a' -> helper a' xs
41 Right a' -> helper a' xs
37fromLBS' :: IO L.ByteString -> Enumerator a
43fromLBS' :: IO L.ByteString -> Enumerator a
@@ -41,4 +47,26 @@ fromLBS' lbs' iter a0 = lbs' >>= \lbs -> fromLBS lbs iter a0
41-- Each time you call it, it returns the next chunk of data if available, or
47-- Each time you call it, it returns the next chunk of data if available, or
42-- 'Nothing' if the data has been completely consumed.
48-- 'Nothing' if the data has been completely consumed.
43toSource :: Enumerator (Maybe B.ByteString) -> IO (Maybe B.ByteString)
49toSource :: Enumerator (Maybe B.ByteString) -> IO (Maybe B.ByteString)
44−toSource e = e (const $ return . Left . Just) Nothing
50+toSource e = fmap (either id id) $ e (const $ return . Left . Just) Nothing
53+chunkSize = 1024 -- FIXME
55+fromHandle :: Handle -> Enumerator a
56+fromHandle h iter a = do
59+ then return $ Right a
61+ bs <- B.hGet h chunkSize
64+ Left a' -> return $ Left a'
65+ Right a' -> fromHandle h iter a'
67+fromFile :: FilePath -> Enumerator a
68+fromFile fp iter a0 = withBinaryFile fp ReadMode $ \h -> fromHandle h iter a0
70+fromEitherFile :: Either FilePath (Enumerator a) -> Enumerator a
71+fromEitherFile (Left fp) = fromFile fp
72+fromEitherFile (Right e) = e