Apply Word32 Function to ByteString

I have a ByteString b with a form length of 4 * n (with an integer n) and you want to use map with the function f::Word32->Word32 on b (so that f applies to " b[0..3] ", " b[4..7] ", etc.). How can this be done in an efficient (and elegant) way?

+6
source share
2 answers

You can use ByteString effectively, given that B.take and B.drop are O(1) operations:

 import Data.ByteString (ByteString) import qualified Data.ByteString as B chunk :: Int -> ByteString -> [ByteString] chunk k = takeWhile (not . B.null) . map (B.take k) . iterate (B.drop k) 

then

 \> :set -XOverloadedStrings \> chunk 4 "abcdefghijkl" ["abcd","efgh","ijkl"] 

the rest will be to display a list converted to the desired type from the desired, and one call to B.concat at the end.

A possible fromByteString can be implemented using bit shifts and left folds:

 import Data.Bits (Bits, shiftL, (.|.)) fromByteString :: (Num a, Bits a) => ByteString -> a fromByteString = B.foldl go 0 where go acc i = (acc `shiftL` 8) .|. (fromIntegral i) 

then

 \> map fromByteString $ chunk 4 "abcdefghijkl" :: [Word32] [1633837924,1701209960,1768581996] 
+4
source

A hacky but effective way is to convert to a persistent vector (which does not require a copy!), Match this and convert back:

 import Data.Vector.Storable.ByteString import qualified Data.Vector.Storable as VS import qualified Data.ByteString as BS mapBSChunks :: (VS.Storable a, VS.Storable b) => (a->b) -> BS.ByteString -> BS.ByteString mapBSChunks f = vectorToByteString . VS.map f . byteStringToVector 

According to Michael's comment , you can easily define these hacker conversion features locally:

 bytestringToVector bs = runST ( V.unsafeThaw (toByteVector bs) >>= V.unsafeFreeze . M.unsafeCast ) vectorToByteString v = runST ( V.unsafeThaw v >>= fmap fromByteVector . V.unsafeFreeze . M.unsafeCast ) 

although I would prefer to rely on the library to provide this, in particular, because insecure casting is a little suspicious.

+4
source

All Articles