module Data.Enumerator.IO
( enumHandle
, enumFile
, iterFile
, iterHandle
) where
import Data.Enumerator
import Data.Enumerator.Util
import qualified Control.Exception as E
import qualified Data.ByteString as B
import qualified System.IO as IO
enumHandle :: Integer
-> IO.Handle
-> Enumerator E.SomeException B.ByteString IO b
enumHandle bufferSize h = Iteratee . loop where
loop (Continue k) = withBytes $ \bytes -> if B.null bytes
then return $ Continue k
else runIteratee (k (Chunks [bytes])) >>= loop
loop step = return step
intSize = fromInteger bufferSize
withBytes = tryStep $ do
hasInput <- E.catch
(IO.hWaitForInput h (1))
(\(E.SomeException _) -> return False)
if hasInput
then B.hGetNonBlocking h intSize
else return B.empty
enumFile :: FilePath -> Enumerator E.SomeException B.ByteString IO b
enumFile path s = Iteratee io where
withHandle = tryStep (IO.openBinaryFile path IO.ReadMode)
io = withHandle $ \h -> E.finally
(runIteratee (enumHandle 4096 h s))
(IO.hClose h)
iterHandle :: IO.Handle -> Iteratee E.SomeException B.ByteString IO ()
iterHandle h = continue step where
step EOF = yield () EOF
step (Chunks []) = continue step
step (Chunks bytes) = Iteratee io where
put = mapM_ (B.hPut h) bytes
io = tryStep put (\_ -> return $ Continue step)
iterFile :: FilePath -> Iteratee E.SomeException B.ByteString IO ()
iterFile path = Iteratee io where
withHandle = tryStep (IO.openBinaryFile path IO.WriteMode)
io = withHandle $ \h -> E.finally
(runIteratee (iterHandle h))
(IO.hClose h)