module Hasql.Core.Loops.Serializer where import Hasql.Prelude import qualified ByteString.StrictBuilder as D import qualified Data.ByteString as B import qualified Data.ByteString.Internal as C data Message = SerializeMessage !D.Builder | FlushMessage loop :: IO Message -> (ByteString -> IO ()) -> IO () loop getMessage sendBytes = startAnew where size = shiftL 2 12 startAnew = do fp <- mallocForeignPtrBytes size processNextMessage fp 0 processNextMessage !fp !offset = do message <- getMessage case message of SerializeMessage builder -> D.builderPtrFiller builder $ \spaceRequired write -> serialize fp offset spaceRequired write FlushMessage -> do sendBytes (C.PS fp 0 offset) startAnew serialize !fp !offset !spaceRequired !write = if size - offset >= spaceRequired then do withForeignPtr fp (\p -> write (plusPtr p offset)) processNextMessage fp (offset + spaceRequired) else do when (offset >= 0) (sendBytes (C.PS fp 0 offset)) if spaceRequired >= size then do newFP <- mallocForeignPtrBytes spaceRequired withForeignPtr newFP write sendBytes (C.PS newFP 0 spaceRequired) startAnew else do newFP <- mallocForeignPtrBytes size withForeignPtr newFP write processNextMessage newFP spaceRequired