Offer direct conversion between short and lazy bytestrings
- Dominant language
- Haskell
- Stars
- 301
- Forks
- 144
- Avg merge
- 7d 22h
- Merged PRs (30d)
- 1
Description
Going through strict bytestrings is totally unnecessary and wasteful. Here's one direction. I don't know if it's as efficient as possible, but it's surely more efficient than performing an unnecessary full copy of the result and allocating an unneeded `ForeignPtr`.
```haskell
import qualified Data.ByteString.Lazy as Lazy
import qualified Data.ByteString.Internal as S
import qualified Data.ByteString.Short as Short
import qualified Data.ByteString.Short.Internal as Short
import GHC.Exts
import Foreign.Ptr (plusPtr)
import Foreign.ForeignPtr (withForeignPtr)
import Control.Monad.ST.Strict
import GHC.ST
import System.IO.Unsafe
data BA = BA# ByteArray#
data MBA s = MBA# (MutableByteArray# s)
createIO :: Int -> (MBA RealWorld -> IO ()) -> Short.ShortByteString
createIO len fill = unsafeDupablePerformIO $ do
mba <- stToIO (newByteArray len)
fill mba
BA# ba# <- stToIO (unsafeFreezeByteArray mba)
return (Short.SBS ba#)
{-# INLINE createIO #-}
newByteArray :: Int -> ST s (MBA s)
newByteArray (I# len#) =
ST $ \s -> case newByteArray# len# s of
(# s', mba# #) -> (# s', MBA# mba# #)
unsafeFreezeByteArray :: MBA s -> ST s BA
unsafeFreezeByteArray (MBA# mba#) =
ST $ \s -> case unsafeFreezeByteArray# mba# s of
(# s', ba# #) -> (# s', BA# ba# #)
copyAddrToByteArray :: Ptr a -> MBA RealWorld -> Int -> Int -> ST RealWorld ()
copyAddrToByteArray (Ptr src#) (MBA# dst#) (I# dst_off#) (I# len#) =
ST $ \s -> (# copyAddrToByteArray# src# dst# dst_off# len# s, () #)
lazyToShort :: Lazy.ByteString -> Short.ShortByteString
lazyToShort = \cs ->
if Lazy.null cs
then mempty
else createIO (fromIntegral (Lazy.length cs)) $ \mba -> Lazy.foldrChunks go stop cs mba 0
where
go :: S.ByteString -> (MBA RealWorld -> Int -> IO ()) -> MBA RealWorld -> Int -> IO ()
go (S.BS _ 0) r !mba !i = r mba i
go (S.BS fp len) r !mba !i =
unsafeWithForeignPtr fp $ \p -> do
stToIO (copyAddrToByteArray p mba i len)
r mba (i + len)
stop !_ !_ = pure ()
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.