module Pinch.Internal.Builder
( Builder
, Build
, run
, int8
, int16
, int32
, int64
, double
, byteString
) where
#if __GLASGOW_HASKELL__ < 709
import Control.Applicative
#endif
import Data.ByteString (ByteString)
import Data.Int
import Data.Monoid
import Prelude hiding (length)
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
type Build = Builder ()
data Builder a = B !a !Int64 !BB.Builder
instance Functor Builder where
fmap f (B a l b) = B (f a) l b
instance Applicative Builder where
pure a = B a 0 mempty
B f l0 b0 <*> B a l1 b1 = B (f a) (l0 + l1) (b0 <> b1)
instance Monad Builder where
(>>) = (*>)
return = pure
B a l0 b0 >>= k =
let B b l1 b1 = k a
in B b (l0 + l1) (b0 <> b1)
run :: Build -> (Int64, BB.Builder)
run (B () l b) = (l, b)
int8 :: Int8 -> Build
int8 = B () 1 . BB.int8
int16 :: Int16 -> Build
int16 = B () 2 . BB.int16BE
int32 :: Int32 -> Build
int32 = B () 4 . BB.int32BE
int64 :: Int64 -> Build
int64 = B () 8 . BB.int64BE
double :: Double -> Build
double = B () 8 . BB.doubleBE
byteString :: ByteString -> Build
byteString bs = B () (fromIntegral $ B.length bs) (BB.byteString bs)