packages feed

bitarray-bs-0.1.0.0: src/Data/ByteString/Bit.hs

{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

module Data.ByteString.Bit (

	-- * BIT

	B(..), bit,

	-- * LIST

	listToNum, listFromNum,

	-- * QUEUE

	Queue, empty, append, uncons, popByte

	) where

import Control.Arrow
import Data.Bits hiding (bit)
import Data.Bool
import Data.Word

data B = O | I deriving (Show, Eq, Ord)

bit :: a -> a -> B -> a
bit x y = \case O -> x; I -> y

listToNum :: Bits n => [B] -> n
listToNum = foldr (\b s -> bit id (`setBit` 0) b $ s `shiftL` 1) zeroBits

listFromNum :: Bits n => Int -> n -> [B]
listFromNum ln n = bool O I . (n `testBit`) <$> [0 .. ln - 1]

type Queue = ([B], [B])

empty :: Queue
empty = ([], [])

append :: Queue -> [B] -> Queue
append (xs, ys) bs = (xs, reverse bs ++ ys)

uncons :: Queue -> Maybe (B, Queue)
uncons = \case
	([], []) -> Nothing
	([], ys) -> uncons (reverse ys, [])
	(x : xs, ys) -> Just (x, (xs, ys))

popByte :: Queue -> Maybe (Word8, Queue)
popByte = ((listToNum `first`) <$>) . unfoldrN 8 uncons

unfoldrN :: Int -> (a -> Maybe (b, a)) -> a -> Maybe ([b], a)
unfoldrN 0 _ x = Just ([], x)
unfoldrN n f x = case f x of
	Nothing -> Nothing
	Just (y, x') -> ((y :) `first`) <$> unfoldrN (n - 1) f x'