module Data.Packed.Packed (Packed (..), unsafeToPacked, unsafeToPacked', fromPacked, unsafeCastPacked, duplicate) where

import Control.DeepSeq
import Data.ByteString (copy)
import Data.ByteString.Internal
import Data.Kind (Type)
import Foreign (Ptr)
import GHC.Exts (Ptr (Ptr))
import GHC.ForeignPtr (ForeignPtr (ForeignPtr), ForeignPtrContents (FinalPtr))

-- | A buffer that contains one or more packed (i.e. serialised) values.
-- The order of the values in the buffer is defined by the 'l' type list
newtype Packed (l :: [Type]) = Packed ByteString

instance NFData (Packed a) where
    rnf :: Packed a -> ()
rnf Packed a
packed = Packed a -> ByteString
forall (a :: [*]). Packed a -> ByteString
fromPacked Packed a
packed ByteString -> () -> ()
forall a b. a -> b -> b
`Prelude.seq` ()

-- | Duplicates a 'Packed' buffer. The returned 'Packed' is independent from the source one.
duplicate :: Packed a -> Packed a
duplicate :: forall (a :: [*]). Packed a -> Packed a
duplicate (Packed ByteString
bs) = ByteString -> Packed a
forall (l :: [*]). ByteString -> Packed l
Packed (ByteString -> Packed a) -> ByteString -> Packed a
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
copy ByteString
bs

{-# INLINE unsafeToPacked #-}

-- | UNSAFE: Casts a generic 'ByteString' into a 'Data.Packed.Needs'
unsafeToPacked :: ByteString -> Packed a
unsafeToPacked :: forall (l :: [*]). ByteString -> Packed l
unsafeToPacked = ByteString -> Packed a
forall (l :: [*]). ByteString -> Packed l
Packed

{-# INLINE fromPacked #-}

-- | Extracts the raw buffer from a 'Data.Packed' value
fromPacked :: Packed a -> ByteString
fromPacked :: forall (a :: [*]). Packed a -> ByteString
fromPacked (Packed ByteString
bs) = ByteString
bs

{-# INLINE unsafeCastPacked #-}

-- | UNSAFE: Casts a typed 'Packed' value into another 'Packed' value of another type
unsafeCastPacked :: Packed a -> Packed b
unsafeCastPacked :: forall (a :: [*]) (b :: [*]). Packed a -> Packed b
unsafeCastPacked = ByteString -> Packed b
forall (l :: [*]). ByteString -> Packed l
unsafeToPacked (ByteString -> Packed b)
-> (Packed a -> ByteString) -> Packed a -> Packed b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Packed a -> ByteString
forall (a :: [*]). Packed a -> ByteString
fromPacked

unsafeToPacked' :: Ptr a -> Int -> Packed b
unsafeToPacked' :: forall a (b :: [*]). Ptr a -> Int -> Packed b
unsafeToPacked' (Ptr Addr#
addr) Int
l = ByteString -> Packed b
forall (l :: [*]). ByteString -> Packed l
Packed (ForeignPtr Word8 -> Int -> ByteString
BS (Addr# -> ForeignPtrContents -> ForeignPtr Word8
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr Addr#
addr ForeignPtrContents
FinalPtr) Int
l)