{-# LANGUAGE DataKinds #-}
{-# LANGUAGE MagicHash #-}
module Data.Prim.Memory.ByteString
(
MByteString(..)
, Builder
, toBuilderBytes
, fromBuilderBytes
, ByteString(..)
, toByteStringBytes
, fromByteStringBytes
, fromLazyByteStringBytes
, withPtrByteString
, withNoHaltPtrByteString
, ShortByteString(..)
, toShortByteStringBytes
, fromShortByteStringBytes
, byteStringConvertError
) where
import Control.Monad.ST
import Data.ByteString.Builder
import Data.ByteString.Internal
import Data.ByteString.Short.Internal
import qualified Data.ByteString.Lazy as BSL
import Data.Prim
import Foreign.Prim
import Control.Prim.Monad
import GHC.ForeignPtr
import Data.Prim.Memory.Ptr
import Data.Prim.Memory.Bytes.Internal
( Bytes(..)
, Pinned(..)
, allocMBytes
, freezeMBytes
, byteCountBytes
, toForeignPtrBytes
, fromForeignPtrBytes
, byteStringConvertError
)
newtype MByteString s = MByteString ByteString
toByteStringBytes :: Bytes 'Pin -> ByteString
toByteStringBytes b = PS (toForeignPtrBytes b) 0 (coerce (byteCountBytes b))
{-# INLINE toByteStringBytes #-}
toShortByteStringBytes :: Bytes p -> ShortByteString
toShortByteStringBytes (Bytes ba#) = SBS ba#
{-# INLINE toShortByteStringBytes #-}
fromShortByteStringBytes :: ShortByteString -> Bytes 'Inc
fromShortByteStringBytes (SBS ba#) = Bytes ba#
{-# INLINE fromShortByteStringBytes #-}
toBuilderBytes :: Bytes p -> Builder
toBuilderBytes = shortByteString . toShortByteStringBytes
{-# INLINE[1] toBuilderBytes #-}
{-# RULES
"toBuilderBytes" toBuilderBytes = byteString . toByteStringBytes
#-}
fromBuilderBytes :: Builder -> Bytes 'Pin
fromBuilderBytes b = fromLazyByteStringBytes (toLazyByteString b)
{-# INLINE fromBuilderBytes #-}
fromLazyByteStringBytes :: BSL.ByteString -> Bytes 'Pin
fromLazyByteStringBytes bsl =
case BSL.toStrict bsl of
PS fptr _ _ -> either byteStringConvertError id $ fromForeignPtrBytes fptr
{-# INLINE fromLazyByteStringBytes #-}
fromByteStringBytes :: Typeable p => ByteString -> Bytes p
fromByteStringBytes bs@(PS _ _ n) =
runST $
withPtrByteString bs $ \ptr -> do
let c = Count n :: Count Word8
mb <- allocMBytes c
movePtrToMBytes ptr 0 mb 0 c
freezeMBytes mb
{-# INLINE fromByteStringBytes #-}
withPtrByteString :: MonadPrim s m => ByteString -> (Ptr a -> m b) -> m b
withPtrByteString (PS (ForeignPtr addr# ptrContents) (I# o#) _) f = do
r <- f (Ptr (addr# `plusAddr#` o#))
r <$ touch ptrContents
{-# INLINE withPtrByteString #-}
withNoHaltPtrByteString :: MonadUnliftPrim s m => ByteString -> (Ptr a -> m b) -> m b
withNoHaltPtrByteString (PS (ForeignPtr addr# ptrContents) (I# o#) _) f =
withAliveUnliftPrim ptrContents $ f (Ptr (addr# `plusAddr#` o#))
{-# INLINE withNoHaltPtrByteString #-}