module Data.Array.Storable.Internals (
    StorableArray(..),
    withStorableArray,
    touchStorableArray,
    unsafeForeignPtrToStorableArray,
  ) where
import Data.Array.Base
import Data.Array.MArray
import Foreign hiding (newArray)
data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
type role StorableArray nominal nominal
instance Storable e => MArray StorableArray e IO where
    getBounds (StorableArray l u _ _) = return (l,u)
    getNumElements (StorableArray _l _u n _) = return n
    newArray (l,u) initialValue = do
        fp <- mallocForeignPtrArray size
        withForeignPtr fp $ \a ->
            sequence_ [pokeElemOff a i initialValue | i <- [0..size1]]
        return (StorableArray l u size fp)
        where
        size = rangeSize (l,u)
    unsafeNewArray_ (l,u) = do
        let n = rangeSize (l,u)
        fp <- mallocForeignPtrArray n
        return (StorableArray l u n fp)
    newArray_ = unsafeNewArray_
    unsafeRead (StorableArray _ _ _ fp) i =
        withForeignPtr fp $ \a -> peekElemOff a i
    unsafeWrite (StorableArray _ _ _ fp) i e =
        withForeignPtr fp $ \a -> pokeElemOff a i e
withStorableArray :: StorableArray i e -> (Ptr e -> IO a) -> IO a
withStorableArray (StorableArray _ _ _ fp) f = withForeignPtr fp f
touchStorableArray :: StorableArray i e -> IO ()
touchStorableArray (StorableArray _ _ _ fp) = touchForeignPtr fp
unsafeForeignPtrToStorableArray
   :: Ix i => ForeignPtr e -> (i,i) -> IO (StorableArray i e)
unsafeForeignPtrToStorableArray p (l,u) =
   return (StorableArray l u (rangeSize (l,u)) p)