packages feed

dfinity-radix-tree-0.6.0: src/DFINITY/RadixTree/Bits.hs

{-# LANGUAGE ExplicitForAll #-}

{-# OPTIONS -Wall #-}

module DFINITY.RadixTree.Bits
  ( Bitable(..)
  , matchBits
  )
where

import Data.Bits
import Data.Bool
import Data.ByteString       as Strict
import Data.ByteString.Short as Short
import Data.List             as List
import Data.Word

class Bitable a where
  fromBits :: [Bool] -> a
  toBits :: a -> [Bool]

instance Bitable ByteString where
  fromBits = Strict.pack . go where
    go [] = []
    go xs = let (a, b) = List.splitAt 8 xs in toByte a : go b
  toBits = List.concatMap fromByte . Strict.unpack

instance Bitable ShortByteString where
  fromBits = Short.pack . go where
    go [] = []
    go xs = let (a, b) = List.splitAt 8 xs in toByte a : go b
  toBits = List.concatMap fromByte . Short.unpack

matchBits :: [Bool] -> [Bool] -> [Bool]
matchBits x = List.map fst . zipWhile (==) x

zipWhile :: (a -> b -> Bool) -> [a] -> [b] -> [(a, b)]
zipWhile f x = List.takeWhile (uncurry f) . List.zip x

fromByte :: Word8 -> [Bool]
fromByte = flip List.map order . testBit

toByte :: [Bool] -> Word8
toByte = List.foldl (.|.) 0 . List.zipWith (bool 0 . setBit 0) order

order :: Enum a => Num a => [a]
order = [7, 6 .. 0]