module System.IO.UTF8 where

import Prelude

import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as BSL
import Data.ByteString.Search qualified as BSS
import Data.ByteString.UTF8 qualified as UTF8
import Data.Text (Text)
import Data.Text.Encoding qualified as TE
import Protolude (ordNub)

-- | Unfortunately ByteString's readFile does not convert line endings on
-- Windows, so we have to do it ourselves
fixCRLF :: BS.ByteString -> BS.ByteString
fixCRLF :: ByteString -> ByteString
fixCRLF = ByteString -> ByteString
BSL.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall rep.
Substitution rep =>
ByteString -> rep -> ByteString -> ByteString
BSS.replace ByteString
"\r\n" (ByteString
"\n" :: BS.ByteString)

readUTF8FilesT :: [FilePath] -> IO [(FilePath, Text)]
readUTF8FilesT :: [FilePath] -> IO [(FilePath, Text)]
readUTF8FilesT =
  forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (\FilePath
inFile -> (FilePath
inFile, ) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO Text
readUTF8FileT FilePath
inFile) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
ordNub

readUTF8FileT :: FilePath -> IO Text
readUTF8FileT :: FilePath -> IO Text
readUTF8FileT FilePath
inFile =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ByteString -> Text
TE.decodeUtf8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fixCRLF) (FilePath -> IO ByteString
BS.readFile FilePath
inFile)

writeUTF8FileT :: FilePath -> Text -> IO ()
writeUTF8FileT :: FilePath -> Text -> IO ()
writeUTF8FileT FilePath
inFile Text
text =
  FilePath -> ByteString -> IO ()
BS.writeFile FilePath
inFile (Text -> ByteString
TE.encodeUtf8 Text
text)

readUTF8File :: FilePath -> IO String
readUTF8File :: FilePath -> IO FilePath
readUTF8File FilePath
inFile =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ByteString -> FilePath
UTF8.toString forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
fixCRLF) (FilePath -> IO ByteString
BS.readFile FilePath
inFile)