Как взять N бит из ByteString? - PullRequest
0 голосов
/ 02 марта 2020

Я знаю, как разбить Список на 2 части - (a1, rest) = splitAt N myList. Но с ByteString он не будет работать, потому что мы работаем с битами, а не байтами.

Как я могу взять N бит из ByteString? Или разделить его на 2 части, первая часть должна иметь размер N битов.

Ответы [ 3 ]

1 голос
/ 02 марта 2020

Вы не можете брать биты из ByteString. Однако вы можете взять биты из BitString, используя библиотеку bitstring.

import qualified Data.BitString as BitS


myBits = BitS.bitString myList

(a1, rest) = BitS.splitAt n myBits
0 голосов
/ 02 марта 2020

Ниже приведен полный пример. С учетом n и ByteString он вернет [Bool], представляющий биты. Напомним, что гораздо эффективнее использовать побитовые функции, предоставляемые Data.Bits

{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString as B
import qualified Data.Bits as Bits

example :: B.ByteString
example = "abc"

takeNBits :: Int -> B.ByteString -> [Bool]
takeNBits n bs = take n $ B.foldl' toBool [] bs
  where toBool l w = (Bits.testBit w <$> [0..(Bits.finiteBitSize w)]) ++ l

main = print $ takeNBits 18 example
0 голосов
/ 02 марта 2020

Data.Bits обеспечивает побитовые операции: https://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Bits.html
вы можете сначала разбить строку байтов на 2 строки байтов с помощью splitAt и словом 8, а затем прочитать слово 8 по битам с помощью testBit и shiftL / shiftR

type Frag = ([Bool], ByteString, [Bool])  -- naive representation of a list of bits

splitBS :: Int -> ByteString -> (Frag, Frag)
splitBS bits bs =
  let (byte, remb) = bits `quotRem` 8
      (bs1, t) = splitAt byte bs 
      w = head t
      bs2 = tail t
      (b1, b2) = splitWord remb w
   in (([], bs1, b1), (b2, bs2, []))

fromBits :: Bits a => a -> [Bool]
fromBits b
    | b == zeroBits = []
    | otherwise     = testBit b 0 : fromBits (shiftR b 1)

fromBits' :: Bits a => a -> [Bool]
fromBits' = reverse . fromBits

splitWord :: Int -> Word -> ([Bool], [Bool])
splitWord n w =
  let bl = fromBits' w
   in (take n bl, drop n bl)
...