    -- |
    -- Module      : Basement.Types.OffsetSize
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : experimental
    -- Portability : portable
    --
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE MagicHash                  #-}
    {-# LANGUAGE MultiParamTypeClasses      #-}
    {-# LANGUAGE CPP                        #-}
    {-# LANGUAGE ScopedTypeVariables        #-}
    {-# LANGUAGE TypeFamilies               #-}
    {-# LANGUAGE ConstraintKinds            #-}
    {-# OPTIONS_GHC -fno-prof-auto          #-}
    module Basement.Types.OffsetSize
        ( FileSize(..)
        , Offset(..)
        , Offset8
        , sentinel
        , offsetOfE
        , offsetPlusE
        , offsetMinusE
        , offsetRecast
        , offsetCast
        , offsetSub
        , offsetShiftL
        , offsetShiftR
        , sizeCast
        , sizeLastOffset
        , sizeAsOffset
        , sizeSub
        , countOfRoundUp
        , offsetAsSize
        , (+.)
        , (.==#)
        , CountOf(..)
        , sizeOfE
        , csizeOfOffset
        , csizeOfSize
        , sizeOfCSSize
        , sizeOfCSize
        , Countable
        , Offsetable
        , natValCountOf
        , natValOffset
        ) where

    #include "MachDeps.h"

    import GHC.Types
    import GHC.Word
    import GHC.Int
    import GHC.Prim
    import qualified GHC.Prim
    import System.Posix.Types (CSsize (..))
    import Data.Bits
    import Basement.Compat.Base
    import Basement.Compat.C.Types
    import Basement.Compat.Semigroup
    import Data.Proxy
    import Basement.Numerical.Number
    import Basement.Numerical.Additive
    import Basement.Numerical.Subtractive
    import Basement.Numerical.Multiplicative
    import Basement.Numerical.Conversion (intToWord)
    import Basement.Nat
    import Basement.IntegralConv
    import Data.List (foldl')
    import qualified Prelude

    #if WORD_SIZE_IN_BITS < 64
    #if __GLASGOW_HASKELL__ >= 904
    import GHC.Exts
    #else
    import GHC.IntWord64
    #endif
    #endif

    -- | File size in bytes
    newtype FileSize = FileSize Word64
        deriving (Int -> FileSize -> ShowS
    [FileSize] -> ShowS
    FileSize -> String
    (Int -> FileSize -> ShowS)
    -> (FileSize -> String) -> ([FileSize] -> ShowS) -> Show FileSize
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> FileSize -> ShowS
    showsPrec :: Int -> FileSize -> ShowS
    $cshow :: FileSize -> String
    show :: FileSize -> String
    $cshowList :: [FileSize] -> ShowS
    showList :: [FileSize] -> ShowS
    Show,FileSize -> FileSize -> Bool
    (FileSize -> FileSize -> Bool)
    -> (FileSize -> FileSize -> Bool) -> Eq FileSize
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: FileSize -> FileSize -> Bool
    == :: FileSize -> FileSize -> Bool
    $c/= :: FileSize -> FileSize -> Bool
    /= :: FileSize -> FileSize -> Bool
    Eq,Eq FileSize
    Eq FileSize =>
    (FileSize -> FileSize -> Ordering)
    -> (FileSize -> FileSize -> Bool)
    -> (FileSize -> FileSize -> Bool)
    -> (FileSize -> FileSize -> Bool)
    -> (FileSize -> FileSize -> Bool)
    -> (FileSize -> FileSize -> FileSize)
    -> (FileSize -> FileSize -> FileSize)
    -> Ord FileSize
    FileSize -> FileSize -> Bool
    FileSize -> FileSize -> Ordering
    FileSize -> FileSize -> FileSize
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: FileSize -> FileSize -> Ordering
    compare :: FileSize -> FileSize -> Ordering
    $c< :: FileSize -> FileSize -> Bool
    < :: FileSize -> FileSize -> Bool
    $c<= :: FileSize -> FileSize -> Bool
    <= :: FileSize -> FileSize -> Bool
    $c> :: FileSize -> FileSize -> Bool
    > :: FileSize -> FileSize -> Bool
    $c>= :: FileSize -> FileSize -> Bool
    >= :: FileSize -> FileSize -> Bool
    $cmax :: FileSize -> FileSize -> FileSize
    max :: FileSize -> FileSize -> FileSize
    $cmin :: FileSize -> FileSize -> FileSize
    min :: FileSize -> FileSize -> FileSize
    Ord)

    -- | Offset in bytes used for memory addressing (e.g. in a vector, string, ..)
    type Offset8 = Offset Word8

    -- | Offset in a data structure consisting of elements of type 'ty'.
    --
    -- Int is a terrible backing type which is hard to get away from,
    -- considering that GHC/Haskell are mostly using this for offset.
    -- Trying to bring some sanity by a lightweight wrapping.
    newtype Offset ty = Offset Int
        deriving (Int -> Offset ty -> ShowS
    [Offset ty] -> ShowS
    Offset ty -> String
    (Int -> Offset ty -> ShowS)
    -> (Offset ty -> String)
    -> ([Offset ty] -> ShowS)
    -> Show (Offset ty)
    forall ty. Int -> Offset ty -> ShowS
    forall ty. [Offset ty] -> ShowS
    forall ty. Offset ty -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall ty. Int -> Offset ty -> ShowS
    showsPrec :: Int -> Offset ty -> ShowS
    $cshow :: forall ty. Offset ty -> String
    show :: Offset ty -> String
    $cshowList :: forall ty. [Offset ty] -> ShowS
    showList :: [Offset ty] -> ShowS
    Show,Offset ty -> Offset ty -> Bool
    (Offset ty -> Offset ty -> Bool)
    -> (Offset ty -> Offset ty -> Bool) -> Eq (Offset ty)
    forall ty. Offset ty -> Offset ty -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall ty. Offset ty -> Offset ty -> Bool
    == :: Offset ty -> Offset ty -> Bool
    $c/= :: forall ty. Offset ty -> Offset ty -> Bool
    /= :: Offset ty -> Offset ty -> Bool
    Eq,Eq (Offset ty)
    Eq (Offset ty) =>
    (Offset ty -> Offset ty -> Ordering)
    -> (Offset ty -> Offset ty -> Bool)
    -> (Offset ty -> Offset ty -> Bool)
    -> (Offset ty -> Offset ty -> Bool)
    -> (Offset ty -> Offset ty -> Bool)
    -> (Offset ty -> Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty -> Offset ty)
    -> Ord (Offset ty)
    Offset ty -> Offset ty -> Bool
    Offset ty -> Offset ty -> Ordering
    Offset ty -> Offset ty -> Offset ty
    forall ty. Eq (Offset ty)
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    forall ty. Offset ty -> Offset ty -> Bool
    forall ty. Offset ty -> Offset ty -> Ordering
    forall ty. Offset ty -> Offset ty -> Offset ty
    $ccompare :: forall ty. Offset ty -> Offset ty -> Ordering
    compare :: Offset ty -> Offset ty -> Ordering
    $c< :: forall ty. Offset ty -> Offset ty -> Bool
    < :: Offset ty -> Offset ty -> Bool
    $c<= :: forall ty. Offset ty -> Offset ty -> Bool
    <= :: Offset ty -> Offset ty -> Bool
    $c> :: forall ty. Offset ty -> Offset ty -> Bool
    > :: Offset ty -> Offset ty -> Bool
    $c>= :: forall ty. Offset ty -> Offset ty -> Bool
    >= :: Offset ty -> Offset ty -> Bool
    $cmax :: forall ty. Offset ty -> Offset ty -> Offset ty
    max :: Offset ty -> Offset ty -> Offset ty
    $cmin :: forall ty. Offset ty -> Offset ty -> Offset ty
    min :: Offset ty -> Offset ty -> Offset ty
    Ord,Int -> Offset ty
    Offset ty -> Int
    Offset ty -> [Offset ty]
    Offset ty -> Offset ty
    Offset ty -> Offset ty -> [Offset ty]
    Offset ty -> Offset ty -> Offset ty -> [Offset ty]
    (Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty)
    -> (Int -> Offset ty)
    -> (Offset ty -> Int)
    -> (Offset ty -> [Offset ty])
    -> (Offset ty -> Offset ty -> [Offset ty])
    -> (Offset ty -> Offset ty -> [Offset ty])
    -> (Offset ty -> Offset ty -> Offset ty -> [Offset ty])
    -> Enum (Offset ty)
    forall ty. Int -> Offset ty
    forall ty. Offset ty -> Int
    forall ty. Offset ty -> [Offset ty]
    forall ty. Offset ty -> Offset ty
    forall ty. Offset ty -> Offset ty -> [Offset ty]
    forall ty. Offset ty -> Offset ty -> Offset ty -> [Offset ty]
    forall a.
    (a -> a)
    -> (a -> a)
    -> (Int -> a)
    -> (a -> Int)
    -> (a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> a -> [a])
    -> Enum a
    $csucc :: forall ty. Offset ty -> Offset ty
    succ :: Offset ty -> Offset ty
    $cpred :: forall ty. Offset ty -> Offset ty
    pred :: Offset ty -> Offset ty
    $ctoEnum :: forall ty. Int -> Offset ty
    toEnum :: Int -> Offset ty
    $cfromEnum :: forall ty. Offset ty -> Int
    fromEnum :: Offset ty -> Int
    $cenumFrom :: forall ty. Offset ty -> [Offset ty]
    enumFrom :: Offset ty -> [Offset ty]
    $cenumFromThen :: forall ty. Offset ty -> Offset ty -> [Offset ty]
    enumFromThen :: Offset ty -> Offset ty -> [Offset ty]
    $cenumFromTo :: forall ty. Offset ty -> Offset ty -> [Offset ty]
    enumFromTo :: Offset ty -> Offset ty -> [Offset ty]
    $cenumFromThenTo :: forall ty. Offset ty -> Offset ty -> Offset ty -> [Offset ty]
    enumFromThenTo :: Offset ty -> Offset ty -> Offset ty -> [Offset ty]
    Enum,Offset ty
    Offset ty -> Offset ty -> Offset ty
    Offset ty
    -> (Offset ty -> Offset ty -> Offset ty)
    -> (forall n. IsNatural n => n -> Offset ty -> Offset ty)
    -> Additive (Offset ty)
    forall ty. Offset ty
    forall a.
    a
    -> (a -> a -> a)
    -> (forall n. IsNatural n => n -> a -> a)
    -> Additive a
    forall n. IsNatural n => n -> Offset ty -> Offset ty
    forall ty. Offset ty -> Offset ty -> Offset ty
    forall ty n. IsNatural n => n -> Offset ty -> Offset ty
    $cazero :: forall ty. Offset ty
    azero :: Offset ty
    $c+ :: forall ty. Offset ty -> Offset ty -> Offset ty
    + :: Offset ty -> Offset ty -> Offset ty
    $cscale :: forall ty n. IsNatural n => n -> Offset ty -> Offset ty
    scale :: forall n. IsNatural n => n -> Offset ty -> Offset ty
    Additive,Typeable,Integer -> Offset ty
    (Integer -> Offset ty) -> Integral (Offset ty)
    forall ty. Integer -> Offset ty
    forall a. (Integer -> a) -> Integral a
    $cfromInteger :: forall ty. Integer -> Offset ty
    fromInteger :: Integer -> Offset ty
    Integral,Integer -> Offset ty
    Offset ty -> Offset ty
    Offset ty -> Offset ty -> Offset ty
    (Offset ty -> Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty)
    -> (Offset ty -> Offset ty)
    -> (Integer -> Offset ty)
    -> Num (Offset ty)
    forall ty. Integer -> Offset ty
    forall ty. Offset ty -> Offset ty
    forall ty. Offset ty -> Offset ty -> Offset ty
    forall a.
    (a -> a -> a)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> (a -> a)
    -> (a -> a)
    -> (a -> a)
    -> (Integer -> a)
    -> Num a
    $c+ :: forall ty. Offset ty -> Offset ty -> Offset ty
    + :: Offset ty -> Offset ty -> Offset ty
    $c- :: forall ty. Offset ty -> Offset ty -> Offset ty
    - :: Offset ty -> Offset ty -> Offset ty
    $c* :: forall ty. Offset ty -> Offset ty -> Offset ty
    * :: Offset ty -> Offset ty -> Offset ty
    $cnegate :: forall ty. Offset ty -> Offset ty
    negate :: Offset ty -> Offset ty
    $cabs :: forall ty. Offset ty -> Offset ty
    abs :: Offset ty -> Offset ty
    $csignum :: forall ty. Offset ty -> Offset ty
    signum :: Offset ty -> Offset ty
    $cfromInteger :: forall ty. Integer -> Offset ty
    fromInteger :: Integer -> Offset ty
    Prelude.Num)

    sentinel :: Offset ty
    sentinel = Int -> Offset ty
    forall ty. Int -> Offset ty
    Offset (-Int
    1)

    instance IsIntegral (Offset ty) where
        toInteger :: Offset ty -> Integer
    toInteger (Offset Int
    i) = Int -> Integer
    forall a. IsIntegral a => a -> Integer
    toInteger Int
    i
    instance IsNatural (Offset ty) where
        toNatural :: Offset ty -> Natural
    toNatural (Offset Int
    i) = Word -> Natural
    forall a. IsNatural a => a -> Natural
    toNatural (Int -> Word
    intToWord Int
    i)
    instance Subtractive (Offset ty) where
        type Difference (Offset ty) = CountOf ty
        (Offset Int
    a) - :: Offset ty -> Offset ty -> Difference (Offset ty)
    - (Offset Int
    b) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int
    aInt -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    -Int
    b)

    (+.) :: Offset ty -> Int -> Offset ty
    +. :: forall ty. Offset ty -> Int -> Offset ty
    (+.) (Offset Int
    a) Int
    b = Int -> Offset ty
    forall ty. Int -> Offset ty
    Offset (Int
    a Int -> Int -> Int
    forall a. Additive a => a -> a -> a
    + Int
    b)
    {-# INLINE (+.) #-}

    -- . is offset (as a pointer from a beginning), and # is the size (amount of data)
    (.==#) :: Offset ty -> CountOf ty -> Bool
    .==# :: forall ty. Offset ty -> CountOf ty -> Bool
    (.==#) (Offset Int
    ofs) (CountOf Int
    sz) = Int
    ofs Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    sz
    {-# INLINE (.==#) #-}

    offsetOfE :: CountOf Word8 -> Offset ty -> Offset8
    offsetOfE :: forall ty. CountOf Word8 -> Offset ty -> Offset8
    offsetOfE (CountOf Int
    sz) (Offset Int
    ty) = Int -> Offset8
    forall ty. Int -> Offset ty
    Offset (Int
    ty Int -> Int -> Int
    forall a. Multiplicative a => a -> a -> a
    * Int
    sz)

    offsetPlusE :: Offset ty -> CountOf ty -> Offset ty
    offsetPlusE :: forall ty. Offset ty -> CountOf ty -> Offset ty
    offsetPlusE (Offset Int
    ofs) (CountOf Int
    sz) = Int -> Offset ty
    forall ty. Int -> Offset ty
    Offset (Int
    ofs Int -> Int -> Int
    forall a. Additive a => a -> a -> a
    + Int
    sz)

    offsetMinusE :: Offset ty -> CountOf ty -> Offset ty
    offsetMinusE :: forall ty. Offset ty -> CountOf ty -> Offset ty
    offsetMinusE (Offset Int
    ofs) (CountOf Int
    sz) = Int -> Offset ty
    forall ty. Int -> Offset ty
    Offset (Int
    ofs Int -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    - Int
    sz)

    -- | subtract 2 CountOf values of the same type.
    --
    -- m need to be greater than n, otherwise negative count error ensue
    -- use the safer (-) version if unsure.
    offsetSub :: Offset a -> Offset a -> Offset a
    offsetSub :: forall ty. Offset ty -> Offset ty -> Offset ty
    offsetSub (Offset Int
    m) (Offset Int
    n) = Int -> Offset a
    forall ty. Int -> Offset ty
    Offset (Int
    m Int -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    - Int
    n)

    offsetRecast :: CountOf Word8 -> CountOf Word8 -> Offset ty -> Offset ty2
    offsetRecast :: forall ty ty2.
    CountOf Word8 -> CountOf Word8 -> Offset ty -> Offset ty2
    offsetRecast CountOf Word8
    szTy (CountOf Int
    szTy2) Offset ty
    ofs =
        let (Offset Int
    bytes) = CountOf Word8 -> Offset ty -> Offset8
    forall ty. CountOf Word8 -> Offset ty -> Offset8
    offsetOfE CountOf Word8
    szTy Offset ty
    ofs
         in Int -> Offset ty2
    forall ty. Int -> Offset ty
    Offset (Int
    bytes Int -> Int -> Int
    forall a. IDivisible a => a -> a -> a
    `div` Int
    szTy2)

    offsetShiftR :: Int -> Offset ty -> Offset ty2
    offsetShiftR :: forall ty ty2. Int -> Offset ty -> Offset ty2
    offsetShiftR Int
    n (Offset Int
    o) = Int -> Offset ty2
    forall ty. Int -> Offset ty
    Offset (Int
    o Int -> Int -> Int
    forall a. Bits a => a -> Int -> a
    `unsafeShiftR` Int
    n)

    offsetShiftL :: Int -> Offset ty -> Offset ty2
    offsetShiftL :: forall ty ty2. Int -> Offset ty -> Offset ty2
    offsetShiftL Int
    n (Offset Int
    o) = Int -> Offset ty2
    forall ty. Int -> Offset ty
    Offset (Int
    o Int -> Int -> Int
    forall a. Bits a => a -> Int -> a
    `unsafeShiftL` Int
    n)

    offsetCast :: Proxy (a -> b) -> Offset a -> Offset b
    offsetCast :: forall a b. Proxy (a -> b) -> Offset a -> Offset b
    offsetCast Proxy (a -> b)
    _ (Offset Int
    o) = Int -> Offset b
    forall ty. Int -> Offset ty
    Offset Int
    o
    {-# INLINE offsetCast #-}

    sizeCast :: Proxy (a -> b) -> CountOf a -> CountOf b
    sizeCast :: forall a b. Proxy (a -> b) -> CountOf a -> CountOf b
    sizeCast Proxy (a -> b)
    _ (CountOf Int
    sz) = Int -> CountOf b
    forall ty. Int -> CountOf ty
    CountOf Int
    sz
    {-# INLINE sizeCast #-}

    -- | subtract 2 CountOf values of the same type.
    --
    -- m need to be greater than n, otherwise negative count error ensue
    -- use the safer (-) version if unsure.
    sizeSub :: CountOf a -> CountOf a -> CountOf a
    sizeSub :: forall a. CountOf a -> CountOf a -> CountOf a
    sizeSub (CountOf Int
    m) (CountOf Int
    n)
        | Int
    Difference Int
    diff Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    0 = Int -> CountOf a
    forall ty. Int -> CountOf ty
    CountOf Int
    Difference Int
    diff
        | Bool
    otherwise = String -> CountOf a
    forall a. HasCallStack => String -> a
    error String
    "sizeSub negative size"
      where
        diff :: Difference Int
    diff = Int
    m Int -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    - Int
    n

    -- TODO add a callstack, or a construction to prevent size == 0 error
    sizeLastOffset :: CountOf a -> Offset a
    sizeLastOffset :: forall a. CountOf a -> Offset a
    sizeLastOffset (CountOf Int
    s)
        | Int
    s Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    0     = Int -> Offset a
    forall ty. Int -> Offset ty
    Offset (Int -> Int
    forall a. Enum a => a -> a
    pred Int
    s)
        | Bool
    otherwise = String -> Offset a
    forall a. HasCallStack => String -> a
    error String
    "last offset on size 0"

    sizeAsOffset :: CountOf a -> Offset a
    sizeAsOffset :: forall a. CountOf a -> Offset a
    sizeAsOffset (CountOf Int
    a) = Int -> Offset a
    forall ty. Int -> Offset ty
    Offset Int
    a
    {-# INLINE sizeAsOffset #-}

    offsetAsSize :: Offset a -> CountOf a
    offsetAsSize :: forall a. Offset a -> CountOf a
    offsetAsSize (Offset Int
    a) = Int -> CountOf a
    forall ty. Int -> CountOf ty
    CountOf Int
    a
    {-# INLINE offsetAsSize #-}

    -- | CountOf of a data structure.
    --
    -- More specifically, it represents the number of elements of type `ty` that fit
    -- into the data structure.
    --
    -- >>> length (fromList ['a', 'b', 'c', '🌟']) :: CountOf Char
    -- CountOf 4
    --
    -- Same caveats as 'Offset' apply here.
    newtype CountOf ty = CountOf Int
        deriving (Int -> CountOf ty -> ShowS
    [CountOf ty] -> ShowS
    CountOf ty -> String
    (Int -> CountOf ty -> ShowS)
    -> (CountOf ty -> String)
    -> ([CountOf ty] -> ShowS)
    -> Show (CountOf ty)
    forall ty. Int -> CountOf ty -> ShowS
    forall ty. [CountOf ty] -> ShowS
    forall ty. CountOf ty -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall ty. Int -> CountOf ty -> ShowS
    showsPrec :: Int -> CountOf ty -> ShowS
    $cshow :: forall ty. CountOf ty -> String
    show :: CountOf ty -> String
    $cshowList :: forall ty. [CountOf ty] -> ShowS
    showList :: [CountOf ty] -> ShowS
    Show,CountOf ty -> CountOf ty -> Bool
    (CountOf ty -> CountOf ty -> Bool)
    -> (CountOf ty -> CountOf ty -> Bool) -> Eq (CountOf ty)
    forall ty. CountOf ty -> CountOf ty -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall ty. CountOf ty -> CountOf ty -> Bool
    == :: CountOf ty -> CountOf ty -> Bool
    $c/= :: forall ty. CountOf ty -> CountOf ty -> Bool
    /= :: CountOf ty -> CountOf ty -> Bool
    Eq,Eq (CountOf ty)
    Eq (CountOf ty) =>
    (CountOf ty -> CountOf ty -> Ordering)
    -> (CountOf ty -> CountOf ty -> Bool)
    -> (CountOf ty -> CountOf ty -> Bool)
    -> (CountOf ty -> CountOf ty -> Bool)
    -> (CountOf ty -> CountOf ty -> Bool)
    -> (CountOf ty -> CountOf ty -> CountOf ty)
    -> (CountOf ty -> CountOf ty -> CountOf ty)
    -> Ord (CountOf ty)
    CountOf ty -> CountOf ty -> Bool
    CountOf ty -> CountOf ty -> Ordering
    CountOf ty -> CountOf ty -> CountOf ty
    forall ty. Eq (CountOf ty)
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    forall ty. CountOf ty -> CountOf ty -> Bool
    forall ty. CountOf ty -> CountOf ty -> Ordering
    forall a. CountOf a -> CountOf a -> CountOf a
    $ccompare :: forall ty. CountOf ty -> CountOf ty -> Ordering
    compare :: CountOf ty -> CountOf ty -> Ordering
    $c< :: forall ty. CountOf ty -> CountOf ty -> Bool
    < :: CountOf ty -> CountOf ty -> Bool
    $c<= :: forall ty. CountOf ty -> CountOf ty -> Bool
    <= :: CountOf ty -> CountOf ty -> Bool
    $c> :: forall ty. CountOf ty -> CountOf ty -> Bool
    > :: CountOf ty -> CountOf ty -> Bool
    $c>= :: forall ty. CountOf ty -> CountOf ty -> Bool
    >= :: CountOf ty -> CountOf ty -> Bool
    $cmax :: forall a. CountOf a -> CountOf a -> CountOf a
    max :: CountOf ty -> CountOf ty -> CountOf ty
    $cmin :: forall a. CountOf a -> CountOf a -> CountOf a
    min :: CountOf ty -> CountOf ty -> CountOf ty
    Ord,Int -> CountOf ty
    CountOf ty -> Int
    CountOf ty -> [CountOf ty]
    CountOf ty -> CountOf ty
    CountOf ty -> CountOf ty -> [CountOf ty]
    CountOf ty -> CountOf ty -> CountOf ty -> [CountOf ty]
    (CountOf ty -> CountOf ty)
    -> (CountOf ty -> CountOf ty)
    -> (Int -> CountOf ty)
    -> (CountOf ty -> Int)
    -> (CountOf ty -> [CountOf ty])
    -> (CountOf ty -> CountOf ty -> [CountOf ty])
    -> (CountOf ty -> CountOf ty -> [CountOf ty])
    -> (CountOf ty -> CountOf ty -> CountOf ty -> [CountOf ty])
    -> Enum (CountOf ty)
    forall ty. Int -> CountOf ty
    forall ty. CountOf ty -> Int
    forall ty. CountOf ty -> [CountOf ty]
    forall ty. CountOf ty -> CountOf ty
    forall ty. CountOf ty -> CountOf ty -> [CountOf ty]
    forall ty. CountOf ty -> CountOf ty -> CountOf ty -> [CountOf ty]
    forall a.
    (a -> a)
    -> (a -> a)
    -> (Int -> a)
    -> (a -> Int)
    -> (a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> [a])
    -> (a -> a -> a -> [a])
    -> Enum a
    $csucc :: forall ty. CountOf ty -> CountOf ty
    succ :: CountOf ty -> CountOf ty
    $cpred :: forall ty. CountOf ty -> CountOf ty
    pred :: CountOf ty -> CountOf ty
    $ctoEnum :: forall ty. Int -> CountOf ty
    toEnum :: Int -> CountOf ty
    $cfromEnum :: forall ty. CountOf ty -> Int
    fromEnum :: CountOf ty -> Int
    $cenumFrom :: forall ty. CountOf ty -> [CountOf ty]
    enumFrom :: CountOf ty -> [CountOf ty]
    $cenumFromThen :: forall ty. CountOf ty -> CountOf ty -> [CountOf ty]
    enumFromThen :: CountOf ty -> CountOf ty -> [CountOf ty]
    $cenumFromTo :: forall ty. CountOf ty -> CountOf ty -> [CountOf ty]
    enumFromTo :: CountOf ty -> CountOf ty -> [CountOf ty]
    $cenumFromThenTo :: forall ty. CountOf ty -> CountOf ty -> CountOf ty -> [CountOf ty]
    enumFromThenTo :: CountOf ty -> CountOf ty -> CountOf ty -> [CountOf ty]
    Enum,Typeable,Integer -> CountOf ty
    (Integer -> CountOf ty) -> Integral (CountOf ty)
    forall ty. Integer -> CountOf ty
    forall a. (Integer -> a) -> Integral a
    $cfromInteger :: forall ty. Integer -> CountOf ty
    fromInteger :: Integer -> CountOf ty
    Integral)

    instance Prelude.Num (CountOf ty) where
        fromInteger :: Integer -> CountOf ty
    fromInteger Integer
    a = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Integer -> Int
    forall a. Integral a => Integer -> a
    fromInteger Integer
    a)
        + :: CountOf ty -> CountOf ty -> CountOf ty
    (+) (CountOf Int
    a) (CountOf Int
    b) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int
    aInt -> Int -> Int
    forall a. Additive a => a -> a -> a
    +Int
    b)
        (-) (CountOf Int
    a) (CountOf Int
    b)
            | Int
    b Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    a     = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf Int
    0
            | Bool
    otherwise = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int
    a Int -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    - Int
    b)
        * :: CountOf ty -> CountOf ty -> CountOf ty
    (*) (CountOf Int
    a) (CountOf Int
    b) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int
    aInt -> Int -> Int
    forall a. Multiplicative a => a -> a -> a
    *Int
    b)
        abs :: CountOf ty -> CountOf ty
    abs CountOf ty
    a = CountOf ty
    a
        negate :: CountOf ty -> CountOf ty
    negate CountOf ty
    _ = String -> CountOf ty
    forall a. HasCallStack => String -> a
    error String
    "cannot negate CountOf: use Foundation Numerical hierarchy for this function to not be exposed to CountOf"
        signum :: CountOf ty -> CountOf ty
    signum (CountOf Int
    a) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int -> Int
    forall a. Num a => a -> a
    Prelude.signum Int
    a)

    instance IsIntegral (CountOf ty) where
        toInteger :: CountOf ty -> Integer
    toInteger (CountOf Int
    i) = Int -> Integer
    forall a. IsIntegral a => a -> Integer
    toInteger Int
    i
    instance IsNatural (CountOf ty) where
        toNatural :: CountOf ty -> Natural
    toNatural (CountOf Int
    i) = Word -> Natural
    forall a. IsNatural a => a -> Natural
    toNatural (Int -> Word
    intToWord Int
    i)

    instance Additive (CountOf ty) where
        azero :: CountOf ty
    azero = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf Int
    0
        + :: CountOf ty -> CountOf ty -> CountOf ty
    (+) (CountOf Int
    a) (CountOf Int
    b) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int
    aInt -> Int -> Int
    forall a. Additive a => a -> a -> a
    +Int
    b)
        scale :: forall n. IsNatural n => n -> CountOf ty -> CountOf ty
    scale n
    n (CountOf Int
    a) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (n -> Int -> Int
    forall n. IsNatural n => n -> Int -> Int
    forall a n. (Additive a, IsNatural n) => n -> a -> a
    scale n
    n Int
    a)

    instance Subtractive (CountOf ty) where
        type Difference (CountOf ty) = Maybe (CountOf ty)
        (CountOf Int
    a) - :: CountOf ty -> CountOf ty -> Difference (CountOf ty)
    - (CountOf Int
    b) | Int
    a Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    b    = CountOf ty -> Maybe (CountOf ty)
    CountOf ty -> Difference (CountOf ty)
    forall a. a -> Maybe a
    Just (CountOf ty -> Difference (CountOf ty))
    -> (Int -> CountOf ty) -> Int -> Difference (CountOf ty)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
    Category cat =>
    cat b c -> cat a b -> cat a c
    . Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int -> Difference (CountOf ty)) -> Int -> Difference (CountOf ty)
    forall a b. (a -> b) -> a -> b
    $ Int
    a Int -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    - Int
    b
                                  | Bool
    otherwise = Maybe (CountOf ty)
    Difference (CountOf ty)
    forall a. Maybe a
    Nothing

    instance Semigroup (CountOf ty) where
        <> :: CountOf ty -> CountOf ty -> CountOf ty
    (<>) = CountOf ty -> CountOf ty -> CountOf ty
    forall a. Additive a => a -> a -> a
    (+)

    instance Monoid (CountOf ty) where
        mempty :: CountOf ty
    mempty = CountOf ty
    forall a. Additive a => a
    azero
        mconcat :: [CountOf ty] -> CountOf ty
    mconcat = (CountOf ty -> CountOf ty -> CountOf ty)
    -> CountOf ty -> [CountOf ty] -> CountOf ty
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' CountOf ty -> CountOf ty -> CountOf ty
    forall a. Additive a => a -> a -> a
    (+) CountOf ty
    0

    sizeOfE :: CountOf Word8 -> CountOf ty -> CountOf Word8
    sizeOfE :: forall ty. CountOf Word8 -> CountOf ty -> CountOf Word8
    sizeOfE (CountOf Int
    sz) (CountOf Int
    ty) = Int -> CountOf Word8
    forall ty. Int -> CountOf ty
    CountOf (Int
    ty Int -> Int -> Int
    forall a. Multiplicative a => a -> a -> a
    * Int
    sz)

    -- | alignment need to be a power of 2
    countOfRoundUp :: Int -> CountOf ty -> CountOf ty
    countOfRoundUp :: forall ty. Int -> CountOf ty -> CountOf ty
    countOfRoundUp Int
    alignment (CountOf Int
    n) = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf ((Int
    n Int -> Int -> Int
    forall a. Additive a => a -> a -> a
    + (Int
    alignmentInt -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    -Int
    1)) Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .&. Int -> Int
    forall a. Bits a => a -> a
    complement (Int
    alignmentInt -> Int -> Difference Int
    forall a. Subtractive a => a -> a -> Difference a
    -Int
    1))

    -- when #if WORD_SIZE_IN_BITS < 64 the 2 following are wrong
    -- instead of using FromIntegral and being silently wrong
    -- explicit pattern match to sort it out.

    csizeOfSize :: CountOf Word8 -> CSize
    #if WORD_SIZE_IN_BITS < 64
    #if __GLASGOW_HASKELL__ >= 904
    csizeOfSize (CountOf (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
    #else
    csizeOfSize (CountOf (I# sz)) = CSize (W32# (int2Word# sz))
    #endif
    #else
    #if __GLASGOW_HASKELL__ >= 904
    csizeOfSize :: CountOf Word8 -> CSize
    csizeOfSize (CountOf (I# Int#
    sz)) = Word64 -> CSize
    CSize (Word64# -> Word64
    W64# (Word# -> Word64#
    wordToWord64# (Int# -> Word#
    int2Word# Int#
    sz)))
    #else
    csizeOfSize (CountOf (I# sz)) = CSize (W64# (int2Word# sz))
    #endif
    #endif

    csizeOfOffset :: Offset8 -> CSize
    #if WORD_SIZE_IN_BITS < 64
    #if __GLASGOW_HASKELL__ >= 904
    csizeOfOffset (Offset (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
    #else
    csizeOfOffset (Offset (I# sz)) = CSize (W32# (int2Word# sz))
    #endif
    #else
    #if __GLASGOW_HASKELL__ >= 904
    csizeOfOffset :: Offset8 -> CSize
    csizeOfOffset (Offset (I# Int#
    sz)) = Word64 -> CSize
    CSize (Word64# -> Word64
    W64# (Word# -> Word64#
    wordToWord64# (Int# -> Word#
    int2Word# Int#
    sz)))
    #else
    csizeOfOffset (Offset (I# sz)) = CSize (W64# (int2Word# sz))
    #endif
    #endif

    sizeOfCSSize :: CSsize -> CountOf Word8
    sizeOfCSSize :: CSsize -> CountOf Word8
    sizeOfCSSize (CSsize (-1))      = String -> CountOf Word8
    forall a. HasCallStack => String -> a
    error String
    "invalid size: CSSize is -1"
    #if WORD_SIZE_IN_BITS < 64
    #if __GLASGOW_HASKELL__ >= 904
    sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# (int32ToInt# sz))
    #else
    sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# sz)
    #endif
    #else
    #if __GLASGOW_HASKELL__ >= 904
    sizeOfCSSize (CSsize (I64# Int64#
    sz)) = Int -> CountOf Word8
    forall ty. Int -> CountOf ty
    CountOf (Int# -> Int
    I# (Int64# -> Int#
    int64ToInt# Int64#
    sz))
    #else
    sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# sz)
    #endif
    #endif

    sizeOfCSize :: CSize -> CountOf Word8
    #if WORD_SIZE_IN_BITS < 64
    #if __GLASGOW_HASKELL__ >= 904
    sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# (word32ToWord# sz)))
    #else
    sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# sz))
    #endif
    #else
    #if __GLASGOW_HASKELL__ >= 904
    sizeOfCSize :: CSize -> CountOf Word8
    sizeOfCSize (CSize (W64# Word64#
    sz)) = Int -> CountOf Word8
    forall ty. Int -> CountOf ty
    CountOf (Int# -> Int
    I# (Word# -> Int#
    word2Int# (Word64# -> Word#
    word64ToWord# Word64#
    sz)))
    #else
    sizeOfCSize (CSize (W64# sz)) = CountOf (I# (word2Int# sz))
    #endif
    #endif

    natValCountOf :: forall n ty proxy . (KnownNat n, NatWithinBound (CountOf ty) n) => proxy n -> CountOf ty
    natValCountOf :: forall (n :: Natural) ty (proxy :: Natural -> *).
    (KnownNat n, NatWithinBound (CountOf ty) n) =>
    proxy n -> CountOf ty
    natValCountOf proxy n
    n = Int -> CountOf ty
    forall ty. Int -> CountOf ty
    CountOf (Int -> CountOf ty) -> Int -> CountOf ty
    forall a b. (a -> b) -> a -> b
    $ Integer -> Int
    forall a b. (Integral a, Num b) => a -> b
    Prelude.fromIntegral (proxy n -> Integer
    forall (n :: Natural) (proxy :: Natural -> *).
    KnownNat n =>
    proxy n -> Integer
    natVal proxy n
    n)

    natValOffset :: forall n ty proxy . (KnownNat n, NatWithinBound (Offset ty) n) => proxy n -> Offset ty
    natValOffset :: forall (n :: Natural) ty (proxy :: Natural -> *).
    (KnownNat n, NatWithinBound (Offset ty) n) =>
    proxy n -> Offset ty
    natValOffset proxy n
    n = Int -> Offset ty
    forall ty. Int -> Offset ty
    Offset (Int -> Offset ty) -> Int -> Offset ty
    forall a b. (a -> b) -> a -> b
    $ Integer -> Int
    forall a b. (Integral a, Num b) => a -> b
    Prelude.fromIntegral (proxy n -> Integer
    forall (n :: Natural) (proxy :: Natural -> *).
    KnownNat n =>
    proxy n -> Integer
    natVal proxy n
    n)

    type instance NatNumMaxBound (CountOf x) = NatNumMaxBound Int
    type instance NatNumMaxBound (Offset x) = NatNumMaxBound Int

    type Countable ty n = NatWithinBound (CountOf ty) n
    type Offsetable ty n = NatWithinBound (Offset ty) n