{-# 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
{ BitBuilder -> Word8
buffer :: Word.Word8,
BitBuilder -> Builder
builder :: Builder.Builder,
BitBuilder -> Int
offset :: Int
}
empty :: BitBuilder
empty :: BitBuilder
empty = BitBuilder {buffer :: Word8
buffer = Word8
0x00, builder :: Builder
builder = forall a. Monoid a => a
mempty, offset :: Int
offset = Int
0}
push :: Bool -> BitBuilder -> BitBuilder
push :: Bool -> BitBuilder -> BitBuilder
push Bool
b BitBuilder
x =
let !newBuffer :: Word8
newBuffer = if Bool
b then forall a. Bits a => a -> Int -> a
Bits.setBit (BitBuilder -> Word8
buffer BitBuilder
x) (BitBuilder -> Int
offset BitBuilder
x) else BitBuilder -> Word8
buffer BitBuilder
x
in if BitBuilder -> Int
offset BitBuilder
x forall a. Eq a => a -> a -> Bool
== Int
7
then
BitBuilder
{ buffer :: Word8
buffer = Word8
0x00,
builder :: Builder
builder = BitBuilder -> Builder
builder BitBuilder
x forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
Builder.word8 Word8
newBuffer,
offset :: Int
offset = Int
0
}
else BitBuilder
x {buffer :: Word8
buffer = Word8
newBuffer, offset :: Int
offset = BitBuilder -> Int
offset BitBuilder
x forall a. Num a => a -> a -> a
+ Int
1}
toBuilder :: BitBuilder -> Builder.Builder
toBuilder :: BitBuilder -> Builder
toBuilder BitBuilder
x =
if BitBuilder -> Int
offset BitBuilder
x forall a. Eq a => a -> a -> Bool
== Int
0 then BitBuilder -> Builder
builder BitBuilder
x else BitBuilder -> Builder
builder BitBuilder
x forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
Builder.word8 (BitBuilder -> Word8
buffer BitBuilder
x)