on master help sign in
Enumerator returns Either; fromHandle/File
commitedf1eabb60c2785a56192ac174280343a503e6d8 authorMichael Snoyman <michael@snoyman.com> dateSat 30 Jan 2010, 21:02 (17 years ago) parentb8ba4fd
3 files changed+36−6
Network/Wai.hs+3−1 Network/Wai/Enumerator.hs+31−3 Network/Wai/Handler/SimpleServer.hs+2−2
Network/Wai.hs+3−1
@@ -235,7 +235,9 @@ statusMessage Status405 = B8.pack "Method Not Allowed"
235235statusMessage Status500 = B8.pack "Internal Server Error"
236236statusMessage (Status _ m) = m
237237
238−type Enumerator a = (a -> B.ByteString -> IO (Either a a)) -> a -> IO a
238+type Enumerator a = (a -> B.ByteString -> IO (Either a a))
239+ -> a
240+ -> IO (Either a a)
239241
240242data Request = Request
241243 { requestMethod :: Method
Network/Wai/Enumerator.hs+31−3
@@ -6,12 +6,18 @@ module Network.Wai.Enumerator
66 , fromLBS'
77 -- * Source
88 , toSource
9+ -- * Handle
10+ , fromHandle
11+ -- * FilePath
12+ , fromFile
13+ , fromEitherFile
914 ) where
1015
1116import Network.Wai (Enumerator)
1217import qualified Data.ByteString.Lazy as L
1318import qualified Data.ByteString as B
1419import System.IO.Unsafe (unsafeInterleaveIO)
20+import System.IO (withBinaryFile, IOMode (ReadMode), Handle, hIsEOF)
1521
1622-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
1723-- normal lazy I/O warnings apply.
@@ -27,11 +33,11 @@ toLBS e = L.fromChunks `fmap` helper where
2733
2834fromLBS :: L.ByteString -> Enumerator a
2935fromLBS lbs iter a0 = helper a0 $ L.toChunks lbs where
30− helper a [] = return a
36+ helper a [] = return $ Right a
3137 helper a (x:xs) = do
3238 ea <- iter a x
3339 case ea of
34− Left a' -> return a'
40+ Left a' -> return $ Left a'
3541 Right a' -> helper a' xs
3642
3743fromLBS' :: IO L.ByteString -> Enumerator a
@@ -41,4 +47,26 @@ fromLBS' lbs' iter a0 = lbs' >>= \lbs -> fromLBS lbs iter a0
4147-- Each time you call it, it returns the next chunk of data if available, or
4248-- 'Nothing' if the data has been completely consumed.
4349toSource :: 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
51+
52+chunkSize :: Int
53+chunkSize = 1024 -- FIXME
54+
55+fromHandle :: Handle -> Enumerator a
56+fromHandle h iter a = do
57+ eof <- hIsEOF h
58+ if eof
59+ then return $ Right a
60+ else do
61+ bs <- B.hGet h chunkSize
62+ ea' <- iter a bs
63+ case ea' of
64+ Left a' -> return $ Left a'
65+ Right a' -> fromHandle h iter a'
66+
67+fromFile :: FilePath -> Enumerator a
68+fromFile fp iter a0 = withBinaryFile fp ReadMode $ \h -> fromHandle h iter a0
69+
70+fromEitherFile :: Either FilePath (Enumerator a) -> Enumerator a
71+fromEitherFile (Left fp) = fromFile fp
72+fromEitherFile (Right e) = e
Network/Wai/Handler/SimpleServer.hs+2−2
@@ -136,7 +136,7 @@ parseRequest port lines' handle remoteHost' = do
136136
137137requestBodyHandle :: Handle -> MVar Int -> Enumerator a
138138requestBodyHandle h mlen iter accum = modifyMVar mlen (helper accum) where
139− helper a 0 = return (0, a)
139+ helper a 0 = return (0, Right a)
140140 helper a len = do
141141 let maxChunkSize = 1024
142142 bs <- BS.hGet h $ min len maxChunkSize
@@ -144,7 +144,7 @@ requestBodyHandle h mlen iter accum = modifyMVar mlen (helper accum) where
144144 putStrLn $ "reading a chunk of size " ++ show (BS.length bs)
145145 ea' <- iter a bs
146146 case ea' of
147− Left a' -> return (newLen, a')
147+ Left a' -> return (newLen, Left a')
148148 Right a' -> helper a' newLen
149149
150150parseFirst :: (StringLike s, MonadFailure InvalidRequest m) =>