diff --git a/CHANGELOG.md b/CHANGELOG.md index d81a69d..0ee181c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ `relude` uses [PVP Versioning][1]. The changelog is available [on GitHub][2]. +## 1.2.2 - Unreleased ## + +- [#459](https://github.com/kowainik/relude/pull/459): + Add `Relude.File.readFileUtf8`. + ## 1.2.1.0 – Oct 4, 2023 - [#439](https://github.com/kowainik/relude/issues/439): diff --git a/src/Relude/File.hs b/src/Relude/File.hs index ca49981..9aef744 100644 --- a/src/Relude/File.hs +++ b/src/Relude/File.hs @@ -1,4 +1,5 @@ -{-# LANGUAGE Safe #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE Safe #-} {- | Module : Relude.File @@ -53,12 +54,16 @@ module Relude.File , readFileLBS , writeFileLBS , appendFileLBS + + -- * Reading in UTF-8 + , readFileUtf8 ) where import Relude.Base (FilePath, IO) import Relude.Function ((.)) +import Relude.Functor (fmap) import Relude.Monad.Reexport (MonadIO (..)) -import Relude.String (ByteString, LByteString, LText, Text) +import Relude.String (ByteString, ConvertUtf8 (..), LByteString, LText, String, Text) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS @@ -191,3 +196,21 @@ appendFileLBS :: MonadIO m => FilePath -> LByteString -> m () appendFileLBS p = liftIO . LBS.appendFile p {-# SPECIALIZE appendFileLBS :: FilePath -> LByteString -> IO () #-} {-# INLINE appendFileLBS #-} + +---------------------------------------------------------------------------- +-- UTF-8 +---------------------------------------------------------------------------- + +{- | 'MonadIO'-lifted strict file reading with the assumption that it contains +text in UTF-8 (or just ASCII) encoding. + +Invalid byte sequences that don't represent characters will be converted to +U+FFFD replacement characters (@decodeUtf8Lenient@). + +@since 1.2.2 +-} +readFileUtf8 :: (MonadIO m, ConvertUtf8 r ByteString) => FilePath -> m r +readFileUtf8 = liftIO . fmap decodeUtf8 . BS.readFile +{-# SPECIALIZE readFileUtf8 :: FilePath -> IO Text #-} +{-# SPECIALIZE readFileUtf8 :: FilePath -> IO String #-} +{-# INLINE readFileUtf8 #-}