content: {-# LANGUAGE CPP #-}
  module RIO.Prelude.IO
    ( withLazyFile
    , withLazyFileUtf8
    , readFileBinary
    , writeFileBinary
    , readFileUtf8
    , writeFileUtf8
    , hPutBuilder
    ) where
  
  import           RIO.Prelude.Reexports
  import qualified Data.ByteString         as B
  import qualified Data.ByteString.Builder as BB
  import qualified Data.ByteString.Lazy    as BL
  import qualified Data.Text.Lazy          as TL
  import qualified Data.Text.Lazy.IO       as TL
  import qualified Data.Text.IO            as T
  import           System.IO               (hSetEncoding, utf8)
  
  
  -- | Lazily get the contents of a file. Unlike 'BL.readFile', this
  -- ensures that if an exception is thrown, the file handle is closed
  -- immediately.
  withLazyFile :: MonadUnliftIO m => FilePath -> (BL.ByteString -> m a) -> m a
  withLazyFile fp inner = withBinaryFile fp ReadMode $ inner <=< liftIO . BL.hGetContents
  
  -- | Lazily read a file in UTF8 encoding.
  --
  -- @since 0.1.13
  withLazyFileUtf8 :: MonadUnliftIO m => FilePath -> (TL.Text -> m a) -> m a
  withLazyFileUtf8 fp inner = withFile fp ReadMode $ \h ->
    inner =<< liftIO (hSetEncoding h utf8 >> TL.hGetContents h)
  
  -- | Write a file in UTF8 encoding
  --
  -- This function will use OS-specific line ending handling.
  writeFileUtf8 :: MonadIO m => FilePath -> Text -> m ()
  writeFileUtf8 fp text = liftIO $ withFile fp WriteMode $ \h -> do
    hSetEncoding h utf8
    T.hPutStr h text
  
  hPutBuilder :: MonadIO m => Handle -> Builder -> m ()
  hPutBuilder h = liftIO . BB.hPutBuilder h
  {-# INLINE hPutBuilder #-}
  
  -- | Same as 'B.readFile', but generalized to 'MonadIO'
  readFileBinary :: MonadIO m => FilePath -> m ByteString
  readFileBinary = liftIO . B.readFile
  
  -- | Same as 'B.writeFile', but generalized to 'MonadIO'
  writeFileBinary :: MonadIO m => FilePath -> ByteString -> m ()
  writeFileBinary fp = liftIO . B.writeFile fp
  
  -- | Read a file in UTF8 encoding, throwing an exception on invalid character
  -- encoding.
  --
  -- This function will use OS-specific line ending handling.
  readFileUtf8 :: MonadIO m => FilePath -> m Text
  readFileUtf8 fp = liftIO $ withFile fp ReadMode $ \h -> do
    hSetEncoding h utf8
    T.hGetContents h
  