module C_03_Bytes (binaryFileResource) where
import Data.Word (Word8)
import C_01_Handles (getDataDir, greetingTxt)
import C_02_Chunks (repeatUntil)
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.Trans.Resource (ReleaseKey, ResourceT, allocate, runResourceT)
import Data.ByteString as BS (ByteString, hGetSome, hPut, hPutStr, map, null, pack)
import Data.String (fromString)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Encoding qualified as T
import Data.Text.IO qualified as T
import GHC.IO.Handle.FD (stdout)
import Relude (Handle, IOMode (..), UnicodeException)
import System.FilePath ((</>))
import System.IO qualified as IO
exampleBytes :: [Word8]
exampleBytes = [104, 101, 108, 111] :: [Word8]
greeting2Txt :: FilePath
greeting2Txt = "greeting2.txt"
copyGreetingFile :: IO ()
copyGreetingFile = runResourceT @IO do
dir <- liftIO getDataDir
(_, h1) <- binaryFileResource (dir </> greetingTxt) ReadMode
(_, h2) <- binaryFileResource (dir </> greeting2Txt) WriteMode
liftIO $ repeatUntil (BS.hGetSome h1 1024) BS.null (BS.hPutStr h2)
binaryFileResource :: FilePath -> IOMode -> ResourceT IO (ReleaseKey, Handle)
binaryFileResource path mode = allocate (IO.openBinaryFile path mode) IO.hClose
helloHandle :: IO ()
helloHandle = IO.hPutStrLn IO.stdout "Hello, world!"
helloByteString :: IO ()
helloByteString = do
IO.hSetBinaryMode stdout True
BS.hPut stdout (BS.pack helloBytes)
helloBytes :: [Word8]
helloBytes =
[ -- hello
104
, 101
, 108
, 111
, -- ,
32
, -- world
119
, 111
, 114
, 108
, 100
, 33
, -- /n
10
]
-- >>>helloByteString
helloUtf8 :: IO ()
helloUtf8 = do
IO.hSetBinaryMode stdout True
BS.hPutStr stdout (T.encodeUtf8 (T.pack "hello, world!\n"))
-- >>>helloUtf8
greet :: BS.ByteString -> IO ()
greet nameBS = case T.decodeUtf8' nameBS of
Left _ -> putStrLn "Invalid byte string"
Right nameText -> T.putStrLn (T.pack "Hello, " <> nameText)
p1 :: Either UnicodeException Text
p1 = T.decodeUtf8' (fromString "♫")
-- >>>p1
-- Right "k"
asciiUpper :: BS.ByteString -> BS.ByteString
asciiUpper = BS.map (\x -> if 97 <= x && x <= 122 then 65 + x - 97 else x)
p2 :: ByteString
p2 = asciiUpper (fromString "Hello!")
-- >>> p2
-- "HELLO!"