{-# 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 :: Word8 -> Builder -> Int -> BitBuilder
BitBuilder { buffer :: Word8
buffer = Word8
0x00, builder :: 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 Word8 -> Int -> Word8
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 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
7
then BitBuilder :: Word8 -> Builder -> Int -> BitBuilder
BitBuilder
{ buffer :: Word8
buffer = Word8
0x00
, builder :: Builder
builder = BitBuilder -> Builder
builder BitBuilder
x Builder -> Builder -> Builder
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 Int -> Int -> Int
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 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then BitBuilder -> Builder
builder BitBuilder
x else BitBuilder -> Builder
builder BitBuilder
x Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
Builder.word8 (BitBuilder -> Word8
buffer BitBuilder
x)