{-# language BangPatterns #-}
{-# language DataKinds #-}
{-# language PolyKinds #-}
{-# language MagicHash #-}
{-# language TypeFamilies #-}
{-# language DuplicateRecordFields #-}
{-# language ScopedTypeVariables #-}

module Data.Bytes.Types
  ( Bytes(..)
  , Bytes#(..)
  , MutableBytes(..)
  , UnmanagedBytes(..)
  , BytesN(..)
  , ByteArrayN(..)
  ) where

import Data.Bytes.Internal (Bytes(..))
import Data.Primitive (ByteArray(..),MutableByteArray(..))
import Data.Primitive.Addr (Addr)
import GHC.TypeNats (Nat,KnownNat,natVal)
import Reps (Bytes#(..))
import Data.Bytes.Internal.Show (showsSlice)
import Data.Proxy (Proxy(Proxy))
import GHC.Natural (naturalToInteger)

-- | A slice of a 'ByteArray' whose compile-time-known length is represented
-- by a phantom type variable. Consumers of this data constructor must be
-- careful to preserve the expected invariant.
data BytesN (n :: Nat) = BytesN
  { forall (n :: Nat). BytesN n -> ByteArray
array :: {-# UNPACK #-} !ByteArray
  , forall (n :: Nat). BytesN n -> Int
offset :: {-# UNPACK #-} !Int
  }

instance KnownNat n => Show (BytesN n) where
  showsPrec :: Int -> BytesN n -> ShowS
showsPrec Int
_ (BytesN ByteArray
arr Int
off) String
s =
    let len :: Int
len = forall a. Num a => Integer -> a
fromInteger (Nat -> Integer
naturalToInteger (forall (n :: Nat) (proxy :: Nat -> *). KnownNat n => proxy n -> Nat
natVal (forall {k} (t :: k). Proxy t
Proxy :: Proxy n)))
     in ByteArray -> Int -> Int -> ShowS
showsSlice ByteArray
arr Int
off Int
len String
s

-- | A 'ByteArray' whose compile-time-known length is represented
-- by a phantom type variable. Consumers of this data constructor must be
-- careful to preserve the expected invariant.
newtype ByteArrayN (n :: Nat) = ByteArrayN
  { forall (n :: Nat). ByteArrayN n -> ByteArray
array :: ByteArray
  }

instance KnownNat n => Show (ByteArrayN n) where
  showsPrec :: Int -> ByteArrayN n -> ShowS
showsPrec Int
_ (ByteArrayN ByteArray
arr) String
s =
    let len :: Int
len = forall a. Num a => Integer -> a
fromInteger (Nat -> Integer
naturalToInteger (forall (n :: Nat) (proxy :: Nat -> *). KnownNat n => proxy n -> Nat
natVal (forall {k} (t :: k). Proxy t
Proxy :: Proxy n)))
     in ByteArray -> Int -> Int -> ShowS
showsSlice ByteArray
arr Int
0 Int
len String
s

-- | A slice of a 'MutableByteArray'.
data MutableBytes s = MutableBytes
  { forall s. MutableBytes s -> MutableByteArray s
array :: {-# UNPACK #-} !(MutableByteArray s)
  , forall s. MutableBytes s -> Int
offset :: {-# UNPACK #-} !Int
  , forall s. MutableBytes s -> Int
length :: {-# UNPACK #-} !Int
  }

-- | A slice of unmanaged memory.
data UnmanagedBytes = UnmanagedBytes
  { UnmanagedBytes -> Addr
address :: {-# UNPACK #-} !Addr
  , UnmanagedBytes -> Int
length :: {-# UNPACK #-} !Int
  }