packages feed

primitive-checked 0.7.0.0 → 0.7.2.0

raw patch · 7 files changed

+539/−227 lines, 7 filesdep ~primitivesetup-changednew-uploaderPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: primitive

API changes (from Hackage documentation)

+ Data.Primitive.Array: arrayFromList :: [a] -> Array a
+ Data.Primitive.Array: arrayFromListN :: Int -> [a] -> Array a
+ Data.Primitive.Array: fromList :: IsList l => [Item l] -> l
+ Data.Primitive.Array: fromListN :: IsList l => Int -> [Item l] -> l
+ Data.Primitive.Array: indexArray## :: HasCallStack => Array a -> Int -> (# a #)
+ Data.Primitive.Array: mapArray' :: (a -> b) -> Array a -> Array b
+ Data.Primitive.Array: runArray :: (forall s. () => ST s (MutableArray s a)) -> Array a
+ Data.Primitive.Array: traverseArrayP :: PrimMonad m => (a -> m b) -> Array a -> m (Array b)
+ Data.Primitive.ByteArray: byteArrayFromList :: Prim a => [a] -> ByteArray
+ Data.Primitive.ByteArray: byteArrayFromListN :: Prim a => Int -> [a] -> ByteArray
+ Data.Primitive.ByteArray: cloneByteArray :: HasCallStack => ByteArray -> Int -> Int -> ByteArray
+ Data.Primitive.ByteArray: cloneMutableByteArray :: (HasCallStack, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> Int -> m (MutableByteArray (PrimState m))
+ Data.Primitive.ByteArray: compareByteArrays :: ByteArray -> Int -> ByteArray -> Int -> Int -> Ordering
+ Data.Primitive.ByteArray: copyByteArrayToAddr :: (HasCallStack, PrimMonad m) => Ptr Word8 -> ByteArray -> Int -> Int -> m ()
+ Data.Primitive.ByteArray: copyByteArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Ptr a -> ByteArray -> Int -> Int -> m ()
+ Data.Primitive.ByteArray: copyMutableByteArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Ptr a -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
+ Data.Primitive.ByteArray: freezeByteArray :: (HasCallStack, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> Int -> m ByteArray
+ Data.Primitive.ByteArray: shrinkMutableByteArray :: (HasCallStack, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m ()
+ Data.Primitive.ByteArray: thawByteArray :: (HasCallStack, PrimMonad m) => ByteArray -> Int -> Int -> m (MutableByteArray (PrimState m))
+ Data.Primitive.PrimArray: cloneMutablePrimArray :: (HasCallStack, PrimMonad m, Prim a) => MutablePrimArray (PrimState m) a -> Int -> Int -> m (MutablePrimArray (PrimState m) a)
+ Data.Primitive.PrimArray: clonePrimArray :: (HasCallStack, Prim a) => PrimArray a -> Int -> Int -> PrimArray a
+ Data.Primitive.PrimArray: freezePrimArray :: (HasCallStack, PrimMonad m, Prim a) => MutablePrimArray (PrimState m) a -> Int -> Int -> m (PrimArray a)
+ Data.Primitive.PrimArray: isMutablePrimArrayPinned :: MutablePrimArray s a -> Bool
+ Data.Primitive.PrimArray: isPrimArrayPinned :: PrimArray a -> Bool
+ Data.Primitive.PrimArray: mutablePrimArrayContents :: MutablePrimArray s a -> Ptr a
+ Data.Primitive.PrimArray: newAlignedPinnedPrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)
+ Data.Primitive.PrimArray: newPinnedPrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)
+ Data.Primitive.PrimArray: primArrayContents :: PrimArray a -> Ptr a
+ Data.Primitive.PrimArray: primArrayFromList :: Prim a => [a] -> PrimArray a
+ Data.Primitive.PrimArray: primArrayFromListN :: Prim a => Int -> [a] -> PrimArray a
+ Data.Primitive.PrimArray: primArrayToList :: Prim a => PrimArray a -> [a]
+ Data.Primitive.PrimArray: thawPrimArray :: (HasCallStack, PrimMonad m, Prim a) => PrimArray a -> Int -> Int -> m (MutablePrimArray (PrimState m) a)
+ Data.Primitive.SmallArray: mapSmallArray' :: (a -> b) -> SmallArray a -> SmallArray b
+ Data.Primitive.SmallArray: runSmallArray :: (forall s. () => ST s (SmallMutableArray s a)) -> SmallArray a
+ Data.Primitive.SmallArray: shrinkSmallMutableArray :: (HasCallStack, PrimMonad m) => SmallMutableArray (PrimState m) a -> Int -> m ()
+ Data.Primitive.SmallArray: traverseSmallArrayP :: PrimMonad m => (a -> m b) -> SmallArray a -> m (SmallArray b)
- Data.Primitive.Array: indexArrayM :: HasCallStack => Monad m => Array a -> Int -> m a
+ Data.Primitive.Array: indexArrayM :: (HasCallStack, Monad m) => Array a -> Int -> m a
- Data.Primitive.Array: sameMutableArray :: () => MutableArray s a -> MutableArray s a -> Bool
+ Data.Primitive.Array: sameMutableArray :: MutableArray s a -> MutableArray s a -> Bool
- Data.Primitive.Array: sizeofArray :: () => Array a -> Int
+ Data.Primitive.Array: sizeofArray :: Array a -> Int
- Data.Primitive.Array: sizeofMutableArray :: () => MutableArray s a -> Int
+ Data.Primitive.Array: sizeofMutableArray :: MutableArray s a -> Int
- Data.Primitive.ByteArray: copyMutableByteArrayToAddr :: PrimMonad m => Ptr Word8 -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
+ Data.Primitive.ByteArray: copyMutableByteArrayToAddr :: (HasCallStack, PrimMonad m) => Ptr Word8 -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
- Data.Primitive.ByteArray: data ByteArray# :: TYPE UnliftedRep
+ Data.Primitive.ByteArray: data ByteArray# :: TYPE 'UnliftedRep
- Data.Primitive.ByteArray: data MutableByteArray# (a :: Type) :: Type -> TYPE UnliftedRep
+ Data.Primitive.ByteArray: data MutableByteArray# a :: TYPE 'UnliftedRep
- Data.Primitive.ByteArray: isMutableByteArrayPinned :: () => MutableByteArray s -> Bool
+ Data.Primitive.ByteArray: isMutableByteArrayPinned :: MutableByteArray s -> Bool
- Data.Primitive.ByteArray: mutableByteArrayContents :: () => MutableByteArray s -> Ptr Word8
+ Data.Primitive.ByteArray: mutableByteArrayContents :: MutableByteArray s -> Ptr Word8
- Data.Primitive.ByteArray: sameMutableByteArray :: () => MutableByteArray s -> MutableByteArray s -> Bool
+ Data.Primitive.ByteArray: sameMutableByteArray :: MutableByteArray s -> MutableByteArray s -> Bool
- Data.Primitive.ByteArray: sizeofMutableByteArray :: () => MutableByteArray s -> Int
+ Data.Primitive.ByteArray: sizeofMutableByteArray :: MutableByteArray s -> Int
- Data.Primitive.PrimArray: copyMutablePrimArrayToPtr :: (PrimMonad m, Prim a) => Ptr a -> MutablePrimArray (PrimState m) a -> Int -> Int -> m ()
+ Data.Primitive.PrimArray: copyMutablePrimArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Ptr a -> MutablePrimArray (PrimState m) a -> Int -> Int -> m ()
- Data.Primitive.PrimArray: copyPrimArrayToPtr :: (PrimMonad m, Prim a) => Ptr a -> PrimArray a -> Int -> Int -> m ()
+ Data.Primitive.PrimArray: copyPrimArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Ptr a -> PrimArray a -> Int -> Int -> m ()
- Data.Primitive.PrimArray: sameMutablePrimArray :: () => MutablePrimArray s a -> MutablePrimArray s a -> Bool
+ Data.Primitive.PrimArray: sameMutablePrimArray :: MutablePrimArray s a -> MutablePrimArray s a -> Bool
- Data.Primitive.PrimArray: sizeofMutablePrimArray :: Prim a => MutablePrimArray s a -> Int
+ Data.Primitive.PrimArray: sizeofMutablePrimArray :: forall s a. Prim a => MutablePrimArray s a -> Int
- Data.Primitive.SmallArray: sizeofSmallArray :: () => SmallArray a -> Int
+ Data.Primitive.SmallArray: sizeofSmallArray :: SmallArray a -> Int
- Data.Primitive.SmallArray: sizeofSmallMutableArray :: () => SmallMutableArray s a -> Int
+ Data.Primitive.SmallArray: sizeofSmallMutableArray :: SmallMutableArray s a -> Int
- Data.Primitive.SmallArray: smallArrayFromList :: () => [a] -> SmallArray a
+ Data.Primitive.SmallArray: smallArrayFromList :: [a] -> SmallArray a
- Data.Primitive.SmallArray: smallArrayFromListN :: () => Int -> [a] -> SmallArray a
+ Data.Primitive.SmallArray: smallArrayFromListN :: Int -> [a] -> SmallArray a

Files

− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
primitive-checked.cabal view
@@ -1,11 +1,11 @@ cabal-version: 2.2 name: primitive-checked-version: 0.7.0.0+version: 0.7.2.0 synopsis: primitive functions with bounds-checking homepage: https://github.com/andrewthad/primitive-checked#readme bug-reports: https://github.com/andrewthad/primitive-checked/issues author: Andrew Martin-maintainer: andrew.thaddeus@gmail.com+maintainer: Andrew Martin <andrew.thaddeus@gmail.com>, konsumlamm <konsumlamm@gmail.com> copyright: 2018 Andrew Martin license: BSD-3-Clause license-file: LICENSE@@ -14,34 +14,34 @@ description:   .   This library is intended to be used as a drop-in replacement for-  the `primitive` library in test environments. It adds bounds-checking-  to all functions in `primitive` that are able to cause segfaults.+  the @primitive@ library in test environments. It adds bounds-checking+  to all functions in @primitive@ that are able to cause segfaults.   It is not recommended to use this library in production. However,   if you are testing a library or application you wrote that uses-  `primitive`, you can temporarily replace your `primitive` dependency-  with `primitive-checked`, and your segfaults will become normal-  haskell exceptions that you can hunt down with GHC's stack trace+  @primitive@, you can temporarily replace your @primitive@ dependency+  with @primitive-checked@, and your segfaults will become normal+  Haskell exceptions that you can hunt down with GHC's stack trace   facilities.   .-  The versioning for this library matches the version of primitive-  that is targeted. The first three digits of the version match the-  version of `primitive`. The fourth digit is used for bug fixes.+  The versioning for this library matches the version of @primitive@+  that is targeted. The first three numbers of the version match the+  version of @primitive@. The fourth number is used for bug fixes.   This packages deviates slightly from the PVP in that functions-  can be added to the API with only a bump to the fourth digit.+  can be added to the API with only a bump to the fourth number.  extra-source-files:   README.md  source-repository head   type: git-  location: https://github.com/andrewthad/primitive-checked+  location: https://github.com/andrewthad/primitive-checked.git  library   hs-source-dirs:       src   build-depends:-      base >=4.9.1.0 && <5-    , primitive == 0.7.0.*+      base >= 4.9.1.0 && < 5+    , primitive == 0.7.2.*   exposed-modules:     Data.Primitive     Data.Primitive.Array@@ -57,4 +57,3 @@     , Data.Primitive.Types   default-language: Haskell2010   ghc-options: -Wall-
src/Data/Primitive.hs view
@@ -1,11 +1,11 @@-module Data.Primitive (-  module Data.Primitive.Types,-  module Data.Primitive.Array,-  module Data.Primitive.ByteArray,-  module Data.Primitive.PrimArray,-  module Data.Primitive.SmallArray,-  module Data.Primitive.MutVar-) where+module Data.Primitive+  ( module Data.Primitive.Types+  , module Data.Primitive.Array+  , module Data.Primitive.ByteArray+  , module Data.Primitive.PrimArray+  , module Data.Primitive.SmallArray+  , module Data.Primitive.MutVar+  ) where  import Data.Primitive.Array import Data.Primitive.ByteArray
src/Data/Primitive/Array.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE PackageImports #-}+{-# LANGUAGE UnboxedTuples #-}  module Data.Primitive.Array   ( Array(..)@@ -9,8 +11,10 @@   , writeArray   , indexArray   , indexArrayM+  , indexArray##   , freezeArray   , thawArray+  , A.runArray   , unsafeFreezeArray   , A.unsafeThawArray   , A.sameMutableArray@@ -20,48 +24,70 @@   , cloneMutableArray   , A.sizeofArray   , A.sizeofMutableArray+  , A.fromListN+  , A.fromList+  , A.arrayFromListN+  , A.arrayFromList+  , A.mapArray'+  , A.traverseArrayP   ) where -import Control.Monad.Primitive (PrimMonad,PrimState)-import Control.Exception (throw, ArrayException(..))+import Control.Monad.Primitive (PrimMonad, PrimState)+import Control.Exception (throw, ArrayException(..), Exception, toException) import qualified Data.List as L-import "primitive" Data.Primitive.Array (Array,MutableArray)+import "primitive" Data.Primitive.Array (Array, MutableArray) import qualified "primitive" Data.Primitive.Array as A+import GHC.Exts (raise#) import GHC.Stack  check :: HasCallStack => String -> Bool -> a -> a check _      True  x = x-check errMsg False _ = throw (IndexOutOfBounds $ "Data.Primitive.Array.Checked." ++ errMsg ++ "\n" ++ prettyCallStack callStack)+check errMsg False _ = throw (IndexOutOfBounds $ "Data.Primitive.Array." ++ errMsg ++ "\n" ++ prettyCallStack callStack) +checkUnary :: HasCallStack => String -> Bool -> (# a #) -> (# a #)+checkUnary _      True  x = x+checkUnary errMsg False _ = throwUnary (IndexOutOfBounds $ "Data.Primitive.Array." ++ errMsg ++ "\n" ++ prettyCallStack callStack)++throwUnary :: Exception e => e -> (# a #)+throwUnary e = raise# (toException e)+ newArray :: (HasCallStack, PrimMonad m) => Int -> a -> m (MutableArray (PrimState m) a)-newArray n x = check "newArray: negative size" (n>=0) (A.newArray n x)+newArray n x = check "newArray: negative size" (n >= 0) (A.newArray n x)  readArray :: (HasCallStack, PrimMonad m) => MutableArray (PrimState m) a -> Int -> m a readArray marr i = do   let siz = A.sizeofMutableArray marr-  check "readArray: index of out bounds" (i>=0 && i<siz) (A.readArray marr i)+  check "readArray: index out of bounds" (i >= 0 && i < siz) (A.readArray marr i)  writeArray :: (HasCallStack, PrimMonad m) => MutableArray (PrimState m) a -> Int -> a -> m () writeArray marr i x = do   let siz = A.sizeofMutableArray marr-  check "writeArray: index of out bounds" (i>=0 && i<siz) (A.writeArray marr i x)+  check "writeArray: index out of bounds" (i >= 0 && i < siz) (A.writeArray marr i x)  indexArray :: HasCallStack => Array a -> Int -> a-indexArray arr i = check "indexArray: index of out bounds"-  (i>=0 && i<A.sizeofArray arr)+indexArray arr i = check "indexArray: index out of bounds"+  (i >= 0 && i < A.sizeofArray arr)   (A.indexArray arr i) -indexArrayM :: HasCallStack => Monad m => Array a -> Int -> m a-indexArrayM arr i = check "indexArrayM: index of out bounds"-    (i>=0 && i<A.sizeofArray arr)-    (A.indexArrayM arr i)+indexArrayM :: (HasCallStack, Monad m) => Array a -> Int -> m a+indexArrayM arr i = check "indexArrayM: index out of bounds"+  (i >= 0 && i < A.sizeofArray arr)+  (A.indexArrayM arr i) +indexArray## :: HasCallStack => Array a -> Int -> (# a #)+indexArray## arr i = checkUnary "indexArray##: index out of bounds"+  (i >= 0 && i < A.sizeofArray arr)+  (A.indexArray## arr i)+ {-# NOINLINE errorUnsafeFreeze #-} errorUnsafeFreeze :: a errorUnsafeFreeze =-  error "Data.Primitive.Array.Checked.unsafeFreeze:\nAttempted to read from an array after unsafely freezing it."+  error "Data.Primitive.Array.unsafeFreeze:\nAttempted to read from an array after unsafely freezing it." -unsafeFreezeArray :: (HasCallStack, PrimMonad m)+-- | This installs error thunks in the argument array so that+-- any attempt to use it after an unsafeFreeze will fail.+unsafeFreezeArray+  :: (HasCallStack, PrimMonad m)   => MutableArray (PrimState m) a   -> m (Array a) unsafeFreezeArray marr = do@@ -79,11 +105,9 @@   -> Int                          -- ^ offset   -> Int                          -- ^ length   -> m (Array a)-freezeArray marr s l = do-  let siz = A.sizeofMutableArray marr-  check "freezeArray: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=siz)-    (A.freezeArray marr s l)+freezeArray marr s l = check "freezeArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofMutableArray marr)+  (A.freezeArray marr s l)  thawArray   :: (HasCallStack, PrimMonad m)@@ -91,68 +115,68 @@   -> Int     -- ^ offset   -> Int     -- ^ length   -> m (MutableArray (PrimState m) a)-thawArray arr s l = check "thawArr: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=A.sizeofArray arr)-    (A.thawArray arr s l)+thawArray arr s l = check "thawArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofArray arr)+  (A.thawArray arr s l) -copyArray :: (HasCallStack, PrimMonad m)-          => MutableArray (PrimState m) a    -- ^ destination array-          -> Int                             -- ^ offset into destination array-          -> Array a                         -- ^ source array-          -> Int                             -- ^ offset into source array-          -> Int                             -- ^ number of elements to copy-          -> m ()+copyArray+  :: (HasCallStack, PrimMonad m)+  => MutableArray (PrimState m) a -- ^ destination array+  -> Int                          -- ^ offset into destination array+  -> Array a                      -- ^ source array+  -> Int                          -- ^ offset into source array+  -> Int                          -- ^ number of elements to copy+  -> m () copyArray marr s1 arr s2 l = do   let siz = A.sizeofMutableArray marr   check "copyArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=A.sizeofArray arr && (s1+l)<=siz)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz && s2 + l <= A.sizeofArray arr)     (A.copyArray marr s1 arr s2 l) --copyMutableArray :: (HasCallStack, PrimMonad m)-          => MutableArray (PrimState m) a    -- ^ destination array-          -> Int                             -- ^ offset into destination array-          -> MutableArray (PrimState m) a    -- ^ source array-          -> Int                             -- ^ offset into source array-          -> Int                             -- ^ number of elements to copy-          -> m ()+copyMutableArray+  :: (HasCallStack, PrimMonad m)+  => MutableArray (PrimState m) a -- ^ destination array+  -> Int                          -- ^ offset into destination array+  -> MutableArray (PrimState m) a -- ^ source array+  -> Int                          -- ^ offset into source array+  -> Int                          -- ^ number of elements to copy+  -> m () copyMutableArray marr1 s1 marr2 s2 l = do   let siz1 = A.sizeofMutableArray marr1   let siz2 = A.sizeofMutableArray marr2   let explain = L.concat         [ "[dst size: "         , show siz1-        , ", dst off: " +        , ", dst off: "         , show s1         , ", src size: "         , show siz2-        , ", src off: " +        , ", src off: "         , show s2         , ", copy size: "         , show l         , "]"         ]   check ("copyMutableArray: index range of out bounds " ++ explain)-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz1 && s2 + l <= siz2)     (A.copyMutableArray marr1 s1 marr2 s2 l) --cloneArray :: HasCallStack-           => Array a -- ^ source array-           -> Int     -- ^ offset into destination array-           -> Int     -- ^ number of elements to copy-           -> Array a+cloneArray+  :: HasCallStack+  => Array a -- ^ source array+  -> Int     -- ^ offset into source array+  -> Int     -- ^ number of elements to copy+  -> Array a cloneArray arr s l = check "cloneArray: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=A.sizeofArray arr)-    (A.cloneArray arr s l)+  (s >= 0 && l >= 0 && s + l <= A.sizeofArray arr)+  (A.cloneArray arr s l) -cloneMutableArray :: (HasCallStack, PrimMonad m)-        => MutableArray (PrimState m) a -- ^ source array-        -> Int                          -- ^ offset into destination array-        -> Int                          -- ^ number of elements to copy-        -> m (MutableArray (PrimState m) a)-cloneMutableArray marr s l = do-  let siz = A.sizeofMutableArray marr-  check "cloneMutableArray: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=siz)-    (A.cloneMutableArray marr s l)+cloneMutableArray+  :: (HasCallStack, PrimMonad m)+  => MutableArray (PrimState m) a -- ^ source array+  -> Int                          -- ^ offset into source array+  -> Int                          -- ^ number of elements to copy+  -> m (MutableArray (PrimState m) a)+cloneMutableArray marr s l = check "cloneMutableArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofMutableArray marr)+  (A.cloneMutableArray marr s l)
src/Data/Primitive/ByteArray.hs view
@@ -5,8 +5,8 @@  module Data.Primitive.ByteArray   ( -- * Types-    A.ByteArray(..)-  , A.MutableByteArray(..)+    ByteArray(..)+  , MutableByteArray(..)   , A.ByteArray#   , A.MutableByteArray#     -- * Allocation@@ -14,40 +14,54 @@   , newPinnedByteArray   , newAlignedPinnedByteArray   , resizeMutableByteArray+  , shrinkMutableByteArray     -- * Element access   , readByteArray   , writeByteArray   , indexByteArray+    -- * Constructing+  , A.byteArrayFromList+  , A.byteArrayFromListN     -- * Folding   , A.foldrByteArray+    -- * Comparing+  , compareByteArrays     -- * Freezing and thawing+  , freezeByteArray+  , thawByteArray   , A.unsafeFreezeByteArray   , A.unsafeThawByteArray     -- * Block operations   , copyByteArray   , copyMutableByteArray+  , copyByteArrayToPtr+  , copyMutableByteArrayToPtr+  , copyByteArrayToAddr+  , copyMutableByteArrayToAddr   , moveByteArray   , setByteArray   , fillByteArray-  , A.copyMutableByteArrayToAddr+  , cloneByteArray+  , cloneMutableByteArray   -- * Information   , A.sizeofByteArray   , A.sizeofMutableByteArray   , A.getSizeofMutableByteArray   , A.sameMutableByteArray-  , A.byteArrayContents-  , A.mutableByteArrayContents   , A.isByteArrayPinned   , A.isMutableByteArrayPinned+  , A.byteArrayContents+  , A.mutableByteArrayContents   ) where  import Control.Monad.Primitive (PrimMonad,PrimState) import Control.Exception (throw, ArrayException(..))-import Data.Primitive.Types (Prim,sizeOf)+import Data.Primitive.Types (Prim, Ptr, sizeOf) import Data.Proxy (Proxy(..)) import Data.Word (Word8)-import "primitive" Data.Primitive.ByteArray (ByteArray,MutableByteArray)+import "primitive" Data.Primitive.ByteArray (ByteArray, MutableByteArray) import qualified "primitive" Data.Primitive.ByteArray as A+import qualified Data.List as L import GHC.Stack  check :: HasCallStack => String -> Bool -> a -> a@@ -55,44 +69,91 @@ check errMsg False _ = throw (IndexOutOfBounds $ "Data.Primitive.ByteArray." ++ errMsg ++ "\n" ++ prettyCallStack callStack)  elementSizeofByteArray :: forall a. Prim a => Proxy a -> ByteArray -> Int-elementSizeofByteArray _ arr = div (A.sizeofByteArray arr) (sizeOf (undefined :: a))+elementSizeofByteArray _ arr = A.sizeofByteArray arr `div` sizeOf (undefined :: a) -elementSizeofMutableByteArray :: forall s a. Prim a => Proxy a -> MutableByteArray s -> Int-elementSizeofMutableByteArray _ arr = div (A.sizeofMutableByteArray arr) (sizeOf (undefined :: a))+getElementSizeofMutableByteArray :: forall m a. (PrimMonad m, Prim a)+  => Proxy a -> MutableByteArray (PrimState m) -> m Int+getElementSizeofMutableByteArray _ arr = do+  sz <- A.getSizeofMutableByteArray arr+  return (sz `div` sizeOf (undefined :: a))  newByteArray :: (HasCallStack, PrimMonad m) => Int -> m (MutableByteArray (PrimState m)) newByteArray n =-    check "newByteArray: negative size" (n>=0)-  $ check ("newByteArray: reqeusted " ++ show n ++ " bytes") (n<1024*1024*1024)-  $ (A.newByteArray n)+    check "newByteArray: negative size" (n >= 0)+  $ check ("newByteArray: requested " ++ show n ++ " bytes") (n < 1024*1024*1024)+  $ A.newByteArray n  newPinnedByteArray :: (HasCallStack, PrimMonad m) => Int -> m (MutableByteArray (PrimState m))-newPinnedByteArray n = check "newPinnedByteArray: negative size" (n>=0) (A.newPinnedByteArray n)+newPinnedByteArray n = check "newPinnedByteArray: negative size" (n >= 0) (A.newPinnedByteArray n)  newAlignedPinnedByteArray :: (HasCallStack, PrimMonad m) => Int -> Int -> m (MutableByteArray (PrimState m))-newAlignedPinnedByteArray n k = check "newAlignedPinnedByteArray: negative size" (n>=0) (A.newAlignedPinnedByteArray n k)+newAlignedPinnedByteArray n k = check "newAlignedPinnedByteArray: negative size" (n >= 0) (A.newAlignedPinnedByteArray n k)  resizeMutableByteArray :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> m (MutableByteArray (PrimState m))-resizeMutableByteArray a n = check "resizeMutableByteArray: negative size" (n>=0) (A.resizeMutableByteArray a n)+resizeMutableByteArray a n = check "resizeMutableByteArray: negative size" (n >= 0) (A.resizeMutableByteArray a n) +shrinkMutableByteArray :: (HasCallStack, PrimMonad m)+  => MutableByteArray (PrimState m)+  -> Int -- ^ new size+  -> m ()+shrinkMutableByteArray marr n = do+  old <- A.getSizeofMutableByteArray marr+  check "shrinkMutableByteArray: illegal new size" (n >= 0 && n <= old) (A.shrinkMutableByteArray marr n)+ readByteArray :: forall m a. (HasCallStack, Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a readByteArray marr i = do-  let siz = elementSizeofMutableByteArray (Proxy :: Proxy a) marr-  check "readByteArray: index of out bounds" (i>=0 && i<siz) (A.readByteArray marr i)+  siz <- getElementSizeofMutableByteArray (Proxy :: Proxy a) marr+  check "readByteArray: index out of bounds" (i >= 0 && i < siz) (A.readByteArray marr i)  writeByteArray :: forall m a. (HasCallStack, Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m () writeByteArray marr i x = do-  let siz = elementSizeofMutableByteArray (Proxy :: Proxy a) marr-  check "writeByteArray: index of out bounds" (i>=0 && i<siz) (A.writeByteArray marr i x)+  siz <- getElementSizeofMutableByteArray (Proxy :: Proxy a) marr+  let explain = L.concat+        [ "[size: "+        , show siz+        , ", index: "+        , show i+        , ", elem_sz: "+        , show (sizeOf (undefined :: a))+        , "]"+        ]+  check ("writeByteArray: index out of bounds " ++ explain)+    (i >= 0 && i < siz)+    (A.writeByteArray marr i x)  -- This one is a little special. We allow users to index past the -- end of the byte array as long as the content grabbed is within -- the last machine word of the byte array. indexByteArray :: forall a. (HasCallStack, Prim a) => ByteArray -> Int -> a-indexByteArray arr i = check "indexByteArray: index of out bounds"-  (i>=0 && i< elementSizeofByteArray (Proxy :: Proxy a) arr)+indexByteArray arr i = check "indexByteArray: index out of bounds"+  (i >= 0 && i < elementSizeofByteArray (Proxy :: Proxy a) arr)   (A.indexByteArray arr i) +compareByteArrays :: ByteArray -> Int -> ByteArray -> Int -> Int -> Ordering+compareByteArrays arr1 off1 arr2 off2 len = check "compareByteArrays: index range out of bounds"+  (off1 >= 0 && off2 >= 0 && off1 + len <= A.sizeofByteArray arr1 && off2 + len <= A.sizeofByteArray arr2)+  (A.compareByteArrays arr1 off1 arr2 off2 len)++freezeByteArray+  :: (HasCallStack, PrimMonad m)+  => MutableByteArray (PrimState m) -- ^ source+  -> Int                            -- ^ offset+  -> Int                            -- ^ length+  -> m ByteArray+freezeByteArray marr s l = check "freezeByteArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofMutableByteArray marr)+  (A.freezeByteArray marr s l)++thawByteArray+  :: (HasCallStack, PrimMonad m)+  => ByteArray -- ^ source+  -> Int       -- ^ offset+  -> Int       -- ^ length+  -> m (MutableByteArray (PrimState m))+thawByteArray arr s l = check "thawByteArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofByteArray arr)+  (A.thawByteArray arr s l)+ copyByteArray :: forall m. (HasCallStack, PrimMonad m)   => MutableByteArray (PrimState m) -- ^ destination array   -> Int -- ^ offset into destination array@@ -103,10 +164,9 @@ copyByteArray marr s1 arr s2 l = do   let siz = A.sizeofMutableByteArray marr   check "copyByteArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<= A.sizeofByteArray arr && (s1+l)<=siz)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz && s2 + l <= A.sizeofByteArray arr)     (A.copyByteArray marr s1 arr s2 l) - copyMutableByteArray :: forall m. (HasCallStack, PrimMonad m)   => MutableByteArray (PrimState m) -- ^ destination array   -> Int -- ^ offset into destination array@@ -118,21 +178,105 @@   let siz1 = A.sizeofMutableByteArray marr1   let siz2 = A.sizeofMutableByteArray marr2   check "copyMutableByteArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz1 && s2 + l <= siz2)     (A.copyMutableByteArray marr1 s1 marr2 s2 l) +copyByteArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a)+  => Ptr a -- ^ destination pointer+  -> ByteArray -- ^ source array+  -> Int -- ^ offset into source array+  -> Int -- ^ number of elements to copy+  -> m ()+copyByteArrayToPtr ptr arr s l = do+  let srcSz = elementSizeofByteArray (Proxy :: Proxy a) arr+  let explain = L.concat+        [ "[src_sz: "+        , show srcSz+        , ", src_off: "+        , show s+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyByteArrayToPtr: index range of out bounds " ++ explain)+    (s >= 0 && l >= 0 && s + l <= srcSz)+    (A.copyByteArrayToPtr ptr arr s l)++copyMutableByteArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a)+  => Ptr a -- ^ destination pointer+  -> MutableByteArray (PrimState m) -- ^ source array+  -> Int -- ^ offset into source array+  -> Int -- ^ number of elements to copy+  -> m ()+copyMutableByteArrayToPtr ptr marr s l = do+  srcSz <- getElementSizeofMutableByteArray (Proxy :: Proxy a) marr+  let explain = L.concat+        [ "[src_sz: "+        , show srcSz+        , ", src_off: "+        , show s+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyMutableByteArrayToPtr: index range of out bounds " ++ explain)+    (s >= 0 && l >= 0 && s + l <= srcSz)+    (A.copyMutableByteArrayToPtr ptr marr s l)++copyByteArrayToAddr :: (HasCallStack, PrimMonad m)+  => Ptr Word8 -- ^ destination pointer+  -> ByteArray -- ^ source array+  -> Int -- ^ offset into source array+  -> Int -- ^ number of bytes to copy+  -> m ()+copyByteArrayToAddr ptr arr s l = do+  let srcSz = A.sizeofByteArray arr+  let explain = L.concat+        [ "[src_sz: "+        , show srcSz+        , ", src_off: "+        , show s+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyByteArrayToAddr: index range of out bounds " ++ explain)+    (s >= 0 && l >= 0 && s + l <= srcSz)+    (A.copyByteArrayToAddr ptr arr s l)++copyMutableByteArrayToAddr :: (HasCallStack, PrimMonad m)+  => Ptr Word8 -- ^ destination pointer+  -> MutableByteArray (PrimState m) -- ^ source array+  -> Int -- ^ offset into source array+  -> Int -- ^ number of bytes to copy+  -> m ()+copyMutableByteArrayToAddr ptr marr s l = do+  srcSz <- A.getSizeofMutableByteArray marr+  let explain = L.concat+        [ "[src_sz: "+        , show srcSz+        , ", src_off: "+        , show s+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyMutableByteArrayToAddr: index range of out bounds " ++ explain)+    (s >= 0 && l >= 0 && s + l <= srcSz)+    (A.copyMutableByteArrayToAddr ptr marr s l)+ moveByteArray :: forall m. (HasCallStack, PrimMonad m)   => MutableByteArray (PrimState m) -- ^ destination array   -> Int -- ^ offset into destination array   -> MutableByteArray (PrimState m) -- ^ source array   -> Int -- ^ offset into source array-  -> Int -- ^ number of elements to copy+  -> Int -- ^ number of bytes to copy   -> m () moveByteArray marr1 s1 marr2 s2 l = do   let siz1 = A.sizeofMutableByteArray marr1   let siz2 = A.sizeofMutableByteArray marr2   check "moveByteArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz1 && s2 + l <= siz2)     (A.moveByteArray marr1 s1 marr2 s2 l)  fillByteArray :: (HasCallStack, PrimMonad m)@@ -149,8 +293,26 @@   -> Int -- ^ number of values to fill   -> a -- ^ value to fill with   -> m ()-setByteArray dst doff sz x  =+setByteArray dst doff sz x = do+  siz <- getElementSizeofMutableByteArray (Proxy :: Proxy a) dst   check "setByteArray: index range of out bounds"-    (doff>=0 && (doff+sz)<=elementSizeofMutableByteArray (Proxy :: Proxy a) dst)+    (doff >= 0 && doff + sz <= siz)     (A.setByteArray dst doff sz x) +cloneByteArray :: HasCallStack+  => ByteArray -- ^ source array+  -> Int       -- ^ offset into source array+  -> Int       -- ^ number of bytes to copy+  -> ByteArray+cloneByteArray arr s l = check "cloneByteArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofByteArray arr)+  (A.cloneByteArray arr s l)++cloneMutableByteArray :: (HasCallStack, PrimMonad m)+  => MutableByteArray (PrimState m) -- ^ source array+  -> Int                            -- ^ offset into source array+  -> Int                            -- ^ number of bytes to copy+  -> m (MutableByteArray (PrimState m))+cloneMutableByteArray marr s l = check "cloneMutableByteArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofMutableByteArray marr)+  (A.cloneMutableByteArray marr s l)
src/Data/Primitive/PrimArray.hs view
@@ -1,44 +1,49 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}-{-# LANGUAGE MagicHash #-} {-# LANGUAGE PackageImports #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE UnboxedTuples #-} -{-# OPTIONS_GHC -Wall #-}- module Data.Primitive.PrimArray   ( -- * Types     PrimArray(..)   , MutablePrimArray(..)     -- * Allocation   , newPrimArray+  , newPinnedPrimArray+  , newAlignedPinnedPrimArray   , resizeMutablePrimArray-#if __GLASGOW_HASKELL__ >= 710   , shrinkMutablePrimArray-#endif     -- * Element Access   , readPrimArray   , writePrimArray   , indexPrimArray     -- * Freezing and Thawing+  , freezePrimArray+  , thawPrimArray   , unsafeFreezePrimArray   , A.unsafeThawPrimArray     -- * Block Operations   , copyPrimArray   , copyMutablePrimArray-#if __GLASGOW_HASKELL__ >= 708-  , A.copyPrimArrayToPtr -- this is wrong. fix this-  , A.copyMutablePrimArrayToPtr -- this is wrong. fix this-#endif+  , copyPrimArrayToPtr+  , copyMutablePrimArrayToPtr+  , clonePrimArray+  , cloneMutablePrimArray   , setPrimArray     -- * Information   , A.sameMutablePrimArray   , A.getSizeofMutablePrimArray   , A.sizeofMutablePrimArray   , A.sizeofPrimArray+  , A.primArrayContents+  , A.mutablePrimArrayContents+  , A.isPrimArrayPinned+  , A.isMutablePrimArrayPinned+    -- * List Conversion+  , A.primArrayToList+  , A.primArrayFromList+  , A.primArrayFromListN     -- * Folding   , A.foldrPrimArray   , A.foldrPrimArray'@@ -56,7 +61,7 @@   , A.filterPrimArray   , A.mapMaybePrimArray     -- * Effectful Map/Create-    -- $effectfulMapCreate+     -- ** Lazy Applicative   , A.traversePrimArray   , A.itraversePrimArray@@ -73,11 +78,11 @@   , A.mapMaybePrimArrayP   ) where -import Control.Monad.Primitive (PrimMonad,PrimState)+import Control.Monad.Primitive (PrimMonad, PrimState) import Control.Exception (throw, ArrayException(..))-import Data.Primitive.Types (Prim,sizeOf)+import Data.Primitive.Types (Prim, Ptr, sizeOf) import Data.Word (Word8)-import "primitive" Data.Primitive.PrimArray (PrimArray,MutablePrimArray)+import "primitive" Data.Primitive.PrimArray (PrimArray, MutablePrimArray) import qualified "primitive" Data.Primitive.PrimArray as A import GHC.Stack import qualified Data.List as L@@ -88,49 +93,81 @@  newPrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a) newPrimArray n =-    check "newPrimArray: negative size" (n>=0)+    check "newPrimArray: negative size" (n >= 0)   $ check ("newPrimArray: requested " ++ show n ++ " elements of size " ++ show elemSz) (n * elemSz < 1024*1024*1024)   $ A.newPrimArray n   where   elemSz = sizeOf (undefined :: a) +newPinnedPrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)+newPinnedPrimArray n =+    check "newPinnedPrimArray: negative size" (n >= 0)+  $ check ("newPinnedPrimArray: requested " ++ show n ++ " elements of size " ++ show elemSz) (n * elemSz < 1024*1024*1024)+  $ A.newPinnedPrimArray n+  where+  elemSz = sizeOf (undefined :: a)++newAlignedPinnedPrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a) => Int -> m (MutablePrimArray (PrimState m) a)+newAlignedPinnedPrimArray n =+    check "newAlignedPinnedPrimArray: negative size" (n >= 0)+  $ check ("newAlignedPinnedPrimArray: requested " ++ show n ++ " elements of size " ++ show elemSz) (n * elemSz < 1024*1024*1024)+  $ A.newAlignedPinnedPrimArray n+  where+  elemSz = sizeOf (undefined :: a)+ -- | After a call to resizeMutablePrimArray, the original reference to -- the mutable array should not be used again. This cannot truly be enforced -- except by linear types. To attempt to enforce this, we always make a--- copy of the mutable byte array and intentionally corrupt the original+-- copy of the mutable primitive array and intentionally corrupt the original -- of the original one. The strategy used here to corrupt the array is -- simply to write 1 to every bit. resizeMutablePrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a)   => MutablePrimArray (PrimState m) a   -> Int -- ^ new size   -> m (MutablePrimArray (PrimState m) a)-resizeMutablePrimArray marr@(A.MutablePrimArray x) n = check "resizeMutablePrimArray: negative size" (n>=0) $ do-  sz <- A.getSizeofMutablePrimArray marr-  marr' <- A.newPrimArray n-  A.copyMutablePrimArray marr' 0 marr 0 (min sz n)+resizeMutablePrimArray marr@(A.MutablePrimArray x) n = check "resizeMutablePrimArray: negative size" (n >= 0) $ do+  let sz = A.sizeofMutablePrimArray marr+  marr' <- A.cloneMutablePrimArray marr 0 sz   A.setPrimArray (A.MutablePrimArray x) 0 (sz * sizeOf (undefined :: a)) (0xFF :: Word8)   return marr' +freezePrimArray+  :: (HasCallStack, PrimMonad m, Prim a)+  => MutablePrimArray (PrimState m) a -- ^ source+  -> Int                              -- ^ offset+  -> Int                              -- ^ length+  -> m (PrimArray a)+freezePrimArray marr s l = check "freezePrimArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofMutablePrimArray marr)+  (A.freezePrimArray marr s l)++thawPrimArray+  :: (HasCallStack, PrimMonad m, Prim a)+  => PrimArray a -- ^ source+  -> Int         -- ^ offset+  -> Int         -- ^ length+  -> m (MutablePrimArray (PrimState m) a)+thawPrimArray arr s l = check "thawPrimArray: index range of out bounds"+    (s >= 0 && l >= 0 && s + l <= A.sizeofPrimArray arr)+    (A.thawPrimArray arr s l)+ -- | This corrupts the contents of the argument array. unsafeFreezePrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a)   => MutablePrimArray (PrimState m) a   -> m (PrimArray a) unsafeFreezePrimArray marr@(A.MutablePrimArray x) = do-  sz <- A.getSizeofMutablePrimArray marr-  marr' <- A.newPrimArray sz-  A.copyMutablePrimArray marr' 0 marr 0 sz+  let sz = A.sizeofMutablePrimArray marr+  arr <- A.freezePrimArray marr 0 sz   A.setPrimArray (A.MutablePrimArray x) 0 (sz * sizeOf (undefined :: a)) (0xFF :: Word8)-  A.unsafeFreezePrimArray marr'+  return arr -#if __GLASGOW_HASKELL__ >= 710 shrinkMutablePrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a)   => MutablePrimArray (PrimState m) a   -> Int -- ^ new size   -> m () shrinkMutablePrimArray marr n = do   old <- A.getSizeofMutablePrimArray marr-  check "shrinkMutablePrimArray: illegal new size" (n>=0 && n <= old) (A.shrinkMutablePrimArray marr n)-#endif+  check "shrinkMutablePrimArray: illegal new size" (n >= 0 && n <= old) (A.shrinkMutablePrimArray marr n)  readPrimArray :: (HasCallStack, Prim a, PrimMonad m) => MutablePrimArray (PrimState m) a -> Int -> m a readPrimArray marr i = do@@ -142,10 +179,9 @@         , show i         , "]"         ]-  check ("readPrimArray: index of out bounds " ++ explain) (i>=0 && i<siz) (A.readPrimArray marr i)+  check ("readPrimArray: index out of bounds " ++ explain) (i >= 0 && i < siz) (A.readPrimArray marr i) -writePrimArray ::-     (HasCallStack, Prim a, PrimMonad m)+writePrimArray :: (HasCallStack, Prim a, PrimMonad m)   => MutablePrimArray (PrimState m) a -- ^ array   -> Int -- ^ index   -> a -- ^ element@@ -159,10 +195,10 @@         , show i         , "]"         ]-  check ("writePrimArray: index of out bounds " ++ explain) (i>=0 && i<siz) (A.writePrimArray marr i x)+  check ("writePrimArray: index out of bounds " ++ explain) (i >= 0 && i < siz) (A.writePrimArray marr i x)  indexPrimArray :: forall a. Prim a => PrimArray a -> Int -> a-indexPrimArray arr i = +indexPrimArray arr i =   let sz = A.sizeofPrimArray arr       explain = L.concat         [ "[size: "@@ -171,8 +207,8 @@         , show i         , "]"         ]-   in check ("indexPrimArray: index of out bounds " ++ explain)-        (i>=0 && i< sz)+   in check ("indexPrimArray: index out of bounds " ++ explain)+        (i >= 0 && i < sz)         (A.indexPrimArray arr i)  setPrimArray :: forall m a. (HasCallStack, Prim a, PrimMonad m)@@ -193,9 +229,36 @@         , "]"         ]   check ("setPrimArray: index range of out bounds " ++ explain)-    (doff>=0 && (doff+sz)<=arrSz)+    (doff >= 0 && doff + sz <= arrSz)     (A.setPrimArray dst doff sz x) +copyPrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a)+  => MutablePrimArray (PrimState m) a -- ^ destination array+  -> Int -- ^ offset into destination array+  -> PrimArray a -- ^ source array+  -> Int -- ^ offset into source array+  -> Int -- ^ number of elements to copy+  -> m ()+copyPrimArray marr s1 arr s2 l = do+  dstSz <- A.getSizeofMutablePrimArray marr+  let srcSz = A.sizeofPrimArray arr+  let explain = L.concat+        [ "[dst_sz: "+        , show dstSz+        , ", dst_off: "+        , show s1+        , ", src_sz: "+        , show srcSz+        , ", src_off: "+        , show s2+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyPrimArray: index range of out bounds " ++ explain)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= dstSz && s2 + l <= srcSz)+    (A.copyPrimArray marr s1 arr s2 l)+ copyMutablePrimArray :: forall m a. (HasCallStack, PrimMonad m, Prim a)   => MutablePrimArray (PrimState m) a -- ^ destination array   -> Int -- ^ offset into destination array@@ -204,23 +267,81 @@   -> Int -- ^ number of elements to copy   -> m () copyMutablePrimArray marr1 s1 marr2 s2 l = do-  siz1 <- A.getSizeofMutablePrimArray marr1-  siz2 <- A.getSizeofMutablePrimArray marr2-  check "copyMutablePrimArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+  dstSz <- A.getSizeofMutablePrimArray marr1+  srcSz <- A.getSizeofMutablePrimArray marr2+  let explain = L.concat+        [ "[dst_sz: "+        , show dstSz+        , ", dst_off: "+        , show s1+        , ", src_sz: "+        , show srcSz+        , ", src_off: "+        , show s2+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyMutablePrimArray: index range of out bounds " ++ explain)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= dstSz && s2 + l <= srcSz)     (A.copyMutablePrimArray marr1 s1 marr2 s2 l) -copyPrimArray :: forall m a.-     (HasCallStack, PrimMonad m, Prim a)-  => MutablePrimArray (PrimState m) a -- ^ destination array-  -> Int -- ^ offset into destination array+copyPrimArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a)+  => Ptr a -- ^ destination pointer   -> PrimArray a -- ^ source array   -> Int -- ^ offset into source array   -> Int -- ^ number of elements to copy   -> m ()-copyPrimArray marr s1 arr s2 l = do-  siz <- A.getSizeofMutablePrimArray marr-  check "copyPrimArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<= A.sizeofPrimArray arr && (s1+l)<=siz)-    (A.copyPrimArray marr s1 arr s2 l)+copyPrimArrayToPtr ptr arr s l = do+  let srcSz = A.sizeofPrimArray arr+  let explain = L.concat+        [ "[src_sz: "+        , show srcSz+        , ", src_off: "+        , show s+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyPrimArrayToPtr: index range of out bounds " ++ explain)+    (s >= 0 && l >= 0 && s + l <= srcSz)+    (A.copyPrimArrayToPtr ptr arr s l) +copyMutablePrimArrayToPtr :: forall m a. (HasCallStack, PrimMonad m, Prim a)+  => Ptr a -- ^ destination pointer+  -> MutablePrimArray (PrimState m) a -- ^ source array+  -> Int -- ^ offset into source array+  -> Int -- ^ number of elements to copy+  -> m ()+copyMutablePrimArrayToPtr ptr marr s l = do+  srcSz <- A.getSizeofMutablePrimArray marr+  let explain = L.concat+        [ "[src_sz: "+        , show srcSz+        , ", src_off: "+        , show s+        , ", len: "+        , show l+        , "]"+        ]+  check ("copyMutablePrimArrayToPtr: index range of out bounds " ++ explain)+    (s >= 0 && l >= 0 && s + l <= srcSz)+    (A.copyMutablePrimArrayToPtr ptr marr s l)++clonePrimArray :: (HasCallStack, Prim a)+  => PrimArray a -- ^ source array+  -> Int         -- ^ offset into source array+  -> Int         -- ^ number of elements to copy+  -> PrimArray a+clonePrimArray arr s l = check "clonePrimArray: index range of out bounds"+    (s >= 0 && l >= 0 && s + l <= A.sizeofPrimArray arr)+    (A.clonePrimArray arr s l)++cloneMutablePrimArray :: (HasCallStack, PrimMonad m, Prim a)+  => MutablePrimArray (PrimState m) a -- ^ source array+  -> Int                              -- ^ offset into source array+  -> Int                              -- ^ number of elements to copy+  -> m (MutablePrimArray (PrimState m) a)+cloneMutablePrimArray marr s l = check "cloneMutablePrimArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofMutablePrimArray marr)+  (A.cloneMutablePrimArray marr s l)
src/Data/Primitive/SmallArray.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE PackageImports #-} {-# LANGUAGE UnboxedTuples #-}@@ -9,28 +10,34 @@   , newSmallArray   , readSmallArray   , writeSmallArray+  , copySmallArray+  , copySmallMutableArray   , indexSmallArray-  , indexSmallArray##   , indexSmallArrayM+  , indexSmallArray##+  , cloneSmallArray+  , cloneSmallMutableArray   , freezeSmallArray-  , thawSmallArray   , unsafeFreezeSmallArray+  , thawSmallArray+  , A.runSmallArray   , A.unsafeThawSmallArray-  , copySmallArray-  , copySmallMutableArray-  , cloneSmallArray-  , cloneSmallMutableArray   , A.sizeofSmallArray   , A.sizeofSmallMutableArray+#if MIN_VERSION_base(4,14,0)+  , shrinkSmallMutableArray+#endif   , A.smallArrayFromList   , A.smallArrayFromListN+  , A.mapSmallArray'+  , A.traverseSmallArrayP   ) where  import "primitive" Data.Primitive (sizeOf)-import "primitive" Data.Primitive.SmallArray (SmallArray,SmallMutableArray)+import "primitive" Data.Primitive.SmallArray (SmallArray, SmallMutableArray)  import Control.Exception (throw, ArrayException(..), Exception, toException)-import Control.Monad.Primitive (PrimMonad,PrimState)+import Control.Monad.Primitive (PrimMonad, PrimState) import GHC.Exts (raise#) import GHC.Stack @@ -39,18 +46,18 @@  check :: HasCallStack => String -> Bool -> a -> a check _      True  x = x-check errMsg False _ = throw (IndexOutOfBounds $ "Data.Primitive.SmallArray.Checked." ++ errMsg ++ "\n" ++ prettyCallStack callStack)+check errMsg False _ = throw (IndexOutOfBounds $ "Data.Primitive.SmallArray." ++ errMsg ++ "\n" ++ prettyCallStack callStack)  checkUnary :: HasCallStack => String -> Bool -> (# a #) -> (# a #) checkUnary _      True  x = x-checkUnary errMsg False _ = throwUnary (IndexOutOfBounds $ "Data.Primitive.SmallArray.Checked." ++ errMsg ++ "\n" ++ prettyCallStack callStack)+checkUnary errMsg False _ = throwUnary (IndexOutOfBounds $ "Data.Primitive.SmallArray." ++ errMsg ++ "\n" ++ prettyCallStack callStack)  throwUnary :: Exception e => e -> (# a #) throwUnary e = raise# (toException e)  newSmallArray :: (HasCallStack, PrimMonad m) => Int -> a -> m (SmallMutableArray (PrimState m) a) newSmallArray n x =-    check "newSmallArray: negative size" (n>=0)+    check "newSmallArray: negative size" (n >= 0)   $ check ("newSmallArray: requested " ++ show n ++ " elements") (n * ptrSz < 1024*1024*1024)   $ A.newSmallArray n x   where@@ -66,7 +73,7 @@         , show i         , "]"         ]-  check ("readSmallArray: index of out bounds " ++ explain) (i>=0 && i<siz) (A.readSmallArray marr i)+  check ("readSmallArray: index out of bounds " ++ explain) (i >= 0 && i < siz) (A.readSmallArray marr i)  writeSmallArray :: (HasCallStack, PrimMonad m) => SmallMutableArray (PrimState m) a -> Int -> a -> m () writeSmallArray marr i x = do@@ -78,11 +85,11 @@         , show i         , "]"         ]-  check ("writeSmallArray: index of out bounds " ++ explain) (i>=0 && i<siz) (A.writeSmallArray marr i x)+  check ("writeSmallArray: index out of bounds " ++ explain) (i >= 0 && i < siz) (A.writeSmallArray marr i x)  indexSmallArray :: HasCallStack => SmallArray a -> Int -> a-indexSmallArray arr i = check ("indexSmallArray: index of out bounds " ++ explain)-  (i>=0 && i<A.sizeofSmallArray arr)+indexSmallArray arr i = check ("indexSmallArray: index out of bounds " ++ explain)+  (i >= 0 && i < A.sizeofSmallArray arr)   (A.indexSmallArray arr i)   where   explain = L.concat@@ -94,19 +101,19 @@     ]  indexSmallArray## :: HasCallStack => SmallArray a -> Int -> (# a #)-indexSmallArray## arr i = checkUnary "indexSmallArray##: index of out bounds"-  (i>=0 && i<A.sizeofSmallArray arr)+indexSmallArray## arr i = checkUnary "indexSmallArray##: index out of bounds"+  (i >= 0 && i < A.sizeofSmallArray arr)   (A.indexSmallArray## arr i)  indexSmallArrayM :: (HasCallStack, Monad m) => SmallArray a -> Int -> m a-indexSmallArrayM arr i = check "indexSmallArrayM: index of out bounds"-    (i>=0 && i<A.sizeofSmallArray arr)-    (A.indexSmallArrayM arr i)+indexSmallArrayM arr i = check "indexSmallArrayM: index out of bounds"+  (i >= 0 && i < A.sizeofSmallArray arr)+  (A.indexSmallArrayM arr i)  {-# NOINLINE errorUnsafeFreeze #-} errorUnsafeFreeze :: a errorUnsafeFreeze =-  error "Data.Primitive.Array.Checked.unsafeFreeze:\nAttempted to read from an array after unsafely freezing it."+  error "Data.Primitive.Array.unsafeFreeze:\nAttempted to read from an array after unsafely freezing it."  -- | This installs error thunks in the argument array so that -- any attempt to use it after an unsafeFreeze will fail.@@ -125,70 +132,71 @@ freezeSmallArray   :: (HasCallStack, PrimMonad m)   => SmallMutableArray (PrimState m) a -- ^ source-  -> Int                          -- ^ offset-  -> Int                          -- ^ length+  -> Int                               -- ^ offset+  -> Int                               -- ^ length   -> m (SmallArray a)-freezeSmallArray marr s l = do-  let siz = A.sizeofSmallMutableArray marr-  check "freezeSmallArray: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=siz)-    (A.freezeSmallArray marr s l)+freezeSmallArray marr s l = check "freezeSmallArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofSmallMutableArray marr)+  (A.freezeSmallArray marr s l)  thawSmallArray   :: (HasCallStack, PrimMonad m)   => SmallArray a -- ^ source-  -> Int     -- ^ offset-  -> Int     -- ^ length+  -> Int          -- ^ offset+  -> Int          -- ^ length   -> m (SmallMutableArray (PrimState m) a)-thawSmallArray arr s l = check "thawArr: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=A.sizeofSmallArray arr)-    (A.thawSmallArray arr s l)+thawSmallArray arr s l = check "thawSmallArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofSmallArray arr)+  (A.thawSmallArray arr s l)  copySmallArray :: (HasCallStack, PrimMonad m)-          => SmallMutableArray (PrimState m) a    -- ^ destination array-          -> Int                             -- ^ offset into destination array-          -> SmallArray a                         -- ^ source array-          -> Int                             -- ^ offset into source array-          -> Int                             -- ^ number of elements to copy-          -> m ()+  => SmallMutableArray (PrimState m) a -- ^ destination array+  -> Int                               -- ^ offset into destination array+  -> SmallArray a                      -- ^ source array+  -> Int                               -- ^ offset into source array+  -> Int                               -- ^ number of elements to copy+  -> m () copySmallArray marr s1 arr s2 l = do   let siz = A.sizeofSmallMutableArray marr   check "copySmallArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=A.sizeofSmallArray arr && (s1+l)<=siz)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz && s2 + l <= A.sizeofSmallArray arr)     (A.copySmallArray marr s1 arr s2 l) - copySmallMutableArray :: (HasCallStack, PrimMonad m)-          => SmallMutableArray (PrimState m) a    -- ^ destination array-          -> Int                             -- ^ offset into destination array-          -> SmallMutableArray (PrimState m) a    -- ^ source array-          -> Int                             -- ^ offset into source array-          -> Int                             -- ^ number of elements to copy-          -> m ()+  => SmallMutableArray (PrimState m) a -- ^ destination array+  -> Int                               -- ^ offset into destination array+  -> SmallMutableArray (PrimState m) a -- ^ source array+  -> Int                               -- ^ offset into source array+  -> Int                               -- ^ number of elements to copy+  -> m () copySmallMutableArray marr1 s1 marr2 s2 l = do   let siz1 = A.sizeofSmallMutableArray marr1   let siz2 = A.sizeofSmallMutableArray marr2   check "copySmallMutableArray: index range of out bounds"-    (s1>=0 && s2>=0 && l>=0 && (s2+l)<=siz2 && (s1+l)<=siz1)+    (s1 >= 0 && s2 >= 0 && l >= 0 && s1 + l <= siz1 && s2 + l <= siz2)     (A.copySmallMutableArray marr1 s1 marr2 s2 l) - cloneSmallArray :: HasCallStack-           => SmallArray a -- ^ source array-           -> Int     -- ^ offset into destination array-           -> Int     -- ^ number of elements to copy-           -> SmallArray a+  => SmallArray a -- ^ source array+  -> Int          -- ^ offset into source array+  -> Int          -- ^ number of elements to copy+  -> SmallArray a cloneSmallArray arr s l = check "cloneSmallArray: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=A.sizeofSmallArray arr)-    (A.cloneSmallArray arr s l)+  (s >= 0 && l >= 0 && s + l <= A.sizeofSmallArray arr)+  (A.cloneSmallArray arr s l)  cloneSmallMutableArray :: (HasCallStack, PrimMonad m)-        => SmallMutableArray (PrimState m) a -- ^ source array-        -> Int                          -- ^ offset into destination array-        -> Int                          -- ^ number of elements to copy-        -> m (SmallMutableArray (PrimState m) a)-cloneSmallMutableArray marr s l = do-  let siz = A.sizeofSmallMutableArray marr-  check "cloneSmallMutableArray: index range of out bounds"-    (s>=0 && l>=0 && (s+l)<=siz)-    (A.cloneSmallMutableArray marr s l)+  => SmallMutableArray (PrimState m) a -- ^ source array+  -> Int                               -- ^ offset into source array+  -> Int                               -- ^ number of elements to copy+  -> m (SmallMutableArray (PrimState m) a)+cloneSmallMutableArray marr s l = check "cloneSmallMutableArray: index range of out bounds"+  (s >= 0 && l >= 0 && s + l <= A.sizeofSmallMutableArray marr)+  (A.cloneSmallMutableArray marr s l)++#if MIN_VERSION_base(4,14,0)+shrinkSmallMutableArray :: (HasCallStack, PrimMonad m) => SmallMutableArray (PrimState m) a -> Int -> m ()+shrinkSmallMutableArray marr n = do+    let old = A.sizeofSmallMutableArray marr+    check "shrinkSmallMutableArray: illegal new size" (n >= 0 && n <= old) (A.shrinkSmallMutableArray marr n)+#endif