{-# OPTIONS_GHC -Wno-redundant-constraints #-}

module Effectful.FileSystem.HandleRW.Static
  ( -- * Effect
    HandleRW,
    openBinaryFile,
    withBinaryFile,

    -- ** Handlers
    runHandleRW,

    -- * Reexports
    ByteString,
    Handle,
    HandleMode (HandleModeReadWrite),
    OsPath,
  )
where

import Data.ByteString (ByteString)
import Effectful
  ( Dispatch (Static),
    DispatchOf,
    Eff,
    Effect,
    IOE,
    type (:>),
  )
import Effectful.Dispatch.Static
  ( HasCallStack,
    SideEffects (WithSideEffects),
    StaticRep,
    evalStaticRep,
    seqUnliftIO,
    unsafeEff,
    unsafeEff_,
  )
import Effectful.FileSystem.Handle.Internal
  ( Handle (MkHandle),
    HandleMode (HandleModeReadWrite),
  )
import FileSystem.IO qualified as FS.IO
import FileSystem.OsPath (OsPath)
import System.IO (IOMode (ReadWriteMode))

-- | Static effect for reading a handle.
--
-- @since 0.1
data HandleRW :: Effect

type instance DispatchOf HandleRW = Static WithSideEffects

data instance StaticRep HandleRW = MkHandleRW

-- | Runs 'HandleRW' in 'IO'.
--
-- @since 0.1
runHandleRW ::
  (HasCallStack, IOE :> es) =>
  Eff (HandleRW : es) a ->
  Eff es a
runHandleRW :: forall (es :: [Effect]) a.
(HasCallStack, IOE :> es) =>
Eff (HandleRW : es) a -> Eff es a
runHandleRW = StaticRep HandleRW -> Eff (HandleRW : es) a -> Eff es a
forall (e :: Effect) (sideEffects :: SideEffects) (es :: [Effect])
       a.
(HasCallStack, DispatchOf e ~ 'Static sideEffects,
 MaybeIOE sideEffects es) =>
StaticRep e -> Eff (e : es) a -> Eff es a
evalStaticRep StaticRep HandleRW
MkHandleRW

-- | Opens a file in ReadWrite mode.
--
-- @since 0.1
openBinaryFile ::
  ( HandleRW :> es,
    HasCallStack
  ) =>
  OsPath ->
  Eff es (Handle HandleModeReadWrite)
openBinaryFile :: forall (es :: [Effect]).
(HandleRW :> es, HasCallStack) =>
OsPath -> Eff es (Handle 'HandleModeReadWrite)
openBinaryFile OsPath
p =
  IO (Handle 'HandleModeReadWrite)
-> Eff es (Handle 'HandleModeReadWrite)
forall a (es :: [Effect]). IO a -> Eff es a
unsafeEff_ (IO (Handle 'HandleModeReadWrite)
 -> Eff es (Handle 'HandleModeReadWrite))
-> IO (Handle 'HandleModeReadWrite)
-> Eff es (Handle 'HandleModeReadWrite)
forall a b. (a -> b) -> a -> b
$
    Handle -> Handle 'HandleModeReadWrite
forall (p :: HandleMode). Handle -> Handle p
MkHandle
      (Handle -> Handle 'HandleModeReadWrite)
-> IO Handle -> IO (Handle 'HandleModeReadWrite)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> OsPath -> IOMode -> IO Handle
FS.IO.openBinaryFileIO OsPath
p IOMode
ReadWriteMode

-- | Opens a file in ReadWrite mode.
--
-- @since 0.1
withBinaryFile ::
  ( HandleRW :> es,
    HasCallStack
  ) =>
  OsPath ->
  (Handle HandleModeReadWrite -> Eff es a) ->
  Eff es a
withBinaryFile :: forall (es :: [Effect]) a.
(HandleRW :> es, HasCallStack) =>
OsPath -> (Handle 'HandleModeReadWrite -> Eff es a) -> Eff es a
withBinaryFile OsPath
p Handle 'HandleModeReadWrite -> Eff es a
onHandle =
  (Env es -> IO a) -> Eff es a
forall (es :: [Effect]) a. (Env es -> IO a) -> Eff es a
unsafeEff ((Env es -> IO a) -> Eff es a) -> (Env es -> IO a) -> Eff es a
forall a b. (a -> b) -> a -> b
$ \Env es
env -> Env es -> ((forall r. Eff es r -> IO r) -> IO a) -> IO a
forall (es :: [Effect]) a.
HasCallStack =>
Env es -> ((forall r. Eff es r -> IO r) -> IO a) -> IO a
seqUnliftIO Env es
env (((forall r. Eff es r -> IO r) -> IO a) -> IO a)
-> ((forall r. Eff es r -> IO r) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \forall r. Eff es r -> IO r
unlift ->
    OsPath -> IOMode -> (Handle -> IO a) -> IO a
forall a. OsPath -> IOMode -> (Handle -> IO a) -> IO a
FS.IO.withBinaryFileIO OsPath
p IOMode
ReadWriteMode (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 'HandleModeReadWrite -> Eff es a
onHandle (Handle 'HandleModeReadWrite -> Eff es a)
-> (Handle -> Handle 'HandleModeReadWrite) -> Handle -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> Handle 'HandleModeReadWrite
forall (p :: HandleMode). Handle -> Handle p
MkHandle)