module Network.HPACK.Huffman.ByteString (
unpack4bits
, copy
) where
import Control.Monad (void)
import Data.Bits ((.&.), shiftR)
import Data.ByteString.Internal (ByteString(..))
import Data.Word (Word8)
import Foreign.C.Types (CSize(..))
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.Storable (peek)
import System.IO.Unsafe (unsafeDupablePerformIO)
unpack4bits :: ByteString -> [Word8]
unpack4bits (PS fptr off len) = unsafeDupablePerformIO $
withForeignPtr fptr $ \ptr -> do
let lim = ptr `plusPtr` (off 1)
end = ptr `plusPtr` (off + len 1)
go lim end []
where
go lim p ws
| lim == p = return ws
| otherwise = do
w <- peek p
let w0 = w `shiftR` 4
w1 = w .&. 0xf
go lim (p `plusPtr` (1)) (w0:w1:ws)
copy :: Ptr Word8 -> ByteString -> IO ()
copy dst (PS fptr off len) = withForeignPtr fptr $ \ptr -> do
let beg = ptr `plusPtr` off
memcpy dst beg (fromIntegral len)
foreign import ccall unsafe "string.h memcpy" c_memcpy
:: Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)
memcpy :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()
memcpy dst src s = void $ c_memcpy dst src (fromIntegral s)