-- |
-- Module      : Data.ByteArray.Sized
-- License     : BSD-style
-- Maintainer  : Nicolas Di Prima <nicolas@primetype.co.uk>
-- Stability   : stable
-- Portability : Good
--

{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
#if __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif

module Data.ByteArray.Sized
    ( ByteArrayN(..)
    , SizedByteArray
    , unSizedByteArray
    , sizedByteArray
    , unsafeSizedByteArray

    , -- * ByteArrayN operators
      alloc
    , create
    , allocAndFreeze
    , unsafeCreate
    , inlineUnsafeCreate
    , empty
    , pack
    , unpack
    , cons
    , snoc
    , xor
    , index
    , splitAt
    , take
    , drop
    , append
    , copy
    , copyRet
    , copyAndFreeze
    , replicate
    , zero
    , convert
    , fromByteArrayAccess
    , unsafeFromByteArrayAccess
    ) where

import Basement.Imports
import Basement.NormalForm
import Basement.Nat
import Basement.Numerical.Additive ((+))
import Basement.Numerical.Subtractive ((-))

import Basement.Sized.List (ListN, unListN, toListN)

import           Foreign.Storable
import           Foreign.Ptr
import           Data.Maybe (fromMaybe)

import           Data.Memory.Internal.Compat
import           Data.Memory.PtrMethods

import Data.Proxy (Proxy(..))

import Data.ByteArray.Types (ByteArrayAccess(..), ByteArray)
import qualified Data.ByteArray.Types as ByteArray (allocRet)

import           Basement.BlockN (BlockN)
import qualified Basement.BlockN as BlockN
import qualified Basement.PrimType as Base
import           Basement.Types.OffsetSize (Countable)

-- | Type class to emulate exactly the behaviour of 'ByteArray' but with
-- a known length at compile time
--
class (ByteArrayAccess c, KnownNat n) => ByteArrayN (n :: Nat) c | c -> n where
    -- | just like 'allocRet' but with the size at the type level
    allocRet :: forall p a
              . Proxy n
             -> (Ptr p -> IO a)
             -> IO (a, c)

-- | Wrapper around any collection type with the size as type parameter
--
newtype SizedByteArray (n :: Nat) ba = SizedByteArray { SizedByteArray n ba -> ba
unSizedByteArray :: ba }
  deriving (SizedByteArray n ba -> SizedByteArray n ba -> Bool
(SizedByteArray n ba -> SizedByteArray n ba -> Bool)
-> (SizedByteArray n ba -> SizedByteArray n ba -> Bool)
-> Eq (SizedByteArray n ba)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (n :: Nat) ba.
Eq ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
/= :: SizedByteArray n ba -> SizedByteArray n ba -> Bool
$c/= :: forall (n :: Nat) ba.
Eq ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
== :: SizedByteArray n ba -> SizedByteArray n ba -> Bool
$c== :: forall (n :: Nat) ba.
Eq ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
Eq, Int -> SizedByteArray n ba -> ShowS
[SizedByteArray n ba] -> ShowS
SizedByteArray n ba -> String
(Int -> SizedByteArray n ba -> ShowS)
-> (SizedByteArray n ba -> String)
-> ([SizedByteArray n ba] -> ShowS)
-> Show (SizedByteArray n ba)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (n :: Nat) ba.
Show ba =>
Int -> SizedByteArray n ba -> ShowS
forall (n :: Nat) ba. Show ba => [SizedByteArray n ba] -> ShowS
forall (n :: Nat) ba. Show ba => SizedByteArray n ba -> String
showList :: [SizedByteArray n ba] -> ShowS
$cshowList :: forall (n :: Nat) ba. Show ba => [SizedByteArray n ba] -> ShowS
show :: SizedByteArray n ba -> String
$cshow :: forall (n :: Nat) ba. Show ba => SizedByteArray n ba -> String
showsPrec :: Int -> SizedByteArray n ba -> ShowS
$cshowsPrec :: forall (n :: Nat) ba.
Show ba =>
Int -> SizedByteArray n ba -> ShowS
Show, Typeable, Eq (SizedByteArray n ba)
Eq (SizedByteArray n ba)
-> (SizedByteArray n ba -> SizedByteArray n ba -> Ordering)
-> (SizedByteArray n ba -> SizedByteArray n ba -> Bool)
-> (SizedByteArray n ba -> SizedByteArray n ba -> Bool)
-> (SizedByteArray n ba -> SizedByteArray n ba -> Bool)
-> (SizedByteArray n ba -> SizedByteArray n ba -> Bool)
-> (SizedByteArray n ba
    -> SizedByteArray n ba -> SizedByteArray n ba)
-> (SizedByteArray n ba
    -> SizedByteArray n ba -> SizedByteArray n ba)
-> Ord (SizedByteArray n ba)
SizedByteArray n ba -> SizedByteArray n ba -> Bool
SizedByteArray n ba -> SizedByteArray n ba -> Ordering
SizedByteArray n ba -> SizedByteArray n ba -> SizedByteArray n ba
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 (n :: Nat) ba. Ord ba => Eq (SizedByteArray n ba)
forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Ordering
forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> SizedByteArray n ba
min :: SizedByteArray n ba -> SizedByteArray n ba -> SizedByteArray n ba
$cmin :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> SizedByteArray n ba
max :: SizedByteArray n ba -> SizedByteArray n ba -> SizedByteArray n ba
$cmax :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> SizedByteArray n ba
>= :: SizedByteArray n ba -> SizedByteArray n ba -> Bool
$c>= :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
> :: SizedByteArray n ba -> SizedByteArray n ba -> Bool
$c> :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
<= :: SizedByteArray n ba -> SizedByteArray n ba -> Bool
$c<= :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
< :: SizedByteArray n ba -> SizedByteArray n ba -> Bool
$c< :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Bool
compare :: SizedByteArray n ba -> SizedByteArray n ba -> Ordering
$ccompare :: forall (n :: Nat) ba.
Ord ba =>
SizedByteArray n ba -> SizedByteArray n ba -> Ordering
$cp1Ord :: forall (n :: Nat) ba. Ord ba => Eq (SizedByteArray n ba)
Ord, SizedByteArray n ba -> ()
(SizedByteArray n ba -> ()) -> NormalForm (SizedByteArray n ba)
forall a. (a -> ()) -> NormalForm a
forall (n :: Nat) ba. NormalForm ba => SizedByteArray n ba -> ()
toNormalForm :: SizedByteArray n ba -> ()
$ctoNormalForm :: forall (n :: Nat) ba. NormalForm ba => SizedByteArray n ba -> ()
NormalForm)

-- | create a 'SizedByteArray' from the given 'ByteArrayAccess' if the
-- size is the same as the target size.
--
sizedByteArray :: forall n ba . (KnownNat n, ByteArrayAccess ba)
               => ba
               -> Maybe (SizedByteArray n ba)
sizedByteArray :: ba -> Maybe (SizedByteArray n ba)
sizedByteArray ba
ba
    | ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length ba
ba Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n = SizedByteArray n ba -> Maybe (SizedByteArray n ba)
forall a. a -> Maybe a
Just (SizedByteArray n ba -> Maybe (SizedByteArray n ba))
-> SizedByteArray n ba -> Maybe (SizedByteArray n ba)
forall a b. (a -> b) -> a -> b
$ ba -> SizedByteArray n ba
forall (n :: Nat) ba. ba -> SizedByteArray n ba
SizedByteArray ba
ba
    | Bool
otherwise      = Maybe (SizedByteArray n ba)
forall a. Maybe a
Nothing
  where
    n :: Int
n = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n
forall k (t :: k). Proxy t
Proxy @n)

-- | just like the 'sizedByteArray' function but throw an exception if
-- the size is invalid.
unsafeSizedByteArray :: forall n ba . (ByteArrayAccess ba, KnownNat n) => ba -> SizedByteArray n ba
unsafeSizedByteArray :: ba -> SizedByteArray n ba
unsafeSizedByteArray = SizedByteArray n ba
-> Maybe (SizedByteArray n ba) -> SizedByteArray n ba
forall a. a -> Maybe a -> a
fromMaybe (String -> SizedByteArray n ba
forall a. HasCallStack => String -> a
error String
"The size is invalid") (Maybe (SizedByteArray n ba) -> SizedByteArray n ba)
-> (ba -> Maybe (SizedByteArray n ba)) -> ba -> SizedByteArray n ba
forall k (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ba -> Maybe (SizedByteArray n ba)
forall (n :: Nat) ba.
(KnownNat n, ByteArrayAccess ba) =>
ba -> Maybe (SizedByteArray n ba)
sizedByteArray

instance (ByteArrayAccess ba, KnownNat n) => ByteArrayAccess (SizedByteArray n ba) where
    length :: SizedByteArray n ba -> Int
length SizedByteArray n ba
_ = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n
forall k (t :: k). Proxy t
Proxy @n)
    withByteArray :: SizedByteArray n ba -> (Ptr p -> IO a) -> IO a
withByteArray (SizedByteArray ba
ba) = ba -> (Ptr p -> IO a) -> IO a
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
ba

instance (KnownNat n, ByteArray ba) => ByteArrayN n (SizedByteArray n ba) where
    allocRet :: Proxy n -> (Ptr p -> IO a) -> IO (a, SizedByteArray n ba)
allocRet Proxy n
p Ptr p -> IO a
f = do
        (a
a, ba
ba) <- Int -> (Ptr p -> IO a) -> IO (a, ba)
forall ba p a. ByteArray ba => Int -> (Ptr p -> IO a) -> IO (a, ba)
ByteArray.allocRet Int
n Ptr p -> IO a
f
        (a, SizedByteArray n ba) -> IO (a, SizedByteArray n ba)
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (a
a, ba -> SizedByteArray n ba
forall (n :: Nat) ba. ba -> SizedByteArray n ba
SizedByteArray ba
ba)
      where
        n :: Int
n = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal Proxy n
p

instance ( ByteArrayAccess (BlockN n ty)
         , PrimType ty
         , KnownNat n
         , Countable ty n
         , KnownNat nbytes
         , nbytes ~ (Base.PrimSize ty * n)
         ) => ByteArrayN nbytes (BlockN n ty) where
    allocRet :: Proxy nbytes -> (Ptr p -> IO a) -> IO (a, BlockN n ty)
allocRet Proxy nbytes
_ Ptr p -> IO a
f = do
        MutableBlockN n ty RealWorld
mba <- forall ty (prim :: Type -> Type).
(PrimType ty, KnownNat n, Countable ty n, PrimMonad prim) =>
prim (MutableBlockN n ty (PrimState prim))
forall (n :: Nat) ty (prim :: Type -> Type).
(PrimType ty, KnownNat n, Countable ty n, PrimMonad prim) =>
prim (MutableBlockN n ty (PrimState prim))
BlockN.new @n
        a
a   <- Bool
-> Bool
-> MutableBlockN n ty (PrimState IO)
-> (Ptr ty -> IO a)
-> IO a
forall (n :: Nat) ty (prim :: Type -> Type) a.
(PrimMonad prim, KnownNat n) =>
Bool
-> Bool
-> MutableBlockN n ty (PrimState prim)
-> (Ptr ty -> prim a)
-> prim a
BlockN.withMutablePtrHint Bool
True Bool
False MutableBlockN n ty RealWorld
MutableBlockN n ty (PrimState IO)
mba (Ptr p -> IO a
f (Ptr p -> IO a) -> (Ptr ty -> Ptr p) -> Ptr ty -> IO a
forall k (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Ptr ty -> Ptr p
forall a b. Ptr a -> Ptr b
castPtr)
        BlockN n ty
ba  <- MutableBlockN n ty (PrimState IO) -> IO (BlockN n ty)
forall (prim :: Type -> Type) ty (n :: Nat).
(PrimMonad prim, PrimType ty, Countable ty n) =>
MutableBlockN n ty (PrimState prim) -> prim (BlockN n ty)
BlockN.freeze MutableBlockN n ty RealWorld
MutableBlockN n ty (PrimState IO)
mba
        (a, BlockN n ty) -> IO (a, BlockN n ty)
forall (m :: Type -> Type) a. Monad m => a -> m a
return (a
a, BlockN n ty
ba)


-- | Allocate a new bytearray of specific size, and run the initializer on this memory
alloc :: forall n ba p . (ByteArrayN n ba, KnownNat n)
      => (Ptr p -> IO ())
      -> IO ba
alloc :: (Ptr p -> IO ()) -> IO ba
alloc Ptr p -> IO ()
f = ((), ba) -> ba
forall a b. (a, b) -> b
snd (((), ba) -> ba) -> IO ((), ba) -> IO ba
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy n -> (Ptr p -> IO ()) -> IO ((), ba)
forall (n :: Nat) c p a.
ByteArrayN n c =>
Proxy n -> (Ptr p -> IO a) -> IO (a, c)
allocRet (Proxy n
forall k (t :: k). Proxy t
Proxy @n) Ptr p -> IO ()
f

-- | Allocate a new bytearray of specific size, and run the initializer on this memory
create :: forall n ba p . (ByteArrayN n ba, KnownNat n)
       => (Ptr p -> IO ())
       -> IO ba
create :: (Ptr p -> IO ()) -> IO ba
create = forall ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @n
{-# NOINLINE create #-}

-- | similar to 'allocN' but hide the allocation and initializer in a pure context
allocAndFreeze :: forall n ba p . (ByteArrayN n ba, KnownNat n)
               => (Ptr p -> IO ()) -> ba
allocAndFreeze :: (Ptr p -> IO ()) -> ba
allocAndFreeze Ptr p -> IO ()
f = IO ba -> ba
forall a. IO a -> a
unsafeDoIO ((Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @n Ptr p -> IO ()
f)
{-# NOINLINE allocAndFreeze #-}

-- | similar to 'createN' but hide the allocation and initializer in a pure context
unsafeCreate :: forall n ba p . (ByteArrayN n ba, KnownNat n)
             => (Ptr p -> IO ()) -> ba
unsafeCreate :: (Ptr p -> IO ()) -> ba
unsafeCreate Ptr p -> IO ()
f = IO ba -> ba
forall a. IO a -> a
unsafeDoIO ((Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @n Ptr p -> IO ()
f)
{-# NOINLINE unsafeCreate #-}

inlineUnsafeCreate :: forall n ba p . (ByteArrayN n ba, KnownNat n)
                   => (Ptr p -> IO ()) -> ba
inlineUnsafeCreate :: (Ptr p -> IO ()) -> ba
inlineUnsafeCreate Ptr p -> IO ()
f = IO ba -> ba
forall a. IO a -> a
unsafeDoIO ((Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @n Ptr p -> IO ()
f)
{-# INLINE inlineUnsafeCreate #-}

-- | Create an empty byte array
empty :: forall ba . ByteArrayN 0 ba => ba
empty :: ba
empty = IO ba -> ba
forall a. IO a -> a
unsafeDoIO (forall ba p.
(ByteArrayN 0 ba, KnownNat 0) =>
(Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @0 ((Ptr Any -> IO ()) -> IO ba) -> (Ptr Any -> IO ()) -> IO ba
forall a b. (a -> b) -> a -> b
$ \Ptr Any
_ -> () -> IO ()
forall (m :: Type -> Type) a. Monad m => a -> m a
return ())

-- | Pack a list of bytes into a bytearray
pack :: forall n ba . (ByteArrayN n ba, KnownNat n) => ListN n Word8 -> ba
pack :: ListN n Word8 -> ba
pack ListN n Word8
l = (Ptr Word8 -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
inlineUnsafeCreate @n ([Word8] -> Ptr Word8 -> IO ()
forall b. Storable b => [b] -> Ptr b -> IO ()
fill ([Word8] -> Ptr Word8 -> IO ()) -> [Word8] -> Ptr Word8 -> IO ()
forall a b. (a -> b) -> a -> b
$ ListN n Word8 -> [Word8]
forall (n :: Nat) a. ListN n a -> [a]
unListN ListN n Word8
l)
  where fill :: [b] -> Ptr b -> IO ()
fill []     Ptr b
_  = () -> IO ()
forall (m :: Type -> Type) a. Monad m => a -> m a
return ()
        fill (b
x:[b]
xs) !Ptr b
p = Ptr b -> b -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr b
p b
x IO () -> IO () -> IO ()
forall (m :: Type -> Type) a b. Monad m => m a -> m b -> m b
>> [b] -> Ptr b -> IO ()
fill [b]
xs (Ptr b
p Ptr b -> Int -> Ptr b
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1)
        {-# INLINE fill #-}
{-# NOINLINE pack #-}

-- | Un-pack a bytearray into a list of bytes
unpack :: forall n ba
        . (ByteArrayN n ba, KnownNat n, NatWithinBound Int n, ByteArrayAccess ba)
       => ba -> ListN n Word8
unpack :: ba -> ListN n Word8
unpack ba
bs =  ListN n Word8 -> Maybe (ListN n Word8) -> ListN n Word8
forall a. a -> Maybe a -> a
fromMaybe (String -> ListN n Word8
forall a. HasCallStack => String -> a
error String
"the impossible appened") (Maybe (ListN n Word8) -> ListN n Word8)
-> Maybe (ListN n Word8) -> ListN n Word8
forall a b. (a -> b) -> a -> b
$ forall a.
(KnownNat n, NatWithinBound Int n) =>
[a] -> Maybe (ListN n a)
forall (n :: Nat) a.
(KnownNat n, NatWithinBound Int n) =>
[a] -> Maybe (ListN n a)
toListN @n ([Word8] -> Maybe (ListN n Word8))
-> [Word8] -> Maybe (ListN n Word8)
forall a b. (a -> b) -> a -> b
$ Int -> [Word8]
loop Int
0
  where !len :: Int
len = ba -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length ba
bs
        loop :: Int -> [Word8]
loop Int
i
            | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
len  = []
            | Bool
otherwise =
                let !v :: Word8
v = IO Word8 -> Word8
forall a. IO a -> a
unsafeDoIO (IO Word8 -> Word8) -> IO Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ ba -> (Ptr Any -> IO Word8) -> IO Word8
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
bs (Ptr Any -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
`peekByteOff` Int
i)
                 in Word8
v Word8 -> [Word8] -> [Word8]
forall a. a -> [a] -> [a]
: Int -> [Word8]
loop (Int
iInt -> Int -> Int
forall a. Additive a => a -> a -> a
+Int
1)

-- | prepend a single byte to a byte array
cons :: forall ni no bi bo
      . ( ByteArrayN ni bi, ByteArrayN no bo, ByteArrayAccess bi
        , KnownNat ni, KnownNat no
        , (ni + 1) ~ no
        )
     => Word8 -> bi -> bo
cons :: Word8 -> bi -> bo
cons Word8
b bi
ba = forall ba p.
(ByteArrayN no ba, KnownNat no) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @no ((Ptr Any -> IO ()) -> bo) -> (Ptr Any -> IO ()) -> bo
forall a b. (a -> b) -> a -> b
$ \Ptr Any
d -> bi -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bi
ba ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> do
    Ptr Any -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Any
d Int
0 Word8
b
    Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy (Ptr Any
d Ptr Any -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
1) Ptr Word8
s Int
len
  where
    !len :: Int
len = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy ni -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy ni
forall k (t :: k). Proxy t
Proxy @ni)

-- | append a single byte to a byte array
snoc :: forall bi bo ni no
      . ( ByteArrayN ni bi, ByteArrayN no bo, ByteArrayAccess bi
        , KnownNat ni, KnownNat no
        , (ni + 1) ~ no
        )
     => bi -> Word8 -> bo
snoc :: bi -> Word8 -> bo
snoc bi
ba Word8
b = forall ba p.
(ByteArrayN no ba, KnownNat no) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @no ((Ptr Word8 -> IO ()) -> bo) -> (Ptr Word8 -> IO ()) -> bo
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> bi -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bi
ba ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> do
    Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d Ptr Word8
s Int
len
    Ptr Word8 -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Word8
d Int
len Word8
b
  where
    !len :: Int
len = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy ni -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy ni
forall k (t :: k). Proxy t
Proxy @ni)

-- | Create a xor of bytes between a and b.
--
-- the returns byte array is the size of the smallest input.
xor :: forall n a b c
     . ( ByteArrayN n a, ByteArrayN n b, ByteArrayN n c
       , ByteArrayAccess a, ByteArrayAccess b
       , KnownNat n
       )
    => a -> b -> c
xor :: a -> b -> c
xor a
a b
b =
    forall ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @n ((Ptr Word8 -> IO ()) -> c) -> (Ptr Word8 -> IO ()) -> c
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pc ->
    a -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray a
a  ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pa ->
    b -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray b
b  ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pb ->
        Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memXor Ptr Word8
pc Ptr Word8
pa Ptr Word8
pb Int
n
  where
    n :: Int
n  = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n
forall k (t :: k). Proxy t
Proxy @n))

-- | return a specific byte indexed by a number from 0 in a bytearray
--
-- unsafe, no bound checking are done
index :: forall n na ba
       . ( ByteArrayN na ba, ByteArrayAccess ba
         , KnownNat na, KnownNat n
         , n <= na
         )
      => ba -> Proxy n -> Word8
index :: ba -> Proxy n -> Word8
index ba
b Proxy n
pi = IO Word8 -> Word8
forall a. IO a -> a
unsafeDoIO (IO Word8 -> Word8) -> IO Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ ba -> (Ptr Any -> IO Word8) -> IO Word8
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray ba
b ((Ptr Any -> IO Word8) -> IO Word8)
-> (Ptr Any -> IO Word8) -> IO Word8
forall a b. (a -> b) -> a -> b
$ \Ptr Any
p -> Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek (Ptr Any
p Ptr Any -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
i)
  where
    i :: Int
i = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal Proxy n
pi

-- | Split a bytearray at a specific length in two bytearray
splitAt :: forall nblhs nbi nbrhs bi blhs brhs
         . ( ByteArrayN nbi bi, ByteArrayN nblhs blhs, ByteArrayN nbrhs brhs
           , ByteArrayAccess bi
           , KnownNat nbi, KnownNat nblhs, KnownNat nbrhs
           , nblhs <= nbi, (nbrhs + nblhs) ~ nbi
           )
        => bi -> (blhs, brhs)
splitAt :: bi -> (blhs, brhs)
splitAt bi
bs = IO (blhs, brhs) -> (blhs, brhs)
forall a. IO a -> a
unsafeDoIO (IO (blhs, brhs) -> (blhs, brhs))
-> IO (blhs, brhs) -> (blhs, brhs)
forall a b. (a -> b) -> a -> b
$
    bi -> (Ptr Word8 -> IO (blhs, brhs)) -> IO (blhs, brhs)
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bi
bs ((Ptr Word8 -> IO (blhs, brhs)) -> IO (blhs, brhs))
-> (Ptr Word8 -> IO (blhs, brhs)) -> IO (blhs, brhs)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p -> do
        blhs
b1 <- forall ba p.
(ByteArrayN nblhs ba, KnownNat nblhs) =>
(Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @nblhs ((Ptr Word8 -> IO ()) -> IO blhs)
-> (Ptr Word8 -> IO ()) -> IO blhs
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
r -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
r Ptr Word8
p Int
n
        brhs
b2 <- forall ba p.
(ByteArrayN nbrhs ba, KnownNat nbrhs) =>
(Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @nbrhs ((Ptr Word8 -> IO ()) -> IO brhs)
-> (Ptr Word8 -> IO ()) -> IO brhs
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
r -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
r (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
n) (Int
len Int -> Int -> Difference Int
forall a. Subtractive a => a -> a -> Difference a
- Int
n)
        (blhs, brhs) -> IO (blhs, brhs)
forall (m :: Type -> Type) a. Monad m => a -> m a
return (blhs
b1, brhs
b2)
  where
    n :: Int
n = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy nblhs -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy nblhs
forall k (t :: k). Proxy t
Proxy @nblhs)
    len :: Int
len = bi -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length bi
bs

-- | Take the first @n@ byte of a bytearray
take :: forall nbo nbi bi bo
      . ( ByteArrayN nbi bi, ByteArrayN nbo bo
        , ByteArrayAccess bi
        , KnownNat nbi, KnownNat nbo
        , nbo <= nbi
        )
     => bi -> bo
take :: bi -> bo
take bi
bs = forall ba p.
(ByteArrayN nbo ba, KnownNat nbo) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @nbo ((Ptr Word8 -> IO ()) -> bo) -> (Ptr Word8 -> IO ()) -> bo
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> bi -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bi
bs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d Ptr Word8
s Int
m
  where
    !m :: Int
m   = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
len Int
n
    !len :: Int
len = bi -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length bi
bs
    !n :: Int
n   = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy nbo -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy nbo
forall k (t :: k). Proxy t
Proxy @nbo)

-- | drop the first @n@ byte of a bytearray
drop :: forall n nbi nbo bi bo
      . ( ByteArrayN nbi bi, ByteArrayN nbo bo
        , ByteArrayAccess bi
        , KnownNat n, KnownNat nbi, KnownNat nbo
        , (nbo + n) ~ nbi
        )
     => Proxy n -> bi -> bo
drop :: Proxy n -> bi -> bo
drop Proxy n
pn bi
bs = forall ba p.
(ByteArrayN nbo ba, KnownNat nbo) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @nbo ((Ptr Word8 -> IO ()) -> bo) -> (Ptr Word8 -> IO ()) -> bo
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d ->
    bi -> (Ptr Any -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bi
bs ((Ptr Any -> IO ()) -> IO ()) -> (Ptr Any -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Any
s ->
    Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d (Ptr Any
s Ptr Any -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
ofs) Int
Difference Int
nb
  where
    ofs :: Int
ofs = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
len Int
n
    nb :: Difference Int
nb  = Int
len Int -> Int -> Difference Int
forall a. Subtractive a => a -> a -> Difference a
- Int
ofs
    len :: Int
len = bi -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length bi
bs
    n :: Int
n   = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal Proxy n
pn

-- | append one bytearray to the other
append :: forall nblhs nbrhs nbout blhs brhs bout
        . ( ByteArrayN nblhs blhs, ByteArrayN nbrhs brhs, ByteArrayN nbout bout
          , ByteArrayAccess blhs, ByteArrayAccess brhs
          , KnownNat nblhs, KnownNat nbrhs, KnownNat nbout
          , (nbrhs + nblhs) ~ nbout
          )
       => blhs -> brhs -> bout
append :: blhs -> brhs -> bout
append blhs
blhs brhs
brhs = forall ba p.
(ByteArrayN nbout ba, KnownNat nbout) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @nbout ((Ptr Word8 -> IO ()) -> bout) -> (Ptr Word8 -> IO ()) -> bout
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p ->
    blhs -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray blhs
blhs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
plhs ->
    brhs -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray brhs
brhs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
prhs -> do
        Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
p Ptr Word8
plhs (blhs -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length blhs
blhs)
        Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy (Ptr Word8
p Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` blhs -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length blhs
blhs) Ptr Word8
prhs (brhs -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length brhs
brhs)

-- | Duplicate a bytearray into another bytearray, and run an initializer on it
copy :: forall n bs1 bs2 p
      . ( ByteArrayN n bs1, ByteArrayN n bs2
        , ByteArrayAccess bs1
        , KnownNat n
        )
     => bs1 -> (Ptr p -> IO ()) -> IO bs2
copy :: bs1 -> (Ptr p -> IO ()) -> IO bs2
copy bs1
bs Ptr p -> IO ()
f = forall ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> IO ba
alloc @n ((Ptr Word8 -> IO ()) -> IO bs2) -> (Ptr Word8 -> IO ()) -> IO bs2
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> do
    bs1 -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs1
bs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d Ptr Word8
s (bs1 -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length bs1
bs)
    Ptr p -> IO ()
f (Ptr Word8 -> Ptr p
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
d)

-- | Similar to 'copy' but also provide a way to return a value from the initializer
copyRet :: forall n bs1 bs2 p a
         . ( ByteArrayN n bs1, ByteArrayN n bs2
           , ByteArrayAccess bs1
           , KnownNat n
           )
        => bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
copyRet :: bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
copyRet bs1
bs Ptr p -> IO a
f =
    Proxy n -> (Ptr Word8 -> IO a) -> IO (a, bs2)
forall (n :: Nat) c p a.
ByteArrayN n c =>
Proxy n -> (Ptr p -> IO a) -> IO (a, c)
allocRet (Proxy n
forall k (t :: k). Proxy t
Proxy @n) ((Ptr Word8 -> IO a) -> IO (a, bs2))
-> (Ptr Word8 -> IO a) -> IO (a, bs2)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
d -> do
        bs1 -> (Ptr Word8 -> IO ()) -> IO ()
forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
withByteArray bs1
bs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memCopy Ptr Word8
d Ptr Word8
s (bs1 -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length bs1
bs)
        Ptr p -> IO a
f (Ptr Word8 -> Ptr p
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
d)

-- | Similiar to 'copy' but expect the resulting bytearray in a pure context
copyAndFreeze :: forall n bs1 bs2 p
               . ( ByteArrayN n bs1, ByteArrayN n bs2
                 , ByteArrayAccess bs1
                 , KnownNat n
                 )
              => bs1 -> (Ptr p -> IO ()) -> bs2
copyAndFreeze :: bs1 -> (Ptr p -> IO ()) -> bs2
copyAndFreeze bs1
bs Ptr p -> IO ()
f =
    forall ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
inlineUnsafeCreate @n ((Ptr Any -> IO ()) -> bs2) -> (Ptr Any -> IO ()) -> bs2
forall a b. (a -> b) -> a -> b
$ \Ptr Any
d -> do
        bs1 -> Ptr Any -> IO ()
forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bs1
bs Ptr Any
d
        Ptr p -> IO ()
f (Ptr Any -> Ptr p
forall a b. Ptr a -> Ptr b
castPtr Ptr Any
d)
{-# NOINLINE copyAndFreeze #-}

-- | Create a bytearray of a specific size containing a repeated byte value
replicate :: forall n ba . (ByteArrayN n ba, KnownNat n)
          => Word8 -> ba
replicate :: Word8 -> ba
replicate Word8
b = forall ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
inlineUnsafeCreate @n ((Ptr Word8 -> IO ()) -> ba) -> (Ptr Word8 -> IO ()) -> ba
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> Ptr Word8 -> Word8 -> Int -> IO ()
memSet Ptr Word8
ptr Word8
b (Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer) -> Proxy n -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy n
forall k (t :: k). Proxy t
Proxy @n)
{-# NOINLINE replicate #-}

-- | Create a bytearray of a specific size initialized to 0
zero :: forall n ba . (ByteArrayN n ba, KnownNat n) => ba
zero :: ba
zero = forall ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
unsafeCreate @n ((Ptr Word8 -> IO ()) -> ba) -> (Ptr Word8 -> IO ()) -> ba
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> Ptr Word8 -> Word8 -> Int -> IO ()
memSet Ptr Word8
ptr Word8
0 (Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer) -> Proxy n -> Integer
forall a b. (a -> b) -> a -> b
$ Proxy n
forall k (t :: k). Proxy t
Proxy @n)
{-# NOINLINE zero #-}

-- | Convert a bytearray to another type of bytearray
convert :: forall n bin bout
         . ( ByteArrayN n bin, ByteArrayN n bout
           , KnownNat n
           )
        => bin -> bout
convert :: bin -> bout
convert bin
bs = (Ptr Any -> IO ()) -> bout
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
inlineUnsafeCreate @n (bin -> Ptr Any -> IO ()
forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bin
bs)

-- | Convert a ByteArrayAccess to another type of bytearray
--
-- This function returns nothing if the size is not compatible
fromByteArrayAccess :: forall n bin bout
                     . ( ByteArrayAccess bin, ByteArrayN n bout
                       , KnownNat n
                       )
                    => bin -> Maybe bout
fromByteArrayAccess :: bin -> Maybe bout
fromByteArrayAccess bin
bs
    | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n    = bout -> Maybe bout
forall a. a -> Maybe a
Just (bout -> Maybe bout) -> bout -> Maybe bout
forall a b. (a -> b) -> a -> b
$ (Ptr Any -> IO ()) -> bout
forall (n :: Nat) ba p.
(ByteArrayN n ba, KnownNat n) =>
(Ptr p -> IO ()) -> ba
inlineUnsafeCreate @n (bin -> Ptr Any -> IO ()
forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
copyByteArrayToPtr bin
bs)
    | Bool
otherwise = Maybe bout
forall a. Maybe a
Nothing
  where
    l :: Int
l = bin -> Int
forall ba. ByteArrayAccess ba => ba -> Int
length bin
bs
    n :: Int
n = Integer -> Int
forall a. Integral a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n
forall k (t :: k). Proxy t
Proxy @n)

-- | Convert a ByteArrayAccess to another type of bytearray
unsafeFromByteArrayAccess :: forall n bin bout
                           . ( ByteArrayAccess bin, ByteArrayN n bout
                             , KnownNat n
                           )
                          => bin -> bout
unsafeFromByteArrayAccess :: bin -> bout
unsafeFromByteArrayAccess bin
bs = case bin -> Maybe bout
forall (n :: Nat) bin bout.
(ByteArrayAccess bin, ByteArrayN n bout, KnownNat n) =>
bin -> Maybe bout
fromByteArrayAccess @n @bin @bout bin
bs of
    Maybe bout
Nothing -> String -> bout
forall a. HasCallStack => String -> a
error String
"Invalid Size"
    Just bout
v  -> bout
v