packages feed

twee-lib-2.1: src/Data/Primitive/Checked.hs

-- | A helper module for array bounds checking.

module Data.Primitive.Checked where

import Data.Primitive(Prim, sizeOf)

-- | A type class of things which have a size (e.g., arrays).
class Sized a where
  -- | Read the size of the thing.
  size :: a -> Int

-- | Check that a single access is in bounds.
{-# INLINE check #-}
check :: Sized a => a -> Int -> b -> b
check arr n x
  | n >= 0 && n < size arr = x
  | otherwise = error "out-of-bounds array access"

-- | Check that a range of accesses is in bounds.
-- The range is inclusive.
{-# INLINE range #-}
range :: Sized a => a -> Int -> Int -> b -> b
range arr n len x
  | len < 0 = error "array slice has negative length"
  | len == 0 = x
  | otherwise =
    check arr n $
    check arr (n+len-1) $ x

-- | Check that a single access is in bounds.
-- The index accessed is computed by multiplying by the size
-- of the first argument.
{-# INLINE checkPrim #-}
checkPrim :: (Sized a, Prim b) => b -> a -> Int -> c -> c
checkPrim x arr n res =
  range arr (n*sizeOf x) (sizeOf x) res
  
-- | Check that a range of accesses is in bounds.
-- The range is inclusive.
-- The index accessed is computed by multiplying by the size
-- of the first argument.
{-# INLINE rangePrim #-}
rangePrim :: (Sized a, Prim b) => b -> a -> Int -> Int -> c -> c
rangePrim x arr n len res =
  range arr (n*sizeOf x) (len*sizeOf x) res