content: {-# language ScopedTypeVariables #-}
  {-# language TypeApplications #-}
  {-# language FlexibleContexts #-}
  {-# language ConstraintKinds #-}
  {-# language TypeFamilies #-}
  {-# language Trustworthy #-}
  {-# language CPP #-}
  -- |
  -- 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 Data.Const.Primitive.ByteArray
  ( ConstByteArray
  , constByteArray
  , AByteArray
  
  , readAByteArray
  , sameByteArray
  , copyAByteArray
  , copyAByteArrayToAddr
  , moveAByteArray
  , sizeofAByteArray
  , getSizeofAByteArray
  , isAByteArrayPinned
  , constByteArrayContents
  ) where
  
  import Control.Monad.Primitive
  import Data.Coerce
  import Data.Type.Coercion
  import Data.Primitive.ByteArray
  import Data.Primitive.Ptr (Ptr (..))
  import Data.Primitive.Types
  import Data.Word
  
  import Data.Const.Unsafe
  
  #if MIN_VERSION_primitive(0,7,0)
  type Addr = Ptr ()
  #endif
  
  constByteArray :: AByteArray p => p s -> ConstByteArray s
  constByteArray = constant
  {-# inline constByteArray #-}
  
  readAByteArray :: forall a m p. (Prim a, PrimMonad m, AByteArray p) => p (PrimState m) -> Int -> m a
  readAByteArray = gcoerceWith (unsafeByteArrayCoercion @p @(PrimState m)) $ coerce $ readByteArray @a @m
  {-# inline readAByteArray #-}
  
  sameByteArray :: forall s p q. (AByteArray p, AByteArray q) => p s -> q s -> Bool
  sameByteArray
    = gcoerceWith (unsafeByteArrayCoercion @p @s) 
    $ gcoerceWith (unsafeByteArrayCoercion @q @s) 
    $ coerce $ sameMutableByteArray @s
  {-# inline sameByteArray #-}
  
  copyAByteArray :: forall m p. (AByteArray p, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> p (PrimState m) -> Int -> Int -> m ()
  copyAByteArray = gcoerceWith (unsafeByteArrayCoercion @p @(PrimState m)) $ coerce $ copyMutableByteArray @m
  {-# inline copyAByteArray #-}
  
  copyAByteArrayToAddr :: forall m p. (AByteArray p, PrimMonad m) => Addr -> p (PrimState m) -> Int -> Int -> m ()
  copyAByteArrayToAddr = gcoerceWith (unsafeByteArrayCoercion @p @(PrimState m)) $ coerce $ copyMutableByteArrayToAddr @m
  {-# inline copyAByteArrayToAddr #-}
  
  moveAByteArray :: forall m p. (AByteArray p, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> p (PrimState m) -> Int -> Int -> m ()
  moveAByteArray = gcoerceWith (unsafeByteArrayCoercion @p @(PrimState m)) $ coerce $ moveByteArray @m
  {-# inline moveAByteArray #-}
  
  sizeofAByteArray :: forall s p. AByteArray p => p s -> Int
  sizeofAByteArray = gcoerceWith (unsafeByteArrayCoercion @p @s) $ coerce $ sizeofMutableByteArray @s
  {-# inline sizeofAByteArray #-}
  
  getSizeofAByteArray :: forall m p. (PrimMonad m, AByteArray p) => p (PrimState m) -> m Int
  getSizeofAByteArray =  gcoerceWith (unsafeByteArrayCoercion @p @(PrimState m)) $ coerce $ getSizeofMutableByteArray @m
  {-# inline getSizeofAByteArray #-}
  
  isAByteArrayPinned :: forall s p. AByteArray p => p s -> Bool
  isAByteArrayPinned = gcoerceWith (unsafeByteArrayCoercion @p @s) $ coerce $ isMutableByteArrayPinned @s
  {-# inline isAByteArrayPinned #-}
  
  -- | Only safe on a pinned ByteArray or pinned ConstByteArray
  constByteArrayContents :: forall s p. AByteArray p => p s -> ConstPtr Word8
  #if MIN_VERSION_primitive(0,7,0)
  constByteArrayContents = gcoerceWith (unsafeByteArrayCoercion @p @s) $ coerce $ mutableByteArrayContents @s
  #else
  constByteArrayContents = gcoerceWith (unsafeByteArrayCoercion @p @s) $ coerce $ (\(Addr a) -> Ptr a) . mutableByteArrayContents @s
  #endif
  {-# inline constByteArrayContents #-}
  