module Data.Enumerator.IO
( enumHandle
, enumFile
, iterHandle
) where
import Data.Enumerator
import Data.Enumerator.Util
import Control.Monad.IO.Class (MonadIO)
import qualified Control.Exception as E
import qualified Data.ByteString as B
import qualified System.IO as IO
import System.IO.Error (isEOFError)
enumHandle :: MonadIO m
=> Integer
-> IO.Handle
-> Enumerator B.ByteString m 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))
(\err -> if isEOFError err
then return False
else E.throwIO err)
if hasInput
then B.hGetNonBlocking h intSize
else return B.empty
enumFile :: FilePath -> Enumerator 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 :: MonadIO m => IO.Handle -> Iteratee B.ByteString m ()
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)