{- | This is drop-in replacement for the read, write, and index functions
present in @Data.Primitive.Ptr@. While the functions from those modules
use native byte order, the functions in this one use big-endian byte order
(most significant byte first).
-}
module Data.Primitive.Ptr.BigEndian
  ( -- * Aligned
    writeOffPtr
  , readOffPtr
  , indexOffPtr
  ) where

import Control.Monad.Primitive (PrimMonad)
import Data.Primitive (Prim)
import Data.Primitive.Ptr (Ptr)
import qualified Data.Primitive.Ptr as PM
import System.ByteOrder (Bytes, fromBigEndian, toBigEndian)

{- | Write a primitive value to the pointer. The offset is given
in elements of type @a@ rather than in bytes. The most significant
byte in the value comes first.
-}
writeOffPtr :: (PrimMonad m, Prim a, Bytes a) => Ptr a -> Int -> a -> m ()
writeOffPtr :: forall (m :: * -> *) a.
(PrimMonad m, Prim a, Bytes a) =>
Ptr a -> Int -> a -> m ()
writeOffPtr Ptr a
arr Int
ix a
v = Ptr a -> Int -> a -> m ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
Ptr a -> Int -> a -> m ()
PM.writeOffPtr Ptr a
arr Int
ix (a -> a
forall a. Bytes a => a -> a
toBigEndian a
v)

{- | Read a primitive value from the pointer, interpreting the first
byte as the most significant one. The offset is given in elements of
type @a@ rather than in bytes.
-}
readOffPtr :: (PrimMonad m, Prim a, Bytes a) => Ptr a -> Int -> m a
readOffPtr :: forall (m :: * -> *) a.
(PrimMonad m, Prim a, Bytes a) =>
Ptr a -> Int -> m a
readOffPtr Ptr a
arr Int
ix = a -> a
forall a. Bytes a => a -> a
fromBigEndian (a -> a) -> m a -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr a -> Int -> m a
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
Ptr a -> Int -> m a
PM.readOffPtr Ptr a
arr Int
ix

{- | Read a primitive value from the pointer, interpreting the first
byte as the most significant one. The offset is given in elements of
type @a@ rather than in bytes.
-}
indexOffPtr :: (Prim a, Bytes a) => Ptr a -> Int -> a
indexOffPtr :: forall a. (Prim a, Bytes a) => Ptr a -> Int -> a
indexOffPtr Ptr a
arr Int
ix = a -> a
forall a. Bytes a => a -> a
fromBigEndian (Ptr a -> Int -> a
forall a. Prim a => Ptr a -> Int -> a
PM.indexOffPtr Ptr a
arr Int
ix)