module Ptr.Util.ByteString where

import Data.ByteString
import qualified Data.ByteString as ByteString
import Data.ByteString.Internal
import Ptr.Prelude hiding (length)
import qualified StrictList

-- |
-- __Warning:__
--
-- It is your responsibility to ensure that the size is correct.
fromReverseStrictList :: Int -> List ByteString -> ByteString
fromReverseStrictList :: Int -> List ByteString -> ByteString
fromReverseStrictList Int
size List ByteString
chunks =
  Int -> (Ptr Word8 -> IO ()) -> ByteString
unsafeCreate Int
size (\Ptr Word8
ptr -> Ptr Word8 -> List ByteString -> IO ()
loop (Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
size) List ByteString
chunks)
  where
    loop :: Ptr Word8 -> List ByteString -> IO ()
loop Ptr Word8
endPtr =
      \case
        StrictList.Cons (PS ForeignPtr Word8
fp Int
off Int
len) List ByteString
tail ->
          do
            ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
src -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memcpy Ptr Word8
ptr (Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
src Int
off) Int
len
            Ptr Word8 -> List ByteString -> IO ()
loop Ptr Word8
ptr List ByteString
tail
          where
            ptr :: Ptr Word8
ptr = Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
endPtr (Int -> Int
forall a. Num a => a -> a
negate Int
len)
        List ByteString
StrictList.Nil ->
          () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

fromReverseStrictListWithHead :: ByteString -> Int -> List ByteString -> ByteString
fromReverseStrictListWithHead :: ByteString -> Int -> List ByteString -> ByteString
fromReverseStrictListWithHead ByteString
head Int
sizeInTail List ByteString
tail =
  if Int
sizeInTail Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
    then ByteString
head
    else Int -> List ByteString -> ByteString
fromReverseStrictList (Int
sizeInTail Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteString -> Int
length ByteString
head) (ByteString -> List ByteString -> List ByteString
forall a. a -> List a -> List a
StrictList.Cons ByteString
head List ByteString
tail)

fromPtr :: Int -> Ptr Word8 -> ByteString
fromPtr :: Int -> Ptr Word8 -> ByteString
fromPtr Int
size Ptr Word8
src =
  Int -> (Ptr Word8 -> IO ()) -> ByteString
unsafeCreate Int
size (\Ptr Word8
dst -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memcpy Ptr Word8
dst Ptr Word8
src Int
size)