content: {-# language ScopedTypeVariables #-}
  {-# language FlexibleContexts #-}
  {-# language TypeApplications #-}
  {-# language Trustworthy #-}
  -- |
  -- Copyright :  (c) 2019 Edward Kmett
  -- License   :  BSD-2-Clause OR Apache-2.0
  -- Maintainer:  Edward Kmett <ekmett@gmail.com>
  -- Stability :  experimental
  -- Portability: non-portable
  --
  module Foreign.Const.Marshal.Utils
  ( withConst
  , newConst
  , copyBytesAt
  , moveBytesAt
  , maybeNewA
  , maybePeekA
  , maybeWithA
  ) where
  
  import Data.Coerce
  import Data.Type.Coercion
  import Foreign.Ptr
  import Foreign.Marshal.Utils
  import Foreign.Storable
  
  import Data.Const.Unsafe
  
  withConst :: forall a b. Storable a => a -> (ConstPtr a -> IO b) -> IO b
  withConst = coerce $ withConst @a @b
  
  newConst :: forall a. Storable a => a -> IO (ConstPtr a)
  newConst = coerce $ new @a
  
  copyBytesAt :: forall a p. APtr p => Ptr a -> p a -> Int -> IO ()
  copyBytesAt = gcoerceWith (unsafePtrCoercion @p @a) $ coerce $ copyBytes @a
  
  moveBytesAt :: forall a p. APtr p => Ptr a -> p a -> Int -> IO ()
  moveBytesAt = gcoerceWith (unsafePtrCoercion @p @a) $ coerce $ moveBytes @a
  
  maybeNewA :: forall a b p.  APtr p => (a -> IO (p b)) -> Maybe a -> IO (p b)
  maybeNewA = gcoerceWith (unsafePtrCoercion @p @b) $ coerce $ maybeNew @a @b
  
  maybePeekA :: forall a b p. APtr p => (p a -> IO b) -> p a -> IO (Maybe b)
  maybePeekA = gcoerceWith (unsafePtrCoercion @p @a) $ coerce $ maybePeek @a @b
  
  maybeWithA :: forall a b c p. APtr p => (a -> (p b -> IO c) -> IO c) -> Maybe a -> (p b -> IO c) -> IO c
  maybeWithA = gcoerceWith (unsafePtrCoercion @p @b) $ coerce $ maybeWith @a @b @c
  