packages feed

rattletrap-11.0.0: src/lib/Rattletrap/BitBuilder.hs

{- hlint ignore "Avoid restricted extensions" -}
{-# LANGUAGE BangPatterns #-}

module Rattletrap.BitBuilder where

import qualified Data.Bits as Bits
import qualified Data.ByteString.Builder as Builder
import qualified Data.Word as Word

data BitBuilder = BitBuilder
  { buffer :: Word.Word8
  , builder :: Builder.Builder
  , offset :: Int
  }

empty :: BitBuilder
empty = BitBuilder { buffer = 0x00, builder = mempty, offset = 0 }

push :: Bool -> BitBuilder -> BitBuilder
push b x =
  let !newBuffer = if b then Bits.setBit (buffer x) (offset x) else buffer x
  in
    if offset x == 7
      then BitBuilder
        { buffer = 0x00
        , builder = builder x <> Builder.word8 newBuffer
        , offset = 0
        }
      else x { buffer = newBuffer, offset = offset x + 1 }

toBuilder :: BitBuilder -> Builder.Builder
toBuilder x =
  if offset x == 0 then builder x else builder x <> Builder.word8 (buffer x)