How to convert between ByteString and Storable Vector?

前端 未结 2 1189
清歌不尽
清歌不尽 2021-02-13 17:50

What is the best way to convert between Storable.Vector Word8 and a strict ByteString?

Of course a non-copying (no-op) way would be most apprec

2条回答
  •  天涯浪人
    2021-02-13 18:30

    A simple unsafeCoerce will not work, as the layout of the data constructors is different:

    data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
    

    vs.

    data ByteString = PS {-# UNPACK #-} !(ForeignPtr Word8) -- payload
                         {-# UNPACK #-} !Int                -- offset
                         {-# UNPACK #-} !Int                -- length
    

    You can import Data.Array.Storable.Internals and Data.ByteString.Internal to get access to the raw constructors and then construct one out of the other without copying the data:

    > let bs = pack [1,2,3]
    > bs
    "\SOH\STX\ETX"
    > let sa = case bs of (PS ptr 0 n) -> StorableArray 0 (n-1) n ptr
    > :t sa
    sa :: StorableArray Int GHC.Word.Word8
    > Data.Array.MArray.readArray sa 1
    2
    > Data.Array.MArray.readArray sa 0
    1
    > Data.Array.MArray.readArray sa 3
    *** Exception: Ix{Int}.index: Index (3) out of range ((0,2))
    

    (I removed the rather long prompt of Prelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>).

    This will not work for Data.Vector.Unboxed, because here the data is on the Haskell heap and managed by the GHC runtime, while the other two manage the data outside the Haskell heap.

提交回复
热议问题