    {- | This is drop-in replacement for the read, write, and index functions
    present in @Data.Primitive.ByteArray@ and @Data.Primitive.ByteArray.Unaligned@.
    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.ByteArray.BigEndian
      ( -- * Aligned
        writeByteArray
      , readByteArray
      , indexByteArray

        -- * Unaligned
      , writeUnalignedByteArray
      , readUnalignedByteArray
      , indexUnalignedByteArray
      ) where

    import Control.Monad.Primitive (PrimMonad, PrimState)
    import Data.Primitive (ByteArray, MutableByteArray, Prim)
    import qualified Data.Primitive as PM
    import Data.Primitive.ByteArray.Unaligned (PrimUnaligned)
    import qualified Data.Primitive.ByteArray.Unaligned as PMU
    import System.ByteOrder (Bytes, fromBigEndian, toBigEndian)

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

    {- | Read a primitive value from the byte array, interpreting the first
    byte as the most significant one. The offset is given in elements of
    type @a@ rather than in bytes.
    -}
    readByteArray :: (PrimMonad m, Prim a, Bytes a) => MutableByteArray (PrimState m) -> Int -> m a
    readByteArray :: forall (m :: * -> *) a.
    (PrimMonad m, Prim a, Bytes a) =>
    MutableByteArray (PrimState m) -> Int -> m a
    readByteArray MutableByteArray (PrimState m)
    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
    <$> MutableByteArray (PrimState m) -> Int -> m a
    forall a (m :: * -> *).
    (Prim a, PrimMonad m) =>
    MutableByteArray (PrimState m) -> Int -> m a
    PM.readByteArray MutableByteArray (PrimState m)
    arr Int
    ix

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

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

    {- | Read a primitive value from the byte array, interpreting the first
    byte as the most significant one. The offset is given in bytes rather
    than in elements of type @a@.
    -}
    readUnalignedByteArray ::
      (PrimMonad m, PrimUnaligned a, Bytes a) =>
      MutableByteArray (PrimState m) ->
      Int ->
      m a
    readUnalignedByteArray :: forall (m :: * -> *) a.
    (PrimMonad m, PrimUnaligned a, Bytes a) =>
    MutableByteArray (PrimState m) -> Int -> m a
    readUnalignedByteArray MutableByteArray (PrimState m)
    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
    <$> MutableByteArray (PrimState m) -> Int -> m a
    forall (m :: * -> *) a.
    (PrimMonad m, PrimUnaligned a) =>
    MutableByteArray (PrimState m) -> Int -> m a
    PMU.readUnalignedByteArray MutableByteArray (PrimState m)
    arr Int
    ix

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