{-# LANGUAGE OverloadedStrings, ViewPatterns #-} import Control.Monad.Identity import Data.Bits import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import Data.Word import Test.Hspec.HUnit () import Test.Hspec.QuickCheck import Test.Hspec.Monadic import Test.HUnit import Data.Conduit.Bits main :: IO () main = hspec $ do describe "decoder" $ do it "decodes empty sequence" $ do a <- yield S.empty =$= decodeBits $$ CL.consume [] @=? a prop "decodes bits" $ \bs -> let a = runIdentity $ yield (S.pack bs) =$= decodeBits $$ CL.consume in decodeNaive bs == a describe "encoder" $ do it "encodes empty sequence" $ do a <- CL.sourceNull =$= encodeBits $$ CB.take maxBound L.empty @=? a prop "encodes bits" $ \bs -> let a = runIdentity $ CL.sourceList bs =$= encodeBits $$ CB.take maxBound in L.pack (encodeNaive bs) == a decodeNaive :: [Word8] -> [Bool] decodeNaive = concatMap f where f c = map (\i -> testBit c i) [0..7 :: Int] encodeNaive :: [Bool] -> [Word8] encodeNaive [] = [] encodeNaive (splitAt 8 -> (cur, next)) = let c = foldl (.|.) 0 (zipWith (\i b -> if b then bit i else 0) [0..] cur) in c : encodeNaive next