primitive-offset-0.2.0.0: src/Data/Primitive/PrimArray/Offset.hs
{-# language DuplicateRecordFields #-}
-- | Data types for describing an array paired with an index
-- into it. This is intended to be used in wrappers for @unsafe@
-- FFI calls. For example, the POSIX function @recvfrom@ takes
-- a @socklen_t*@ argument. (Let us assume that @socklen_t@
-- is equivalant to @int@ for this example.) How is this argument best
-- described by a Haskell type? When working with pinned memory,
-- the best option @'Ptr' 'CInt'@.
-- It works equally well regardless of whether we originally had an
-- array of 'CInt' or a pointer to a single 'CInt'. This works because
-- of functions like 'Data.Primitive.advancePtr' and
-- 'Foreign.Ptr.plusPtr' that effectively index into an array.
-- Unpinned memory, however, is trickier. We want to have the full
-- flexibility (handling both a single-element or
-- multi-element buffer) that @'Ptr' 'CInt'@ affords. We cannot
-- offset into a 'MutablePrimArray' to get a new one like we
-- could with 'Ptr'. (Such a function is not possible because
-- unpinned memory can be relocated.) So, the offseting must
-- be done in the C function wrapped by the @unsafe@ FFI. This
-- means that the offset must be passed together with the
-- 'MutablePrimArray'. This is the precisely the product that
-- 'MutablePrimArrayOffset' represents. In a type signature, it
-- provides additional clarity about the meaning of the offset.
--
-- This library is used in the extensively in the @posix-api@
-- library to clarify intent in a number of type signatures.
module Data.Primitive.PrimArray.Offset
( -- * Types
PrimArrayOffset(..)
, MutablePrimArrayOffset(..)
-- * Resolution
, indexOffset
, readOffset
) where
import Control.Monad.Primitive (PrimMonad,PrimState)
import Data.Primitive (Prim,PrimArray,MutablePrimArray)
import Data.Primitive (indexPrimArray,readPrimArray)
-- | A primitive array and an index into the array.
data PrimArrayOffset a = PrimArrayOffset
{ array :: {-# UNPACK #-} !(PrimArray a)
, offset :: {-# UNPACK #-} !Int
}
-- | A mutable primitive array and an index into the array.
data MutablePrimArrayOffset s a = MutablePrimArrayOffset
{ array :: {-# UNPACK #-} !(MutablePrimArray s a)
, offset :: {-# UNPACK #-} !Int
}
-- | Recover the element in the primitive array.
indexOffset :: Prim a
=> PrimArrayOffset a
-> a
{-# inline indexOffset #-}
indexOffset (PrimArrayOffset arr ix) = indexPrimArray arr ix
-- | Recover the element in the mutable primitive array.
readOffset :: (PrimMonad m, Prim a)
=> MutablePrimArrayOffset (PrimState m) a
-> m a
{-# inline readOffset #-}
readOffset (MutablePrimArrayOffset arr ix) = readPrimArray arr ix