{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}
{-# language FlexibleContexts #-}
{-# language ConstraintKinds #-}
{-# language TypeFamilies #-}
{-# 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 Data.Const.Primitive.Array
( ConstArray
, constArray
, AnArray
, readAnArray
, sameArray
, copyAnArray
, cloneAnArray
, sizeofAnArray
) where

import Control.Monad.Primitive
import Data.Coerce
import Data.Type.Coercion
import Data.Primitive.Array

import Data.Const.Unsafe

constArray :: AnArray s p => p a -> ConstArray s a
constArray = constant
{-# inline constArray #-}

readAnArray :: forall m p a. (PrimMonad m, AnArray (PrimState m) p) => p a -> Int -> m a
readAnArray = gcoerceWith (unsafeArrayCoercion @(PrimState m) @p @a) $ coerce $ readArray @m @a
{-# inline readAnArray #-}

sameArray :: forall s p q a. (AnArray s p, AnArray s q) => p a -> q a -> Bool
sameArray
  = gcoerceWith (unsafeArrayCoercion @s @p @a)
  $ gcoerceWith (unsafeArrayCoercion @s @q @a)
  $ coerce $ sameMutableArray @s @a
{-# inline sameArray #-}

copyAnArray :: forall m p a. (PrimMonad m, AnArray (PrimState m) p) => MutableArray (PrimState m) a -> Int -> p a -> Int -> Int -> m ()
copyAnArray = gcoerceWith (unsafeArrayCoercion @(PrimState m) @p @a) $ coerce $ copyMutableArray @m @a
{-# inline copyAnArray #-}

cloneAnArray :: forall m p a. (PrimMonad m, AnArray (PrimState m) p) => p a -> Int -> Int -> m (MutableArray (PrimState m) a)
cloneAnArray =  gcoerceWith (unsafeArrayCoercion @(PrimState m) @p @a) $ coerce $ cloneMutableArray @m @a
{-# inline cloneAnArray #-}

sizeofAnArray :: forall s p a. AnArray s p => p a -> Int
sizeofAnArray = gcoerceWith (unsafeArrayCoercion @s @p @a) $ coerce $ sizeofMutableArray @s @a
{-# inline sizeofAnArray #-}