-- |Given a function, return a bytestring that will call that function when it
-- is partially consumed. The Words provided to the function will be the number
-- of bytes that were just consumed and the total bytes consumed thus far.
trackProgress :: (Word64 -> Word64 -> IO ()) ->
                 ByteString ->
                 IO ByteString
trackProgress tracker inputBS =
  BS.fromChunks <$> runTrack 0 (BS.toChunks inputBS)
 where
  runTrack _ [] = return []
  runTrack x (fst:rest) = unsafeInterleaveIO $ do
    let amtRead = fromIntegral $ BSS.length fst
    tracker amtRead (x + amtRead)
    (fst :) <$> runTrack (x + amtRead) rest

-- |Works like 'trackProgress', except uses fixed-size chunks of the given
-- size.  Thus, for this function, the first number passed to your function
-- will always be the given size *except* for the last call to the function,
-- which will be less then or equal to the final size.
trackProgress :: (Word64 -> Word64 -> IO ()) ->
                 ByteString ->
                 IO ByteString
trackProgress tracker inputBS =
  BS.fromChunks <$> runTrack 0 (BS.toChunks inputBS)
 where
  runTrack _ [] = return []
  runTrack x (fst:rest) = unsafeInterleaveIO $ do
    let amtRead = fromIntegral $ BSS.length fst
    tracker amtRead (x + amtRead)
    (fst :) <$> runTrack (x + amtRead) rest

-- |Works like 'trackProgress', except uses fixed-size chunks of the given
-- size.  Thus, for this function, the first number passed to your function
-- will always be the given size *except* for the last call to the function,
-- which will be less then or equal to the final size.
trackProgress tracker inputBS =
  BS.fromChunks <$> runTrack 0 (BS.toChunks inputBS)
 where
  runTrack _ [] = return []
  runTrack x (fst:rest) = unsafeInterleaveIO $ do
    let amtRead = fromIntegral $ BSS.length fst
    tracker amtRead (x + amtRead)
    (fst :) <$> runTrack (x + amtRead) rest

-- |Works like 'trackProgress', except uses fixed-size chunks of the given
-- size.  Thus, for this function, the first number passed to your function
-- will always be the given size *except* for the last call to the function,
-- which will be less then or equal to the final size.