2013-09-08 11 views
11

Jaki jest najlepszy sposób przekonwertowania między Storable.Vector Word8 a restrykcyjnym ByteString?Jak przekonwertować między ByteString a zapasowym wektorem?

Oczywiście, najbardziej pożądany byłby sposób niekopiowania (no-op).

Czy powinienem po prostu unsafeCoerce lub czy istnieje funkcja biblioteki do tego (nie mogłem znaleźć)?

Co więcej, podejście będzie takie samo dla modelu Unboxed.Vector Word8?

+1

W niektórych przypadkach korzystne byłoby skopiować. Jeśli Twoje bytestrings są krótkimi segmentami dłuższego oryginalnego testu bytowego, np. ('BS.take 10 someLongByteString'), cała długa porcja zostanie zachowana przez' ForeignPtr'. W tym przypadku kopiowanie jest często lepsze, ponieważ zużywa znacznie mniej pamięci. Jest to rodzaj specjalistycznego przypadku, ale zdaje się często pojawiać. –

Odpowiedz

9

Prosty unsafeCoerce nie będzie działać, jak układ konstruktorów danych jest inna:

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

vs.

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

Można importować Data.Array.Storable.Internals i Data.ByteString.Internal aby uzyskać dostęp do surowych konstruktorów a następnie skonstruuj jedno z pozostałych bez kopiowania danych:

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

(Usunąłem raczej długi znak zachęty Prelude Data.Array.Storable.Internals Data.ByteString.Internal Data.ByteString>).

To nie zadziała dla Data.Vector.Unboxed, ponieważ tutaj dane są na stercie Haskella i zarządzane przez środowisko wykonawcze GHC, podczas gdy pozostałe dwa zarządzają danymi poza stertą Haskella.

Powiązane problemy