module Ptr.Util.ByteString where

import Data.ByteString
import Data.ByteString.Internal
import Foreign.Marshal.Utils
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 -> forall {a}. Ptr a -> List ByteString -> IO ()
loop (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
size) List ByteString
chunks)
  where
    loop :: Ptr a -> List ByteString -> IO ()
loop Ptr a
endPtr =
      \case
        StrictList.Cons (PS ForeignPtr Word8
fp Int
off Int
len) List ByteString
tail ->
          do
            forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp forall a b. (a -> b) -> a -> b
$ \Ptr Word8
src -> forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr a
ptr (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
src Int
off) Int
len
            Ptr a -> List ByteString -> IO ()
loop Ptr a
ptr List ByteString
tail
          where
            ptr :: Ptr a
ptr = forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr a
endPtr (forall a. Num a => a -> a
negate Int
len)
        List ByteString
StrictList.Nil ->
          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 forall a. Eq a => a -> a -> Bool
== Int
0
    then ByteString
head
    else Int -> List ByteString -> ByteString
fromReverseStrictList (Int
sizeInTail forall a. Num a => a -> a -> a
+ ByteString -> Int
length ByteString
head) (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 -> forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
dst Ptr Word8
src Int
size)