{-# language UndecidableSuperClasses #-}
{-# language ScopedTypeVariables #-}
{-# language FlexibleContexts #-}
{-# language TypeApplications #-}
{-# language NoStarIsType #-}
{-# language ConstraintKinds #-}
{-# language TypeFamilies #-}
{-# language Trustworthy #-}
module Foreign.Const.ForeignPtr
( ConstForeignPtr
, constForeignPtr
, AForeignPtr
, newConstForeignPtr
, newConstForeignPtr_
, castConstForeignPtr
, plusConstForeignPtr
, newConstForeignPtrEnv
, withConstForeignPtr
, Unforeign
, plusAForeignPtr
, withAForeignPtr
, addAForeignPtrFinalizer
, addAForeignPtrFinalizerEnv
, finalizeAForeignPtr
, touchAForeignPtr
) where
import Data.Coerce
import Data.Kind
import Data.Type.Coercion
import Foreign.Const.Ptr
import Foreign.ForeignPtr
import Foreign.Ptr
import Data.Const.Unsafe
type family Unforeign (fp :: Type -> Type) :: Type -> Type
type instance Unforeign ForeignPtr = Ptr
type instance Unforeign ConstForeignPtr = ConstPtr
constForeignPtr :: AForeignPtr fp => fp a -> ConstForeignPtr a
constForeignPtr = constant
{-# inline constForeignPtr #-}
newConstForeignPtr :: forall p a. APtr p => FinalizerPtr a -> p a -> IO (ConstForeignPtr a)
newConstForeignPtr = gcoerceWith (unsafePtrCoercion @p @a) $ coerce $ newForeignPtr @a
{-# inline newConstForeignPtr #-}
newConstForeignPtr_ :: forall p a. APtr p => p a -> IO (ConstForeignPtr a)
newConstForeignPtr_ = gcoerceWith (unsafePtrCoercion @p @a) $ coerce $ newForeignPtr_ @a
{-# inline newConstForeignPtr_ #-}
addAForeignPtrFinalizer :: forall fp a. AForeignPtr fp => FinalizerPtr a -> fp a -> IO ()
addAForeignPtrFinalizer = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ addForeignPtrFinalizer @a
{-# inline addAForeignPtrFinalizer #-}
newConstForeignPtrEnv :: forall p env a. APtr p => FinalizerEnvPtr env a -> Ptr env -> p a -> IO (ConstForeignPtr a)
newConstForeignPtrEnv = gcoerceWith (unsafePtrCoercion @p @a) $ coerce $ newForeignPtrEnv @env @a
{-# inline newConstForeignPtrEnv #-}
addAForeignPtrFinalizerEnv :: forall fp env a. AForeignPtr fp => FinalizerEnvPtr env a -> Ptr env -> fp a -> IO ()
addAForeignPtrFinalizerEnv = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ addForeignPtrFinalizerEnv @env @a
{-# inline addAForeignPtrFinalizerEnv #-}
withConstForeignPtr :: forall fp a r. AForeignPtr fp => fp a -> (ConstPtr a -> IO r) -> IO r
withConstForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ withForeignPtr @a @r
{-# inline withConstForeignPtr #-}
finalizeAForeignPtr :: forall fp a. AForeignPtr fp => fp a -> IO ()
finalizeAForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ finalizeForeignPtr @a
{-# inline finalizeAForeignPtr #-}
touchAForeignPtr :: forall fp a. AForeignPtr fp => fp a -> IO ()
touchAForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ touchForeignPtr @a
{-# inline touchAForeignPtr #-}
castConstForeignPtr :: forall fp a b. AForeignPtr fp => fp a -> ConstForeignPtr b
castConstForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ castForeignPtr @a @b
{-# inline castConstForeignPtr #-}
plusAForeignPtr :: forall fp a b. AForeignPtr fp => fp a -> Int -> fp b
plusAForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ gcoerceWith (unsafeForeignPtrCoercion @fp @b) $ coerce $ plusForeignPtr @a @b
{-# inline plusAForeignPtr #-}
plusConstForeignPtr :: forall fp a b. AForeignPtr fp => fp a -> Int -> ConstForeignPtr b
plusConstForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ coerce $ plusForeignPtr @a @b
{-# inline plusConstForeignPtr #-}
withAForeignPtr :: forall fp a r. (AForeignPtr fp, APtr (Unforeign fp)) => fp a -> (Unforeign fp a -> IO r) -> IO r
withAForeignPtr = gcoerceWith (unsafeForeignPtrCoercion @fp @a) $ gcoerceWith (unsafePtrCoercion @(Unforeign fp) @a) $ coerce $ withForeignPtr @a @r
{-# inline withAForeignPtr #-}