{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE DeriveDataTypeable #-} module Mismi.S3.Internal.Binary ( slurpHandle , slurpHandleWithBuffer ) where import Control.Monad.IO.Class (MonadIO, liftIO) import qualified Data.ByteString as BS import Data.Conduit (ConduitT, yield) import System.IO (Handle, hSeek, SeekMode (..)) -- This is based on `conduit-extra` version 1.1.7.3 -- Data.Conduit.Binary -- sourceFileRange -- souceHandleRange -- -- Ideally this will be replaced by conduit-extra in a future release -- based on (https://github.com/snoyberg/conduit/pull/213) -- slurpHandle :: MonadIO m => Handle -> Integer -- ^ Offset -> Maybe Integer -- ^ Maximum count -> ConduitT () BS.ByteString m () slurpHandle handle offset count' = slurpHandleWithBuffer handle offset count' (1024 * 1024) slurpHandleWithBuffer :: MonadIO m => Handle -> Integer -- ^ Offset -> Maybe Integer -- ^ Maximum count -> Int -- ^ Buffer size -> ConduitT () BS.ByteString m () slurpHandleWithBuffer handle offset count' buffer = do liftIO $ hSeek handle AbsoluteSeek offset case count' of Nothing -> pullUnlimited Just c -> pullLimited (fromInteger c) where pullUnlimited = do bs <- liftIO $ BS.hGetSome handle buffer if BS.null bs then return () else do yield bs pullUnlimited pullLimited c = do bs <- liftIO $ BS.hGetSome handle (min c $ buffer) let c' = c - BS.length bs if BS.null bs then return () else do yield bs pullLimited c'