module RIO.Prelude.IO ( withLazyFile , readFileBinary , writeFileBinary , readFileUtf8 , writeFileUtf8 , hPutBuilder ) where import RIO.Prelude.Reexports import qualified Data.ByteString.Builder as BB import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL 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 -- | 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