module ByteString.TreeBuilder.Poker where

import ByteString.TreeBuilder.Prelude
import qualified ByteString.TreeBuilder.Tree as E
import qualified Data.ByteString.Internal as B
import Foreign hiding (void)
import qualified Foreign as D

-- |
-- Write the given bytes into the pointer and
-- return a pointer incremented by the amount of written bytes.
pokeBytes :: ByteString -> Ptr Word8 -> IO (Ptr Word8)
pokeBytes :: ByteString -> Ptr Word8 -> IO (Ptr Word8)
pokeBytes (B.PS ForeignPtr Word8
foreignPointer Int
offset Int
length) Ptr Word8
pointer =
  do
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
foreignPointer forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pointer' ->
      forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
pointer (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
pointer' Int
offset) Int
length
    forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
pointer Int
length)

-- |
-- Write the given bytes into the pointer and
-- return a pointer decremented by the amount of written bytes.
pokeBytesMinus :: ByteString -> Ptr Word8 -> IO (Ptr Word8)
pokeBytesMinus :: ByteString -> Ptr Word8 -> IO (Ptr Word8)
pokeBytesMinus (B.PS ForeignPtr Word8
foreignPointer Int
offset Int
length) Ptr Word8
pointer =
  do
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
foreignPointer forall a b. (a -> b) -> a -> b
$ \Ptr Word8
pointer' ->
      forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
targetPointer (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
pointer' Int
offset) Int
length
    forall (f :: * -> *) a. Applicative f => a -> f a
pure Ptr Word8
targetPointer
  where
    targetPointer :: Ptr Word8
targetPointer =
      forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
pointer (forall a. Num a => a -> a
negate Int
length)

pokeTree :: E.Tree -> D.Ptr Word8 -> IO (D.Ptr Word8)
pokeTree :: Tree -> Ptr Word8 -> IO (Ptr Word8)
pokeTree Tree
tree Ptr Word8
ptr =
  case Tree
tree of
    E.Leaf ByteString
bytes -> ByteString -> Ptr Word8 -> IO (Ptr Word8)
pokeBytes ByteString
bytes Ptr Word8
ptr
    E.Branch Tree
tree1 Tree
tree2 -> Tree -> Ptr Word8 -> IO (Ptr Word8)
pokeTree Tree
tree1 Ptr Word8
ptr forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Tree -> Ptr Word8 -> IO (Ptr Word8)
pokeTree Tree
tree2
    Tree
E.Empty -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Ptr Word8
ptr