repa-bytestring-1.1.0.0: Data/Array/Repa/ByteString.hs
{-# LANGUAGE ScopedTypeVariables, PackageImports #-}
-- | Conversions between Repa Arrays and ByteStrings.
module Data.Array.Repa.ByteString
( toByteString
, fromByteString)
where
import Data.Word
import Data.Array.Repa
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import System.IO.Unsafe
import qualified Data.ByteString as BS
import Data.ByteString (ByteString)
import qualified "dph-prim-par" Data.Array.Parallel.Unlifted as U
-- | Convert an `Array` to a (strict) `ByteString`.
toByteString
:: Shape sh
=> Array sh Word8
-> ByteString
toByteString arr
= unsafePerformIO
$ allocaBytes (size $ extent arr) $ \(bufDest :: Ptr Word8) ->
let uarr = toUArray arr
len = size $ extent arr
copy offset
| offset >= len
= return ()
| otherwise
= do pokeByteOff bufDest offset (uarr U.!: offset)
copy (offset + 1)
in do
copy 0
BS.packCStringLen (castPtr bufDest, len)
-- | Convert a (strict) `ByteString` to an `Array`.
-- The given array size must match the length of the `ByteString`, else `error`.
fromByteString
:: Shape sh
=> sh
-> ByteString
-> Array sh Word8
-- TODO: Use an intermediate CString when we do this, to avoid
-- the overhead from bounds checks in ByteString
fromByteString sh str
| size sh /= BS.length str
= error "Data.Array.Repa.fromByteString: given array size does not match length of string"
| otherwise
= fromFunction sh (\ix -> str `BS.index` toIndex sh ix)