-- | Lifted "System.IO".
module Effectful.FileSystem.IO
  ( -- * Effect
    FileSystem

    -- ** Handlers
  , runFileSystem

    -- * IO
  , IOMode (..)
  , Handle
  , IO.stdin
  , IO.stdout
  , IO.stderr
  , withFile
  , withBinaryFile
  , openFile
  , hClose
  , hFlush
  , hFileSize
  , hSetFileSize
  , hIsEOF
  , IO.BufferMode (..)
  , hSetBuffering
  , hGetBuffering
  , hSeek
  , IO.SeekMode (..)
  , hTell
  , hIsOpen
  , hIsClosed
  , hIsReadable
  , hIsWritable
  , hIsSeekable
  , hIsTerminalDevice
  , hSetEcho
  , hGetEcho
  , hWaitForInput
  , hReady
  ) where

import System.IO (Handle, IOMode (..))
import System.IO qualified as IO

import Effectful
import Effectful.Dispatch.Static
import Effectful.FileSystem.Effect

-- | Lifted 'IO.withFile'.
withFile
  :: FileSystem :> es
  => FilePath
  -> IOMode
  -> (Handle -> Eff es a)
  -> Eff es a
withFile :: forall (es :: [Effect]) a.
(FileSystem :> es) =>
FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a
withFile FilePath
fp IOMode
mode Handle -> Eff es a
inner = ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
forall (es :: [Effect]) a.
HasCallStack =>
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeSeqUnliftIO (((forall r. Eff es r -> IO r) -> IO a) -> Eff es a)
-> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  FilePath -> IOMode -> (Handle -> IO a) -> IO a
forall r. FilePath -> IOMode -> (Handle -> IO r) -> IO r
IO.withFile FilePath
fp IOMode
mode ((Handle -> IO a) -> IO a) -> (Handle -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ Eff es a -> IO a
forall r. Eff es r -> IO r
unlift (Eff es a -> IO a) -> (Handle -> Eff es a) -> Handle -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> Eff es a
inner

-- | Lifted 'IO.withBinaryFile'.
withBinaryFile
  :: FileSystem :> es
  => FilePath
  -> IOMode
  -> (Handle -> Eff es a)
  -> Eff es a
withBinaryFile :: forall (es :: [Effect]) a.
(FileSystem :> es) =>
FilePath -> IOMode -> (Handle -> Eff es a) -> Eff es a
withBinaryFile FilePath
fp IOMode
mode Handle -> Eff es a
inner = ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
forall (es :: [Effect]) a.
HasCallStack =>
((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
unsafeSeqUnliftIO (((forall r. Eff es r -> IO r) -> IO a) -> Eff es a)
-> ((forall r. Eff es r -> IO r) -> IO a) -> Eff es a
forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift -> do
  FilePath -> IOMode -> (Handle -> IO a) -> IO a
forall r. FilePath -> IOMode -> (Handle -> IO r) -> IO r
IO.withBinaryFile FilePath
fp IOMode
mode ((Handle -> IO a) -> IO a) -> (Handle -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ Eff es a -> IO a
forall r. Eff es r -> IO r
unlift (Eff es a -> IO a) -> (Handle -> Eff es a) -> Handle -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> Eff es a
inner

-- | Lifted 'IO.openFile'
openFile :: FileSystem :> es => FilePath -> IOMode -> Eff es Handle
openFile :: forall (es :: [Effect]).
(FileSystem :> es) =>
FilePath -> IOMode -> Eff es Handle
openFile FilePath
fp = IO Handle -> Eff es Handle
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Handle -> Eff es Handle)
-> (IOMode -> IO Handle) -> IOMode -> Eff es Handle
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IOMode -> IO Handle
IO.openFile FilePath
fp

-- | Lifted 'IO.hClose'
hClose :: FileSystem :> es => Handle -> Eff es ()
hClose :: forall (es :: [Effect]). (FileSystem :> es) => Handle -> Eff es ()
hClose = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Handle -> IO ()) -> Handle -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO ()
IO.hClose

-- | Lifted 'IO.hFlush'
hFlush :: FileSystem :> es => Handle -> Eff es ()
hFlush :: forall (es :: [Effect]). (FileSystem :> es) => Handle -> Eff es ()
hFlush = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Handle -> IO ()) -> Handle -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO ()
IO.hFlush

-- | Lifted 'IO.hFileSize'
hFileSize :: FileSystem :> es => Handle -> Eff es Integer
hFileSize :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Integer
hFileSize = IO Integer -> Eff es Integer
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Integer -> Eff es Integer)
-> (Handle -> IO Integer) -> Handle -> Eff es Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Integer
IO.hFileSize

-- | Lifted 'IO.hSetFileSize'
hSetFileSize :: FileSystem :> es => Handle -> Integer -> Eff es ()
hSetFileSize :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Integer -> Eff es ()
hSetFileSize Handle
h = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Integer -> IO ()) -> Integer -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> Integer -> IO ()
IO.hSetFileSize Handle
h

-- | Lifted 'IO.hIsEOF'
hIsEOF :: FileSystem :> es => Handle -> Eff es Bool
hIsEOF :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsEOF = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsEOF

-- | Lifted 'IO.hSetBuffering'
hSetBuffering :: FileSystem :> es => Handle -> IO.BufferMode -> Eff es ()
hSetBuffering :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> BufferMode -> Eff es ()
hSetBuffering Handle
h = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ())
-> (BufferMode -> IO ()) -> BufferMode -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> BufferMode -> IO ()
IO.hSetBuffering Handle
h

-- | Lifted 'IO.hGetBuffering'
hGetBuffering :: FileSystem :> es => Handle -> Eff es IO.BufferMode
hGetBuffering :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es BufferMode
hGetBuffering = IO BufferMode -> Eff es BufferMode
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO BufferMode -> Eff es BufferMode)
-> (Handle -> IO BufferMode) -> Handle -> Eff es BufferMode
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO BufferMode
IO.hGetBuffering

-- | Lifted 'IO.hSeek'
hSeek :: FileSystem :> es => Handle -> IO.SeekMode -> Integer -> Eff es ()
hSeek :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> SeekMode -> Integer -> Eff es ()
hSeek Handle
h SeekMode
s = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Integer -> IO ()) -> Integer -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> SeekMode -> Integer -> IO ()
IO.hSeek Handle
h SeekMode
s

-- | Lifted 'IO.hTell'
hTell :: FileSystem :> es => Handle -> Eff es Integer
hTell :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Integer
hTell = IO Integer -> Eff es Integer
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Integer -> Eff es Integer)
-> (Handle -> IO Integer) -> Handle -> Eff es Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Integer
IO.hTell

-- | Lifted 'IO.hIsOpen'
hIsOpen :: FileSystem :> es => Handle -> Eff es Bool
hIsOpen :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsOpen = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsOpen

-- | Lifted 'IO.hIsClosed'
hIsClosed :: FileSystem :> es => Handle -> Eff es Bool
hIsClosed :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsClosed = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsClosed

-- | Lifted 'IO.hIsReadable'
hIsReadable :: FileSystem :> es => Handle -> Eff es Bool
hIsReadable :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsReadable = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsReadable

-- | Lifted 'IO.hIsWritable'
hIsWritable :: FileSystem :> es => Handle -> Eff es Bool
hIsWritable :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsWritable = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsWritable

-- | Lifted 'IO.hIsSeekable'
hIsSeekable :: FileSystem :> es => Handle -> Eff es Bool
hIsSeekable :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsSeekable = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsSeekable

-- | Lifted 'IO.hIsTerminalDevice'
hIsTerminalDevice :: FileSystem :> es => Handle -> Eff es Bool
hIsTerminalDevice :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hIsTerminalDevice = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hIsTerminalDevice

-- | Lifted 'IO.hSetEcho'
hSetEcho :: FileSystem :> es => Handle -> Bool -> Eff es ()
hSetEcho :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Bool -> Eff es ()
hSetEcho Handle
h = IO () -> Eff es ()
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO () -> Eff es ()) -> (Bool -> IO ()) -> Bool -> Eff es ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> Bool -> IO ()
IO.hSetEcho Handle
h

-- | Lifted 'IO.hGetEcho'
hGetEcho :: FileSystem :> es => Handle -> Eff es Bool
hGetEcho :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hGetEcho = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hGetEcho

-- | Lifted 'IO.hWaitForInput'
hWaitForInput :: FileSystem :> es => Handle -> Int -> Eff es Bool
hWaitForInput :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Int -> Eff es Bool
hWaitForInput Handle
h = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool) -> (Int -> IO Bool) -> Int -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> Int -> IO Bool
IO.hWaitForInput Handle
h

-- | Lifted 'IO.hReady'
hReady :: FileSystem :> es => Handle -> Eff es Bool
hReady :: forall (es :: [Effect]).
(FileSystem :> es) =>
Handle -> Eff es Bool
hReady = IO Bool -> Eff es Bool
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO Bool -> Eff es Bool)
-> (Handle -> IO Bool) -> Handle -> Eff es Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO Bool
IO.hReady