{-# LANGUAGE RecordWildCards #-}

-- safe module, only export the safe bits (no @Write(..)@!!)
module Bytezap.Write
  ( Write(size, poke)
  , runWriteBS, runWriteBSUptoN
  , prim, byteString, byteArray#, replicateByte
  ) where

import Bytezap.Write.Internal

import Bytezap.Poke qualified as P
import Raehik.Compat.Data.Primitive.Types
import GHC.Exts
import Data.ByteString qualified as BS
import Data.Word ( Word8 )

runWriteBS :: Write RealWorld -> BS.ByteString
runWriteBS :: Write RealWorld -> ByteString
runWriteBS = (Int -> Poke RealWorld -> ByteString)
-> Write RealWorld -> ByteString
forall a s. (Int -> Poke s -> a) -> Write s -> a
runWriteWith Int -> Poke RealWorld -> ByteString
P.unsafeRunPokeBS

runWriteBSUptoN :: Write RealWorld -> BS.ByteString
runWriteBSUptoN :: Write RealWorld -> ByteString
runWriteBSUptoN = (Int -> Poke RealWorld -> ByteString)
-> Write RealWorld -> ByteString
forall a s. (Int -> Poke s -> a) -> Write s -> a
runWriteWith Int -> Poke RealWorld -> ByteString
P.unsafeRunPokeBSUptoN

-- | Helper for writing 'Write' runners.
runWriteWith :: forall a s. (Int -> P.Poke s -> a) -> Write s -> a
runWriteWith :: forall a s. (Int -> Poke s -> a) -> Write s -> a
runWriteWith Int -> Poke s -> a
runPoke (Write Int
size Poke s
poke) = Int -> Poke s -> a
runPoke Int
size Poke s
poke

prim :: forall a s. Prim' a => a -> Write s
prim :: forall a s. Prim' a => a -> Write s
prim a
a = Int -> Poke s -> Write s
forall s. Int -> Poke s -> Write s
Write (a -> Int
forall a. Prim a => a -> Int
sizeOf (a
forall a. HasCallStack => a
undefined :: a)) (a -> Poke s
forall a s. Prim' a => a -> Poke s
P.prim a
a)

byteString :: BS.ByteString -> Write RealWorld
byteString :: ByteString -> Write RealWorld
byteString ByteString
bs = Int -> Poke RealWorld -> Write RealWorld
forall s. Int -> Poke s -> Write s
Write (ByteString -> Int
BS.length ByteString
bs) (ByteString -> Poke RealWorld
P.byteString ByteString
bs)

byteArray# :: ByteArray# -> Int# -> Int# -> Write s
byteArray# :: forall s. ByteArray# -> Int# -> Int# -> Write s
byteArray# ByteArray#
ba# Int#
baos# Int#
balen# = Write{Int
Poke s
size :: Int
poke :: Poke s
size :: Int
poke :: Poke s
..}
  where
    size :: Int
size = Int# -> Int
I# Int#
balen#
    poke :: Poke s
poke = ByteArray# -> Int# -> Int# -> Poke s
forall s. ByteArray# -> Int# -> Int# -> Poke s
P.byteArray# ByteArray#
ba# Int#
baos# Int#
balen#

-- | essentially memset
replicateByte :: Int -> Word8 -> Write RealWorld
replicateByte :: Int -> Word8 -> Write RealWorld
replicateByte Int
len Word8
byte = Int -> Poke RealWorld -> Write RealWorld
forall s. Int -> Poke s -> Write s
Write Int
len (Int -> Word8 -> Poke RealWorld
P.replicateByte Int
len Word8
byte)