Skip to content

Commit 39cc43d

Browse files
committed
Drop assumption that passed bytes are pinned
Apply a fix that in case of unpinned bytes passed in hPutBuffer we first create a pinned ByteArray and copy bytes there
1 parent b188a28 commit 39cc43d

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

mempack-scls/mempack-1.0/Data/MemPack/Extra.hs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import Data.ByteString.Lazy qualified as BSL
3838
import Data.MemPack
3939
import Data.MemPack.Buffer
4040
import Data.MemPack.Error
41+
import Data.Primitive.ByteArray
4142
import Data.Primitive.Ptr
4243
import Data.String (IsString)
4344
import Data.Text qualified as T
@@ -239,13 +240,21 @@ hPutBuffer :: (Buffer u) => Handle -> u -> IO ()
239240
hPutBuffer handle u =
240241
buffer
241242
u
242-
( \bytes -> do
243-
withForeignPtr (pinnedByteArrayToForeignPtr bytes) $ \ptr -> do
244-
hPutBuf handle ptr len
243+
( \bytes off -> do
244+
(pinnedBytes, offset) <- pinIfNeeded (ByteArray bytes) (I# off)
245+
withForeignPtr (byteArrayAsForeignPtr pinnedBytes) $ \ptr -> do
246+
hPutBuf handle (ptr `plusPtr` offset) (len - offset)
245247
)
246-
(\addr -> hPutBuf handle (Ptr addr) len) -- Write Ptr#
248+
(\addr -> hPutBuf handle (Ptr addr) len)
247249
where
248250
len = bufferByteCount u
251+
pinIfNeeded bytes off
252+
| isByteArrayPinned bytes = return (bytes, off)
253+
| otherwise = do
254+
let l = len - off
255+
dest <- newPinnedByteArray l
256+
copyByteArray dest 0 bytes off l
257+
(,0) <$> unsafeFreezeByteArray dest
249258

250259
runDecode :: (IsString e) => Fail e a -> Either e a
251260
runDecode f = runFailLast f

mempack-scls/mempack-2.0/Data/MemPack/Extra.hs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import Data.ByteString.Lazy qualified as BSL
3939
import Data.MemPack
4040
import Data.MemPack.Buffer
4141
import Data.MemPack.Error
42+
import Data.Primitive.ByteArray
4243
import Data.Primitive.Ptr
4344
import Data.Text qualified as T
4445
import Data.Typeable
@@ -245,12 +246,20 @@ hPutBuffer handle u =
245246
buffer
246247
u
247248
( \bytes off -> do
248-
withForeignPtr (pinnedByteArrayToForeignPtr bytes) $ \ptr -> do
249-
hPutBuf handle (ptr `plusPtr` (I# off)) (len - (I# off))
249+
(pinnedBytes, offset) <- pinIfNeeded (ByteArray bytes) (I# off)
250+
withForeignPtr (byteArrayAsForeignPtr pinnedBytes) $ \ptr -> do
251+
hPutBuf handle (ptr `plusPtr` offset) (len - offset)
250252
)
251-
(\addr -> hPutBuf handle (Ptr addr) len) -- Write Ptr#
253+
(\addr -> hPutBuf handle (Ptr addr) len)
252254
where
253255
len = bufferByteCount u
256+
pinIfNeeded bytes off
257+
| isByteArrayPinned bytes = return (bytes, off)
258+
| otherwise = do
259+
let l = len - off
260+
dest <- newPinnedByteArray l
261+
copyByteArray dest 0 bytes off l
262+
(,0) <$> unsafeFreezeByteArray dest
254263

255264
runDecode :: (IsString e) => (forall s. FailT e (ST s) a) -> Either e a
256265
runDecode f = runST (runFailLastT f)

0 commit comments

Comments
 (0)