2013-09-08 17 views
11

Qual è il modo migliore per convertire tra Storable.Vector Word8 e un ByteString rigoroso?Come convertire tra ByteString e Storable Vector?

Naturalmente un modo non di copiatura (non opzionale) sarebbe più apprezzato.

Devo solo unsafeCoerce o c'è una funzione di libreria per quello (non riuscivo a trovarne uno)?

Inoltre, l'approccio sarà lo stesso per un Unboxed.Vector Word8?

+1

In alcuni casi sarebbe utile per copiare. Se i tuoi bytestrings sono brevi segmenti di un originale più lungo, ad es. ('BS.take 10 someLongByteString'), l'intero blocco lungo verrà mantenuto dal' ForeignPtr'. In questo caso la copia è spesso migliore perché utilizzerà molta meno memoria. Questa è una specie di caso specializzato, ma sembra emergere spesso. –

risposta

9

Un semplice unsafeCoerce non funzionerà, come la disposizione dei costruttori di dati è diverso:

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

vs.

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

È possibile importare Data.Array.Storable.Internals e Data.ByteString.Internal per ottenere l'accesso ai costruttori prime e quindi costruirne uno senza copiare i dati:

> 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)) 

(Ho rimosso il prompt piuttosto lungo di Prelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>).

Questo non funzionerà per Data.Vector.Unboxed, perché qui i dati sono nell'heap di Haskell e gestiti dal runtime di GHC, mentre gli altri due gestiscono i dati all'esterno dell'heap di Haskell.

Problemi correlati