{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE RankNTypes #-}
module Data.ByteString.FastBuilder.Internal
(
Builder(..)
, BuilderState
, DataSink(..)
, DynamicSink(..)
, Queue(..)
, Request(..)
, Response(..)
, SuspendBuilderException(..)
, ChunkOverflowException(..)
, BuildM(..)
, mkBuilder
, useBuilder
, getSink
, getCur
, getEnd
, setCur
, setEnd
, runBuilder
, toLazyByteString
, toLazyByteStringWith
, toStrictByteString
, hPutBuilder
, hPutBuilderLen
, hPutBuilderWith
, primBounded
, primFixed
, primMapListBounded
, primMapListFixed
, byteString
, byteStringThreshold
, byteStringCopy
, byteStringCopyNoCheck
, byteStringInsert
, unsafeCString
, unsafeCStringLen
, ensureBytes
, getBytes
, rebuild
) where
import Control.Concurrent (forkIOWithUnmask, myThreadId)
import Control.Concurrent.MVar
import qualified Control.Exception as E
import Control.Monad
import qualified Data.ByteString as S
import qualified Data.ByteString.Internal as S
import qualified Data.ByteString.Unsafe as S
import qualified Data.ByteString.Lazy as L
import Data.IORef
import Data.Semigroup as Sem
import Data.String
import Data.Word
import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.ForeignPtr.Unsafe
import Foreign.Marshal.Utils
import Foreign.Ptr
import qualified System.IO as IO
import System.IO.Unsafe
import GHC.Exts (Addr#, State#, RealWorld, Ptr(..), Int(..), Int#)
import GHC.Magic (oneShot)
import GHC.IO (IO(..), unIO)
import GHC.CString (unpackCString#)
import qualified Data.ByteString.Builder.Prim as P
import qualified Data.ByteString.Builder.Prim.Internal as PI
import qualified Data.ByteString.Builder.Extra as X
newtype Builder = Builder
{ Builder -> DataSink -> BuilderState -> BuilderState
unBuilder :: DataSink -> BuilderState -> BuilderState
}
type BuilderState = (# Addr#, Addr#, State# RealWorld #)
instance Sem.Semigroup Builder where
<> :: Builder -> Builder -> Builder
(<>) = Builder -> Builder -> Builder
appendBuilder
{-# INLINE (<>) #-}
appendBuilder :: Builder -> Builder -> Builder
appendBuilder :: Builder -> Builder -> Builder
appendBuilder (Builder DataSink -> BuilderState -> BuilderState
a) (Builder DataSink -> BuilderState -> BuilderState
b)
= Builder -> Builder
rebuild (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$ (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex BuilderState
bs -> DataSink -> BuilderState -> BuilderState
b DataSink
dex (DataSink -> BuilderState -> BuilderState
a DataSink
dex BuilderState
bs)
{-# INLINE[1] appendBuilder #-}
{-# RULES "appendBuilder/assoc"
forall x y z.
appendBuilder (appendBuilder x y) z = appendBuilder x (appendBuilder y z)
#-}
instance Monoid Builder where
mempty :: Builder
mempty = (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
_ BuilderState
bs -> BuilderState
bs
{-# INLINE mempty #-}
mappend :: Builder -> Builder -> Builder
mappend = Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
(<>)
{-# INLINE mappend #-}
mconcat :: [Builder] -> Builder
mconcat = (Builder -> Builder -> Builder) -> Builder -> [Builder] -> Builder
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
mappend Builder
forall a. Monoid a => a
mempty
{-# INLINE mconcat #-}
instance IsString Builder where
fromString :: String -> Builder
fromString = String -> Builder
builderFromString
{-# INLINE fromString #-}
data DataSink
= DynamicSink !(IORef DynamicSink)
| GrowingBuffer !(IORef (ForeignPtr Word8))
| HandleSink !IO.Handle !Int !(IORef Queue)
data DynamicSink
= ThreadedSink !(MVar Request) !(MVar Response)
| BoundedGrowingBuffer {-# UNPACK #-} !(ForeignPtr Word8) !Int
data Queue = Queue
{ Queue -> ForeignPtr Word8
queueBuffer :: !(ForeignPtr Word8)
, Queue -> Int
queueStart :: !Int
, Queue -> Int
queueTotal :: !Int
}
data Request
= Request {-# UNPACK #-} !(Ptr Word8) {-# UNPACK #-} !(Ptr Word8)
data Response
= Error E.SomeException
| Done !(Ptr Word8)
| MoreBuffer !(Ptr Word8) !Int
| InsertByteString !(Ptr Word8) !S.ByteString
deriving (Int -> Response -> ShowS
[Response] -> ShowS
Response -> String
(Int -> Response -> ShowS)
-> (Response -> String) -> ([Response] -> ShowS) -> Show Response
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Response] -> ShowS
$cshowList :: [Response] -> ShowS
show :: Response -> String
$cshow :: Response -> String
showsPrec :: Int -> Response -> ShowS
$cshowsPrec :: Int -> Response -> ShowS
Show)
data ChunkOverflowException
= ChunkOverflowException
!S.ByteString !(MVar Request) !(MVar Response) !Int
instance Show ChunkOverflowException where
show :: ChunkOverflowException -> String
show (ChunkOverflowException ByteString
buf MVar Request
_ MVar Response
_ Int
req) =
String
"ChunkOverflowException " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
buf String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" _ _ " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
req
instance E.Exception ChunkOverflowException
data SuspendBuilderException = SuspendBuilderException !(MVar ())
instance Show SuspendBuilderException where
show :: SuspendBuilderException -> String
show SuspendBuilderException
_ = String
"SuspendBuilderException"
instance E.Exception SuspendBuilderException
newtype BuildM a = BuildM { BuildM a -> (a -> Builder) -> Builder
runBuildM :: (a -> Builder) -> Builder }
deriving (a -> BuildM b -> BuildM a
(a -> b) -> BuildM a -> BuildM b
(forall a b. (a -> b) -> BuildM a -> BuildM b)
-> (forall a b. a -> BuildM b -> BuildM a) -> Functor BuildM
forall a b. a -> BuildM b -> BuildM a
forall a b. (a -> b) -> BuildM a -> BuildM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> BuildM b -> BuildM a
$c<$ :: forall a b. a -> BuildM b -> BuildM a
fmap :: (a -> b) -> BuildM a -> BuildM b
$cfmap :: forall a b. (a -> b) -> BuildM a -> BuildM b
Functor)
instance Applicative BuildM where
pure :: a -> BuildM a
pure = a -> BuildM a
forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: BuildM (a -> b) -> BuildM a -> BuildM b
(<*>) = BuildM (a -> b) -> BuildM a -> BuildM b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad BuildM where
return :: a -> BuildM a
return a
x = ((a -> Builder) -> Builder) -> BuildM a
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((a -> Builder) -> Builder) -> BuildM a)
-> ((a -> Builder) -> Builder) -> BuildM a
forall a b. (a -> b) -> a -> b
$ \a -> Builder
k -> a -> Builder
k a
x
{-# INLINE return #-}
BuildM (a -> Builder) -> Builder
b >>= :: BuildM a -> (a -> BuildM b) -> BuildM b
>>= a -> BuildM b
f = ((b -> Builder) -> Builder) -> BuildM b
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((b -> Builder) -> Builder) -> BuildM b)
-> ((b -> Builder) -> Builder) -> BuildM b
forall a b. (a -> b) -> a -> b
$ \b -> Builder
k -> (a -> Builder) -> Builder
b ((a -> Builder) -> Builder) -> (a -> Builder) -> Builder
forall a b. (a -> b) -> a -> b
$ \a
r -> BuildM b -> (b -> Builder) -> Builder
forall a. BuildM a -> (a -> Builder) -> Builder
runBuildM (a -> BuildM b
f a
r) b -> Builder
k
{-# INLINE (>>=) #-}
mkBuilder :: BuildM () -> Builder
mkBuilder :: BuildM () -> Builder
mkBuilder (BuildM (() -> Builder) -> Builder
bb) = (() -> Builder) -> Builder
bb ((() -> Builder) -> Builder) -> (() -> Builder) -> Builder
forall a b. (a -> b) -> a -> b
$ \()
_ -> Builder
forall a. Monoid a => a
mempty
{-# INLINE mkBuilder #-}
useBuilder :: Builder -> BuildM ()
useBuilder :: Builder -> BuildM ()
useBuilder Builder
b = ((() -> Builder) -> Builder) -> BuildM ()
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((() -> Builder) -> Builder) -> BuildM ())
-> ((() -> Builder) -> Builder) -> BuildM ()
forall a b. (a -> b) -> a -> b
$ \() -> Builder
k -> Builder
b Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> () -> Builder
k ()
{-# INLINE useBuilder #-}
getSink :: BuildM DataSink
getSink :: BuildM DataSink
getSink = ((DataSink -> Builder) -> Builder) -> BuildM DataSink
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((DataSink -> Builder) -> Builder) -> BuildM DataSink)
-> ((DataSink -> Builder) -> Builder) -> BuildM DataSink
forall a b. (a -> b) -> a -> b
$ \DataSink -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #) ->
Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (DataSink -> Builder
k DataSink
dex) DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #)
getCur :: BuildM (Ptr Word8)
getCur :: BuildM (Ptr Word8)
getCur = ((Ptr Word8 -> Builder) -> Builder) -> BuildM (Ptr Word8)
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((Ptr Word8 -> Builder) -> Builder) -> BuildM (Ptr Word8))
-> ((Ptr Word8 -> Builder) -> Builder) -> BuildM (Ptr Word8)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8 -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #) ->
Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (Ptr Word8 -> Builder
k (Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr Addr#
cur)) DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #)
getEnd :: BuildM (Ptr Word8)
getEnd :: BuildM (Ptr Word8)
getEnd = ((Ptr Word8 -> Builder) -> Builder) -> BuildM (Ptr Word8)
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((Ptr Word8 -> Builder) -> Builder) -> BuildM (Ptr Word8))
-> ((Ptr Word8 -> Builder) -> Builder) -> BuildM (Ptr Word8)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8 -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #) ->
Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (Ptr Word8 -> Builder
k (Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr Addr#
end)) DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #)
setCur :: Ptr Word8 -> BuildM ()
setCur :: Ptr Word8 -> BuildM ()
setCur (Ptr Addr#
p) = ((() -> Builder) -> Builder) -> BuildM ()
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((() -> Builder) -> Builder) -> BuildM ())
-> ((() -> Builder) -> Builder) -> BuildM ()
forall a b. (a -> b) -> a -> b
$ \() -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex (# Addr#
_, Addr#
end, State# RealWorld
s #) ->
Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (() -> Builder
k ()) DataSink
dex (# Addr#
p, Addr#
end, State# RealWorld
s #)
setEnd :: Ptr Word8 -> BuildM ()
setEnd :: Ptr Word8 -> BuildM ()
setEnd (Ptr Addr#
p) = ((() -> Builder) -> Builder) -> BuildM ()
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((() -> Builder) -> Builder) -> BuildM ())
-> ((() -> Builder) -> Builder) -> BuildM ()
forall a b. (a -> b) -> a -> b
$ \() -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex (# Addr#
cur, Addr#
_, State# RealWorld
s #) ->
Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (() -> Builder
k ()) DataSink
dex (# Addr#
cur, Addr#
p, State# RealWorld
s #)
io :: IO a -> BuildM a
io :: IO a -> BuildM a
io (IO State# RealWorld -> (# State# RealWorld, a #)
x) = ((a -> Builder) -> Builder) -> BuildM a
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((a -> Builder) -> Builder) -> BuildM a)
-> ((a -> Builder) -> Builder) -> BuildM a
forall a b. (a -> b) -> a -> b
$ \a -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #) -> case State# RealWorld -> (# State# RealWorld, a #)
x State# RealWorld
s of
(# State# RealWorld
s', a
val #) -> Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (a -> Builder
k a
val) DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s' #)
updateState :: (BuilderState -> BuilderState) -> BuildM ()
updateState :: (BuilderState -> BuilderState) -> BuildM ()
updateState BuilderState -> BuilderState
f = ((() -> Builder) -> Builder) -> BuildM ()
forall a. ((a -> Builder) -> Builder) -> BuildM a
BuildM (((() -> Builder) -> Builder) -> BuildM ())
-> ((() -> Builder) -> Builder) -> BuildM ()
forall a b. (a -> b) -> a -> b
$ \() -> Builder
k -> (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ \DataSink
sink BuilderState
bs ->
Builder -> DataSink -> BuilderState -> BuilderState
unBuilder (() -> Builder
k ()) DataSink
sink (BuilderState -> BuilderState
f BuilderState
bs)
data Write = Write !Int (BuilderState -> BuilderState)
instance Sem.Semigroup Write where
Write Int
s0 BuilderState -> BuilderState
w0 <> :: Write -> Write -> Write
<> Write Int
s1 BuilderState -> BuilderState
w1 = Int -> (BuilderState -> BuilderState) -> Write
Write (Int
s0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
s1) (\BuilderState
s -> BuilderState -> BuilderState
w1 (BuilderState -> BuilderState
w0 BuilderState
s))
instance Monoid Write where
mempty :: Write
mempty = Int -> (BuilderState -> BuilderState) -> Write
Write Int
0 (\BuilderState
s -> BuilderState
s)
mappend :: Write -> Write -> Write
mappend = Write -> Write -> Write
forall a. Semigroup a => a -> a -> a
(<>)
{-# INLINE mappend #-}
writeBoundedPrim :: PI.BoundedPrim a -> a -> Write
writeBoundedPrim :: BoundedPrim a -> a -> Write
writeBoundedPrim BoundedPrim a
prim a
x =
Int -> (BuilderState -> BuilderState) -> Write
Write (BoundedPrim a -> Int
forall a. BoundedPrim a -> Int
PI.sizeBound BoundedPrim a
prim) ((BuilderState -> BuilderState) -> Write)
-> (BuilderState -> BuilderState) -> Write
forall a b. (a -> b) -> a -> b
$ \(# Addr#
cur, Addr#
end, State# RealWorld
s #) ->
case IO (Ptr Word8)
-> State# RealWorld -> (# State# RealWorld, Ptr Word8 #)
forall a. IO a -> State# RealWorld -> (# State# RealWorld, a #)
unIO (BoundedPrim a -> a -> Ptr Word8 -> IO (Ptr Word8)
forall a. BoundedPrim a -> a -> Ptr Word8 -> IO (Ptr Word8)
PI.runB BoundedPrim a
prim a
x (Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr Addr#
cur)) State# RealWorld
s of
(# State# RealWorld
s', Ptr Addr#
cur' #) -> (# Addr#
cur', Addr#
end, State# RealWorld
s' #)
runBuilder :: Builder -> DataSink -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
runBuilder :: Builder -> DataSink -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
runBuilder (Builder DataSink -> BuilderState -> BuilderState
f) DataSink
sink (Ptr Addr#
cur) (Ptr Addr#
end) = (State# RealWorld -> (# State# RealWorld, Ptr Word8 #))
-> IO (Ptr Word8)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Ptr Word8 #))
-> IO (Ptr Word8))
-> (State# RealWorld -> (# State# RealWorld, Ptr Word8 #))
-> IO (Ptr Word8)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->
case DataSink -> BuilderState -> BuilderState
f DataSink
sink (# Addr#
cur, Addr#
end, State# RealWorld
s #) of
(# Addr#
cur', Addr#
_, State# RealWorld
s' #) -> (# State# RealWorld
s', Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr Addr#
cur' #)
toLazyByteString :: Builder -> L.ByteString
toLazyByteString :: Builder -> ByteString
toLazyByteString = Int -> Int -> Builder -> ByteString
toLazyByteStringWith Int
100 Int
32768
toLazyByteStringWith :: Int -> Int -> Builder -> L.ByteString
toLazyByteStringWith :: Int -> Int -> Builder -> ByteString
toLazyByteStringWith !Int
initialSize !Int
maxSize Builder
builder = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ do
ForeignPtr Word8
fptr <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
initialSize
IORef DynamicSink
sink <- DynamicSink -> IO (IORef DynamicSink)
forall a. a -> IO (IORef a)
newIORef (DynamicSink -> IO (IORef DynamicSink))
-> DynamicSink -> IO (IORef DynamicSink)
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Int -> DynamicSink
BoundedGrowingBuffer ForeignPtr Word8
fptr Int
maxSize
let !base :: Ptr Word8
base = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
let
finalPtr :: Ptr Word8
finalPtr = IO (Ptr Word8) -> Ptr Word8
forall a. IO a -> a
unsafeDupablePerformIO (IO (Ptr Word8) -> Ptr Word8) -> IO (Ptr Word8) -> Ptr Word8
forall a b. (a -> b) -> a -> b
$
Builder -> DataSink -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
runBuilder Builder
builder (IORef DynamicSink -> DataSink
DynamicSink IORef DynamicSink
sink) Ptr Word8
base (Ptr Word8
base Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
initialSize)
{-# NOINLINE finalPtr #-}
loop :: Ptr Word8 -> IO ByteString
loop Ptr Word8
thunk = do
Either SomeException (Ptr Word8)
r <- IO (Ptr Word8) -> IO (Either SomeException (Ptr Word8))
forall e a. Exception e => IO a -> IO (Either e a)
E.try (IO (Ptr Word8) -> IO (Either SomeException (Ptr Word8)))
-> IO (Ptr Word8) -> IO (Either SomeException (Ptr Word8))
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> IO (Ptr Word8)
forall a. a -> IO a
E.evaluate Ptr Word8
thunk
case Either SomeException (Ptr Word8)
r of
Right Ptr Word8
p -> do
BoundedGrowingBuffer ForeignPtr Word8
finalFptr Int
_ <- IORef DynamicSink -> IO DynamicSink
forall a. IORef a -> IO a
readIORef IORef DynamicSink
sink
let !finalBase :: Ptr Word8
finalBase = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
finalFptr
ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$! ByteString -> ByteString
L.fromStrict (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
ForeignPtr Word8 -> Int -> Int -> ByteString
S.fromForeignPtr ForeignPtr Word8
finalFptr Int
0 (Ptr Word8
p Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
finalBase)
Left SomeException
ex
| Just (ChunkOverflowException ByteString
chunk MVar Request
reqV MVar Response
respV Int
minSize)
<- SomeException -> Maybe ChunkOverflowException
forall e. Exception e => SomeException -> Maybe e
E.fromException SomeException
ex
-> do
let rest :: [ByteString]
rest = MVar Request
-> MVar Response -> Int -> Int -> Ptr Word8 -> [ByteString]
continueBuilderThreaded MVar Request
reqV MVar Response
respV Int
minSize Int
maxSize Ptr Word8
thunk
ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$ [ByteString] -> ByteString
L.fromChunks ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$
if ByteString -> Bool
S.null ByteString
chunk then [ByteString]
rest else ByteString
chunk ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
rest
| Bool
otherwise -> do
ThreadId
myTid <- IO ThreadId
myThreadId
ThreadId -> SomeException -> IO ()
forall e. Exception e => ThreadId -> e -> IO ()
E.throwTo ThreadId
myTid SomeException
ex
Ptr Word8 -> IO ByteString
loop Ptr Word8
thunk
Ptr Word8 -> IO ByteString
loop Ptr Word8
finalPtr
continueBuilderThreaded
:: MVar Request -> MVar Response -> Int -> Int -> Ptr Word8
-> [S.ByteString]
continueBuilderThreaded :: MVar Request
-> MVar Response -> Int -> Int -> Ptr Word8 -> [ByteString]
continueBuilderThreaded !MVar Request
reqV !MVar Response
respV !Int
initialSize !Int
maxSize Ptr Word8
thunk =
Int -> Int -> BufferWriter -> [ByteString]
makeChunks (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
maxSize Int
initialSize) Int
maxSize (BufferWriter -> [ByteString]) -> BufferWriter -> [ByteString]
forall a b. (a -> b) -> a -> b
$ MVar Request -> MVar Response -> Ptr Word8 -> BufferWriter
toBufferWriter MVar Request
reqV MVar Response
respV Ptr Word8
thunk
toBufferWriter :: MVar Request -> MVar Response -> Ptr Word8 -> X.BufferWriter
toBufferWriter :: MVar Request -> MVar Response -> Ptr Word8 -> BufferWriter
toBufferWriter !MVar Request
reqV !MVar Response
respV Ptr Word8
thunk Ptr Word8
buf0 Int
sz0 = IO (Int, Next) -> IO (Int, Next)
forall a. IO a -> IO a
E.mask_ (IO (Int, Next) -> IO (Int, Next))
-> IO (Int, Next) -> IO (Int, Next)
forall a b. (a -> b) -> a -> b
$
Maybe ThreadId -> BufferWriter
writer Maybe ThreadId
forall a. Maybe a
Nothing Ptr Word8
buf0 Int
sz0
where
writer :: Maybe ThreadId -> BufferWriter
writer !Maybe ThreadId
maybeBuilderTid !Ptr Word8
buf !Int
sz = do
MVar Request -> Request -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar Request
reqV (Request -> IO ()) -> Request -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> Ptr Word8 -> Request
Request Ptr Word8
buf (Ptr Word8
buf Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
sz)
ThreadId
builderTid <- case Maybe ThreadId
maybeBuilderTid of
Just ThreadId
t -> ThreadId -> IO ThreadId
forall (m :: * -> *) a. Monad m => a -> m a
return ThreadId
t
Maybe ThreadId
Nothing -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
forkIOWithUnmask (((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId)
-> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
u ->
(forall a. IO a -> IO a) -> MVar Response -> Ptr Word8 -> IO ()
builderThreadWithUnmask forall a. IO a -> IO a
u MVar Response
respV Ptr Word8
thunk
Response
resp <- ThreadId -> IO Response
wait ThreadId
builderTid
let go :: Ptr a -> b -> m (Int, b)
go Ptr a
cur b
next = (Int, b) -> m (Int, b)
forall (m :: * -> *) a. Monad m => a -> m a
return(Int
written, b
next)
where !written :: Int
written = Ptr a
cur Ptr a -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
buf
case Response
resp of
Error SomeException
ex -> SomeException -> IO (Int, Next)
forall e a. Exception e => e -> IO a
E.throwIO SomeException
ex
Done Ptr Word8
cur -> Ptr Word8 -> Next -> IO (Int, Next)
forall (m :: * -> *) a b. Monad m => Ptr a -> b -> m (Int, b)
go Ptr Word8
cur Next
X.Done
MoreBuffer Ptr Word8
cur Int
k -> Ptr Word8 -> Next -> IO (Int, Next)
forall (m :: * -> *) a b. Monad m => Ptr a -> b -> m (Int, b)
go Ptr Word8
cur (Next -> IO (Int, Next)) -> Next -> IO (Int, Next)
forall a b. (a -> b) -> a -> b
$ Int -> BufferWriter -> Next
X.More Int
k (BufferWriter -> Next) -> BufferWriter -> Next
forall a b. (a -> b) -> a -> b
$ Maybe ThreadId -> BufferWriter
writer (ThreadId -> Maybe ThreadId
forall a. a -> Maybe a
Just ThreadId
builderTid)
InsertByteString Ptr Word8
cur ByteString
str -> Ptr Word8 -> Next -> IO (Int, Next)
forall (m :: * -> *) a b. Monad m => Ptr a -> b -> m (Int, b)
go Ptr Word8
cur (Next -> IO (Int, Next)) -> Next -> IO (Int, Next)
forall a b. (a -> b) -> a -> b
$ ByteString -> BufferWriter -> Next
X.Chunk ByteString
str (BufferWriter -> Next) -> BufferWriter -> Next
forall a b. (a -> b) -> a -> b
$ Maybe ThreadId -> BufferWriter
writer (ThreadId -> Maybe ThreadId
forall a. a -> Maybe a
Just ThreadId
builderTid)
wait :: ThreadId -> IO Response
wait !ThreadId
builderTid = do
Either SomeException Response
r <- IO Response -> IO (Either SomeException Response)
forall e a. Exception e => IO a -> IO (Either e a)
E.try (IO Response -> IO (Either SomeException Response))
-> IO Response -> IO (Either SomeException Response)
forall a b. (a -> b) -> a -> b
$ MVar Response -> IO Response
forall a. MVar a -> IO a
takeMVar MVar Response
respV
case Either SomeException Response
r of
Right Response
resp -> Response -> IO Response
forall (m :: * -> *) a. Monad m => a -> m a
return Response
resp
Left SomeException
exn -> do
MVar ()
resumeVar <- IO (MVar ())
forall a. IO (MVar a)
newEmptyMVar
ThreadId -> SuspendBuilderException -> IO ()
forall e. Exception e => ThreadId -> e -> IO ()
E.throwTo ThreadId
builderTid (SuspendBuilderException -> IO ())
-> SuspendBuilderException -> IO ()
forall a b. (a -> b) -> a -> b
$ MVar () -> SuspendBuilderException
SuspendBuilderException MVar ()
resumeVar
ThreadId
thisTid <- IO ThreadId
myThreadId
ThreadId -> SomeException -> IO ()
forall e. Exception e => ThreadId -> e -> IO ()
E.throwTo ThreadId
thisTid (SomeException
exn :: E.SomeException)
MVar () -> () -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ()
resumeVar ()
ThreadId -> IO Response
wait ThreadId
builderTid
builderThreadWithUnmask
:: (forall a. IO a -> IO a) -> MVar Response -> Ptr Word8
-> IO ()
builderThreadWithUnmask :: (forall a. IO a -> IO a) -> MVar Response -> Ptr Word8 -> IO ()
builderThreadWithUnmask forall a. IO a -> IO a
unmask !MVar Response
respV Ptr Word8
thunk = IO ()
loop
where
loop :: IO ()
loop = do
Either SomeException (Ptr Word8)
r <- IO (Ptr Word8) -> IO (Either SomeException (Ptr Word8))
forall e a. Exception e => IO a -> IO (Either e a)
E.try (IO (Ptr Word8) -> IO (Either SomeException (Ptr Word8)))
-> IO (Ptr Word8) -> IO (Either SomeException (Ptr Word8))
forall a b. (a -> b) -> a -> b
$ IO (Ptr Word8) -> IO (Ptr Word8)
forall a. IO a -> IO a
unmask (IO (Ptr Word8) -> IO (Ptr Word8))
-> IO (Ptr Word8) -> IO (Ptr Word8)
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> IO (Ptr Word8)
forall a. a -> IO a
E.evaluate Ptr Word8
thunk
case Either SomeException (Ptr Word8)
r of
Right Ptr Word8
p -> MVar Response -> Response -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar Response
respV (Response -> IO ()) -> Response -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> Response
Done Ptr Word8
p
Left SomeException
ex
| Just (SuspendBuilderException MVar ()
lock) <- SomeException -> Maybe SuspendBuilderException
forall e. Exception e => SomeException -> Maybe e
E.fromException SomeException
ex
-> do MVar () -> IO ()
forall a. MVar a -> IO a
takeMVar MVar ()
lock; IO ()
loop
| Bool
otherwise -> MVar Response -> Response -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar Response
respV (Response -> IO ()) -> Response -> IO ()
forall a b. (a -> b) -> a -> b
$ SomeException -> Response
Error SomeException
ex
makeChunks :: Int -> Int -> X.BufferWriter -> [S.ByteString]
makeChunks :: Int -> Int -> BufferWriter -> [ByteString]
makeChunks !Int
initialBufSize Int
maxBufSize = Int -> BufferWriter -> [ByteString]
go Int
initialBufSize
where
go :: Int -> BufferWriter -> [ByteString]
go !Int
bufSize BufferWriter
w = IO [ByteString] -> [ByteString]
forall a. IO a -> a
unsafePerformIO (IO [ByteString] -> [ByteString])
-> IO [ByteString] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ do
ForeignPtr Word8
fptr <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
S.mallocByteString Int
bufSize
(Int
written, Next
next) <- ForeignPtr Word8 -> (Ptr Word8 -> IO (Int, Next)) -> IO (Int, Next)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fptr ((Ptr Word8 -> IO (Int, Next)) -> IO (Int, Next))
-> (Ptr Word8 -> IO (Int, Next)) -> IO (Int, Next)
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
buf -> BufferWriter
w Ptr Word8
buf Int
bufSize
let rest :: [ByteString]
rest = case Next
next of
Next
X.Done -> []
X.More reqSize w' -> Int -> BufferWriter -> [ByteString]
go (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
reqSize Int
maxBufSize) BufferWriter
w'
X.Chunk chunk w' -> ByteString
chunk ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: Int -> BufferWriter -> [ByteString]
go Int
maxBufSize BufferWriter
w'
[ByteString] -> IO [ByteString]
forall (m :: * -> *) a. Monad m => a -> m a
return ([ByteString] -> IO [ByteString])
-> [ByteString] -> IO [ByteString]
forall a b. (a -> b) -> a -> b
$ if Int
written Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
then [ByteString]
rest
else ForeignPtr Word8 -> Int -> Int -> ByteString
S.fromForeignPtr ForeignPtr Word8
fptr Int
0 Int
written ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: [ByteString]
rest
toStrictByteString :: Builder -> S.ByteString
toStrictByteString :: Builder -> ByteString
toStrictByteString Builder
builder = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ do
let cap :: Int
cap = Int
100
ForeignPtr Word8
fptr <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
cap
IORef (ForeignPtr Word8)
bufferRef <- ForeignPtr Word8 -> IO (IORef (ForeignPtr Word8))
forall a. a -> IO (IORef a)
newIORef ForeignPtr Word8
fptr
let !base :: Ptr Word8
base = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
Ptr Word8
cur <- Builder -> DataSink -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
runBuilder Builder
builder (IORef (ForeignPtr Word8) -> DataSink
GrowingBuffer IORef (ForeignPtr Word8)
bufferRef) Ptr Word8
base (Ptr Word8
base Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
cap)
ForeignPtr Word8
endFptr <- IORef (ForeignPtr Word8) -> IO (ForeignPtr Word8)
forall a. IORef a -> IO a
readIORef IORef (ForeignPtr Word8)
bufferRef
let !written :: Int
written = Ptr Word8
cur Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
endFptr
ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Int -> Int -> ByteString
S.fromForeignPtr ForeignPtr Word8
endFptr Int
0 Int
written
hPutBuilder :: IO.Handle -> Builder -> IO ()
hPutBuilder :: Handle -> Builder -> IO ()
hPutBuilder !Handle
h Builder
builder = IO Int -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO Int -> IO ()) -> IO Int -> IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> Builder -> IO Int
hPutBuilderLen Handle
h Builder
builder
{-# INLINE hPutBuilder #-}
hPutBuilderLen :: IO.Handle -> Builder -> IO Int
hPutBuilderLen :: Handle -> Builder -> IO Int
hPutBuilderLen !Handle
h Builder
builder = Handle -> Int -> Int -> Builder -> IO Int
hPutBuilderWith Handle
h Int
100 Int
4096 Builder
builder
hPutBuilderWith :: IO.Handle -> Int -> Int -> Builder -> IO Int
hPutBuilderWith :: Handle -> Int -> Int -> Builder -> IO Int
hPutBuilderWith !Handle
h !Int
initialCap !Int
nextCap Builder
builder = do
ForeignPtr Word8
fptr <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
initialCap
IORef Queue
qRef <- Queue -> IO (IORef Queue)
forall a. a -> IO (IORef a)
newIORef (Queue -> IO (IORef Queue)) -> Queue -> IO (IORef Queue)
forall a b. (a -> b) -> a -> b
$ Queue :: ForeignPtr Word8 -> Int -> Int -> Queue
Queue
{ queueBuffer :: ForeignPtr Word8
queueBuffer = ForeignPtr Word8
fptr
, queueStart :: Int
queueStart = Int
0
, queueTotal :: Int
queueTotal = Int
0
}
let !base :: Ptr Word8
base = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
Ptr Word8
cur <- Builder -> DataSink -> Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)
runBuilder Builder
builder (Handle -> Int -> IORef Queue -> DataSink
HandleSink Handle
h Int
nextCap IORef Queue
qRef)
Ptr Word8
base (Ptr Word8
base Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
initialCap)
Handle -> IORef Queue -> Ptr Word8 -> IO ()
flushQueue Handle
h IORef Queue
qRef Ptr Word8
cur
Queue{ queueTotal :: Queue -> Int
queueTotal = Int
len } <- IORef Queue -> IO Queue
forall a. IORef a -> IO a
readIORef IORef Queue
qRef
Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
len
builderFromString :: String -> Builder
builderFromString :: String -> Builder
builderFromString = BoundedPrim Char -> String -> Builder
forall a. BoundedPrim a -> [a] -> Builder
primMapListBounded BoundedPrim Char
P.charUtf8
{-# NOINLINE[0] builderFromString #-}
{-# RULES "FastBuilder: builderFromString/unpackCString#"
forall addr.
builderFromString (unpackCString# addr) = unsafeCString (Ptr addr)
#-}
primBounded :: PI.BoundedPrim a -> a -> Builder
primBounded :: BoundedPrim a -> a -> Builder
primBounded BoundedPrim a
prim = Write -> Builder
write (Write -> Builder) -> (a -> Write) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BoundedPrim a -> a -> Write
forall a. BoundedPrim a -> a -> Write
writeBoundedPrim BoundedPrim a
prim
{-# INLINE primBounded #-}
write :: Write -> Builder
write :: Write -> Builder
write (Write Int
size BuilderState -> BuilderState
w) = Builder -> Builder
rebuild (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$ BuildM () -> Builder
mkBuilder (BuildM () -> Builder) -> BuildM () -> Builder
forall a b. (a -> b) -> a -> b
$ do
Builder -> BuildM ()
useBuilder (Builder -> BuildM ()) -> Builder -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Int -> Builder
ensureBytes Int
size
(BuilderState -> BuilderState) -> BuildM ()
updateState BuilderState -> BuilderState
w
{-# INLINE[1] write #-}
{-# RULES "fast-builder: write/write"
forall w0 w1.
appendBuilder (write w0) (write w1) = write (w0 <> w1)
#-}
{-# RULES "fast-builder: write/write/x"
forall w0 w1 x.
appendBuilder (write w0) (appendBuilder (write w1) x)
= appendBuilder (write (w0 <> w1)) x
#-}
primFixed :: PI.FixedPrim a -> a -> Builder
primFixed :: FixedPrim a -> a -> Builder
primFixed FixedPrim a
prim = BoundedPrim a -> a -> Builder
forall a. BoundedPrim a -> a -> Builder
primBounded (FixedPrim a -> BoundedPrim a
forall a. FixedPrim a -> BoundedPrim a
PI.toB FixedPrim a
prim)
{-# INLINE primFixed #-}
primMapListBounded :: PI.BoundedPrim a -> [a] -> Builder
primMapListBounded :: BoundedPrim a -> [a] -> Builder
primMapListBounded BoundedPrim a
prim = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> ([a] -> [Builder]) -> [a] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Builder) -> [a] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map (BoundedPrim a -> a -> Builder
forall a. BoundedPrim a -> a -> Builder
primBounded BoundedPrim a
prim)
{-# INLINE primMapListBounded #-}
primMapListFixed :: PI.FixedPrim a -> [a] -> Builder
primMapListFixed :: FixedPrim a -> [a] -> Builder
primMapListFixed FixedPrim a
prim = BoundedPrim a -> [a] -> Builder
forall a. BoundedPrim a -> [a] -> Builder
primMapListBounded (FixedPrim a -> BoundedPrim a
forall a. FixedPrim a -> BoundedPrim a
PI.toB FixedPrim a
prim)
{-# INLINE primMapListFixed #-}
byteString :: S.ByteString -> Builder
byteString :: ByteString -> Builder
byteString = Int -> ByteString -> Builder
byteStringThreshold Int
maximalCopySize
{-# INLINE byteString #-}
maximalCopySize :: Int
maximalCopySize :: Int
maximalCopySize = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
X.smallChunkSize
byteStringThreshold :: Int -> S.ByteString -> Builder
byteStringThreshold :: Int -> ByteString -> Builder
byteStringThreshold Int
th ByteString
bstr = Builder -> Builder
rebuild (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$
if ByteString -> Int
S.length ByteString
bstr Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
th
then ByteString -> Builder
byteStringInsert ByteString
bstr
else ByteString -> Builder
byteStringCopy ByteString
bstr
byteStringCopy :: S.ByteString -> Builder
byteStringCopy :: ByteString -> Builder
byteStringCopy !ByteString
bstr =
Int -> Builder
ensureBytes (ByteString -> Int
S.length ByteString
bstr) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
byteStringCopyNoCheck ByteString
bstr
byteStringCopyNoCheck :: S.ByteString -> Builder
byteStringCopyNoCheck :: ByteString -> Builder
byteStringCopyNoCheck !ByteString
bstr = BuildM () -> Builder
mkBuilder (BuildM () -> Builder) -> BuildM () -> Builder
forall a b. (a -> b) -> a -> b
$ do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ ByteString -> (CString -> IO ()) -> IO ()
forall a. ByteString -> (CString -> IO a) -> IO a
S.unsafeUseAsCString ByteString
bstr ((CString -> IO ()) -> IO ()) -> (CString -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \CString
ptr ->
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
cur (CString -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr CString
ptr) Int
len
Ptr Word8 -> BuildM ()
setCur (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
cur Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len
where
!len :: Int
len = ByteString -> Int
S.length ByteString
bstr
byteStringInsert :: S.ByteString -> Builder
byteStringInsert :: ByteString -> Builder
byteStringInsert !ByteString
bstr = ByteString -> Builder
byteStringInsert_ ByteString
bstr
byteStringInsert_ :: S.ByteString -> Builder
byteStringInsert_ :: ByteString -> Builder
byteStringInsert_ ByteString
bstr = BuildM () -> Builder
mkBuilder (BuildM () -> Builder) -> BuildM () -> Builder
forall a b. (a -> b) -> a -> b
$ do
DataSink
sink <- BuildM DataSink
getSink
case DataSink
sink of
DynamicSink IORef DynamicSink
dRef -> do
DynamicSink
dyn <- IO DynamicSink -> BuildM DynamicSink
forall a. IO a -> BuildM a
io (IO DynamicSink -> BuildM DynamicSink)
-> IO DynamicSink -> BuildM DynamicSink
forall a b. (a -> b) -> a -> b
$ IORef DynamicSink -> IO DynamicSink
forall a. IORef a -> IO a
readIORef IORef DynamicSink
dRef
case DynamicSink
dyn of
ThreadedSink MVar Request
reqV MVar Response
respV -> do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ MVar Response -> Response -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar Response
respV (Response -> IO ()) -> Response -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> ByteString -> Response
InsertByteString Ptr Word8
cur ByteString
bstr
MVar Request -> BuildM ()
handleRequest MVar Request
reqV
BoundedGrowingBuffer ForeignPtr Word8
fptr Int
bound -> do
Int
r <- BuildM Int
remainingBytes
Bool -> BuildM () -> BuildM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
r Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ByteString -> Int
S.length ByteString
bstr) (BuildM () -> BuildM ()) -> BuildM () -> BuildM ()
forall a b. (a -> b) -> a -> b
$
IORef DynamicSink -> ForeignPtr Word8 -> Int -> Int -> BuildM ()
growBufferBounded IORef DynamicSink
dRef ForeignPtr Word8
fptr Int
bound (ByteString -> Int
S.length ByteString
bstr)
Builder -> BuildM ()
useBuilder (Builder -> BuildM ()) -> Builder -> BuildM ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Builder
byteStringCopyNoCheck ByteString
bstr
GrowingBuffer IORef (ForeignPtr Word8)
bufRef -> do
Int
r <- BuildM Int
remainingBytes
Bool -> BuildM () -> BuildM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
r Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ByteString -> Int
S.length ByteString
bstr) (BuildM () -> BuildM ()) -> BuildM () -> BuildM ()
forall a b. (a -> b) -> a -> b
$
IORef (ForeignPtr Word8) -> Int -> BuildM ()
growBuffer IORef (ForeignPtr Word8)
bufRef (ByteString -> Int
S.length ByteString
bstr)
Builder -> BuildM ()
useBuilder (Builder -> BuildM ()) -> Builder -> BuildM ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Builder
byteStringCopyNoCheck ByteString
bstr
HandleSink Handle
h Int
_nextCap IORef Queue
queueRef -> do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Handle -> IORef Queue -> Ptr Word8 -> IO ()
flushQueue Handle
h IORef Queue
queueRef Ptr Word8
cur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Handle -> ByteString -> IO ()
S.hPut Handle
h ByteString
bstr
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ IORef Queue -> (Queue -> Queue) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef Queue
queueRef
((Queue -> Queue) -> IO ()) -> (Queue -> Queue) -> IO ()
forall a b. (a -> b) -> a -> b
$ \Queue
q -> Queue
q { queueTotal :: Int
queueTotal = Queue -> Int
queueTotal Queue
q Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteString -> Int
S.length ByteString
bstr }
{-# NOINLINE byteStringInsert_ #-}
unsafeCString :: CString -> Builder
unsafeCString :: CString -> Builder
unsafeCString CString
cstr = Builder -> Builder
rebuild (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$ let
!len :: Int
len = CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CSize -> Int) -> CSize -> Int
forall a b. (a -> b) -> a -> b
$ CString -> CSize
c_pure_strlen CString
cstr
in CStringLen -> Builder
unsafeCStringLen (CString
cstr, Int
len)
foreign import ccall unsafe "strlen" c_pure_strlen :: CString -> CSize
unsafeCStringLen :: CStringLen -> Builder
unsafeCStringLen :: CStringLen -> Builder
unsafeCStringLen (CString
ptr, Int
len) = Builder -> Builder -> Builder
forall a. Monoid a => a -> a -> a
mappend (Int -> Builder
ensureBytes Int
len) (Builder -> Builder) -> Builder -> Builder
forall a b. (a -> b) -> a -> b
$ BuildM () -> Builder
mkBuilder (BuildM () -> Builder) -> BuildM () -> Builder
forall a b. (a -> b) -> a -> b
$ do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> Ptr Word8 -> Int -> IO ()
forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
cur (CString -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr CString
ptr) Int
len
Ptr Word8 -> BuildM ()
setCur (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
cur Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
len
ensureBytes :: Int -> Builder
ensureBytes :: Int -> Builder
ensureBytes !Int
n = BuildM () -> Builder
mkBuilder (BuildM () -> Builder) -> BuildM () -> Builder
forall a b. (a -> b) -> a -> b
$ do
Int
r <- BuildM Int
remainingBytes
Bool -> BuildM () -> BuildM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
r Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n) (BuildM () -> BuildM ()) -> BuildM () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Builder -> BuildM ()
useBuilder (Builder -> BuildM ()) -> Builder -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Int -> Builder
getBytes Int
n
{-# INLINE ensureBytes #-}
getBytes :: Int -> Builder
getBytes :: Int -> Builder
getBytes (I# Int#
n) = Int# -> Builder
getBytes_ Int#
n
getBytes_ :: Int# -> Builder
getBytes_ :: Int# -> Builder
getBytes_ Int#
n = BuildM () -> Builder
mkBuilder (BuildM () -> Builder) -> BuildM () -> Builder
forall a b. (a -> b) -> a -> b
$ do
DataSink
sink <- BuildM DataSink
getSink
case DataSink
sink of
DynamicSink IORef DynamicSink
dRef -> do
DynamicSink
dyn <- IO DynamicSink -> BuildM DynamicSink
forall a. IO a -> BuildM a
io (IO DynamicSink -> BuildM DynamicSink)
-> IO DynamicSink -> BuildM DynamicSink
forall a b. (a -> b) -> a -> b
$ IORef DynamicSink -> IO DynamicSink
forall a. IORef a -> IO a
readIORef IORef DynamicSink
dRef
case DynamicSink
dyn of
ThreadedSink MVar Request
reqV MVar Response
respV -> do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ MVar Response -> Response -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar Response
respV (Response -> IO ()) -> Response -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8 -> Int -> Response
MoreBuffer Ptr Word8
cur (Int -> Response) -> Int -> Response
forall a b. (a -> b) -> a -> b
$ Int# -> Int
I# Int#
n
MVar Request -> BuildM ()
handleRequest MVar Request
reqV
BoundedGrowingBuffer ForeignPtr Word8
fptr Int
bound ->
IORef DynamicSink -> ForeignPtr Word8 -> Int -> Int -> BuildM ()
growBufferBounded IORef DynamicSink
dRef ForeignPtr Word8
fptr Int
bound (Int# -> Int
I# Int#
n)
GrowingBuffer IORef (ForeignPtr Word8)
bufRef -> IORef (ForeignPtr Word8) -> Int -> BuildM ()
growBuffer IORef (ForeignPtr Word8)
bufRef (Int# -> Int
I# Int#
n)
HandleSink Handle
h Int
nextCap IORef Queue
queueRef -> do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Handle -> IORef Queue -> Ptr Word8 -> IO ()
flushQueue Handle
h IORef Queue
queueRef Ptr Word8
cur
IORef Queue -> Int -> BuildM ()
switchQueue IORef Queue
queueRef (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
nextCap (Int# -> Int
I# Int#
n))
{-# NOINLINE getBytes_ #-}
remainingBytes :: BuildM Int
remainingBytes :: BuildM Int
remainingBytes = Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
minusPtr (Ptr Word8 -> Ptr Word8 -> Int)
-> BuildM (Ptr Word8) -> BuildM (Ptr Word8 -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BuildM (Ptr Word8)
getEnd BuildM (Ptr Word8 -> Int) -> BuildM (Ptr Word8) -> BuildM Int
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BuildM (Ptr Word8)
getCur
{-# INLINE remainingBytes #-}
rebuild :: Builder -> Builder
rebuild :: Builder -> Builder
rebuild (Builder DataSink -> BuilderState -> BuilderState
f) = (DataSink -> BuilderState -> BuilderState) -> Builder
Builder ((DataSink -> BuilderState -> BuilderState) -> Builder)
-> (DataSink -> BuilderState -> BuilderState) -> Builder
forall a b. (a -> b) -> a -> b
$ (DataSink -> BuilderState -> BuilderState)
-> DataSink -> BuilderState -> BuilderState
oneShot ((DataSink -> BuilderState -> BuilderState)
-> DataSink -> BuilderState -> BuilderState)
-> (DataSink -> BuilderState -> BuilderState)
-> DataSink
-> BuilderState
-> BuilderState
forall a b. (a -> b) -> a -> b
$ \DataSink
dex -> (BuilderState -> BuilderState) -> BuilderState -> BuilderState
oneShot ((BuilderState -> BuilderState) -> BuilderState -> BuilderState)
-> (BuilderState -> BuilderState) -> BuilderState -> BuilderState
forall a b. (a -> b) -> a -> b
$
\(# Addr#
cur, Addr#
end, State# RealWorld
s #) -> DataSink -> BuilderState -> BuilderState
f DataSink
dex (# Addr#
cur, Addr#
end, State# RealWorld
s #)
handleRequest :: MVar Request -> BuildM ()
handleRequest :: MVar Request -> BuildM ()
handleRequest MVar Request
reqV = do
Request Ptr Word8
newCur Ptr Word8
newEnd <- IO Request -> BuildM Request
forall a. IO a -> BuildM a
io (IO Request -> BuildM Request) -> IO Request -> BuildM Request
forall a b. (a -> b) -> a -> b
$ MVar Request -> IO Request
forall a. MVar a -> IO a
takeMVar MVar Request
reqV
Ptr Word8 -> BuildM ()
setCur Ptr Word8
newCur
Ptr Word8 -> BuildM ()
setEnd Ptr Word8
newEnd
growBuffer :: IORef (ForeignPtr Word8) -> Int -> BuildM ()
growBuffer :: IORef (ForeignPtr Word8) -> Int -> BuildM ()
growBuffer !IORef (ForeignPtr Word8)
bufRef !Int
req = do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
Ptr Word8
end <- BuildM (Ptr Word8)
getEnd
ForeignPtr Word8
fptr <- IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a. IO a -> BuildM a
io (IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8))
-> IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a b. (a -> b) -> a -> b
$ IORef (ForeignPtr Word8) -> IO (ForeignPtr Word8)
forall a. IORef a -> IO a
readIORef IORef (ForeignPtr Word8)
bufRef
let !base :: Ptr Word8
base = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
let !size :: Int
size = Ptr Word8
cur Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
base
let !cap :: Int
cap = Ptr Word8
end Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
base
let !newCap :: Int
newCap = Int
cap Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
cap Int
req
ForeignPtr Word8
newFptr <- IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a. IO a -> BuildM a
io (IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8))
-> IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a b. (a -> b) -> a -> b
$ Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
newCap
let !newBase :: Ptr Word8
newBase = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
newFptr
Ptr Word8 -> BuildM ()
setCur (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
newBase Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
size
Ptr Word8 -> BuildM ()
setEnd (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
newBase Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
newCap
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ do
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
newBase Ptr Word8
base Int
size
ForeignPtr Word8 -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr Word8
fptr
ForeignPtr Word8 -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr Word8
newFptr
IORef (ForeignPtr Word8) -> ForeignPtr Word8 -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (ForeignPtr Word8)
bufRef ForeignPtr Word8
newFptr
{-# INLINE growBuffer #-}
flushQueue :: IO.Handle -> IORef Queue -> Ptr Word8 -> IO ()
flushQueue :: Handle -> IORef Queue -> Ptr Word8 -> IO ()
flushQueue !Handle
h !IORef Queue
qRef !Ptr Word8
cur = do
Queue{ queueBuffer :: Queue -> ForeignPtr Word8
queueBuffer = ForeignPtr Word8
fptr, queueStart :: Queue -> Int
queueStart = Int
start, queueTotal :: Queue -> Int
queueTotal = Int
total }
<- IORef Queue -> IO Queue
forall a. IORef a -> IO a
readIORef IORef Queue
qRef
let !end :: Int
end = Ptr Word8
cur Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
end Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
start) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Handle -> ByteString -> IO ()
S.hPut Handle
h (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Int -> Int -> ByteString
S.fromForeignPtr ForeignPtr Word8
fptr Int
start (Int
end Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
start)
IORef Queue -> Queue -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Queue
qRef Queue :: ForeignPtr Word8 -> Int -> Int -> Queue
Queue
{ queueBuffer :: ForeignPtr Word8
queueBuffer = ForeignPtr Word8
fptr
, queueStart :: Int
queueStart = Int
end
, queueTotal :: Int
queueTotal = Int
total Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
end Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
start
}
switchQueue :: IORef Queue -> Int -> BuildM ()
switchQueue :: IORef Queue -> Int -> BuildM ()
switchQueue !IORef Queue
qRef !Int
minSize = do
Ptr Word8
end <- BuildM (Ptr Word8)
getCur
Queue{ queueBuffer :: Queue -> ForeignPtr Word8
queueBuffer = ForeignPtr Word8
fptr, queueTotal :: Queue -> Int
queueTotal = Int
total } <- IO Queue -> BuildM Queue
forall a. IO a -> BuildM a
io (IO Queue -> BuildM Queue) -> IO Queue -> BuildM Queue
forall a b. (a -> b) -> a -> b
$ IORef Queue -> IO Queue
forall a. IORef a -> IO a
readIORef IORef Queue
qRef
let !base :: Ptr Word8
base = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
let !cap :: Int
cap = Ptr Word8
end Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
base
ForeignPtr Word8
newFptr <- if Int
minSize Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
cap
then ForeignPtr Word8 -> BuildM (ForeignPtr Word8)
forall (m :: * -> *) a. Monad m => a -> m a
return ForeignPtr Word8
fptr
else IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a. IO a -> BuildM a
io (IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8))
-> IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a b. (a -> b) -> a -> b
$ Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
minSize
let !newBase :: Ptr Word8
newBase = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
newFptr
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ IORef Queue -> Queue -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Queue
qRef Queue :: ForeignPtr Word8 -> Int -> Int -> Queue
Queue
{ queueBuffer :: ForeignPtr Word8
queueBuffer = ForeignPtr Word8
newFptr
, queueStart :: Int
queueStart = Int
0
, queueTotal :: Int
queueTotal = Int
total
}
Ptr Word8 -> BuildM ()
setCur Ptr Word8
newBase
Ptr Word8 -> BuildM ()
setEnd (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
newBase Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
minSize Int
cap
growBufferBounded
:: IORef DynamicSink -> ForeignPtr Word8 -> Int -> Int -> BuildM ()
growBufferBounded :: IORef DynamicSink -> ForeignPtr Word8 -> Int -> Int -> BuildM ()
growBufferBounded !IORef DynamicSink
dRef !ForeignPtr Word8
fptr !Int
bound !Int
req = do
Ptr Word8
cur <- BuildM (Ptr Word8)
getCur
Ptr Word8
end <- BuildM (Ptr Word8)
getCur
let !base :: Ptr Word8
base = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
fptr
let !size :: Int
size = Ptr Word8
cur Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
base
let !cap :: Int
cap = Ptr Word8
end Ptr Word8 -> Ptr Word8 -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr Word8
base
let !newCap :: Int
newCap = Int
cap Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
cap Int
req
if Int
bound Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
newCap
then IORef DynamicSink -> Int -> ByteString -> BuildM ()
chunkOverflow IORef DynamicSink
dRef Int
req (ByteString -> BuildM ()) -> ByteString -> BuildM ()
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Int -> Int -> ByteString
S.fromForeignPtr ForeignPtr Word8
fptr Int
0 Int
size
else do
ForeignPtr Word8
newFptr <- IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a. IO a -> BuildM a
io (IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8))
-> IO (ForeignPtr Word8) -> BuildM (ForeignPtr Word8)
forall a b. (a -> b) -> a -> b
$ Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
newCap
let !newBase :: Ptr Word8
newBase = ForeignPtr Word8 -> Ptr Word8
forall a. ForeignPtr a -> Ptr a
unsafeForeignPtrToPtr ForeignPtr Word8
newFptr
Ptr Word8 -> BuildM ()
setCur (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
newBase Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
size
Ptr Word8 -> BuildM ()
setEnd (Ptr Word8 -> BuildM ()) -> Ptr Word8 -> BuildM ()
forall a b. (a -> b) -> a -> b
$ Ptr Word8
newBase Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
newCap
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ do
Ptr Word8 -> Ptr Word8 -> Int -> IO ()
forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Ptr Word8
newBase Ptr Word8
base Int
size
ForeignPtr Word8 -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr Word8
fptr
ForeignPtr Word8 -> IO ()
forall a. ForeignPtr a -> IO ()
touchForeignPtr ForeignPtr Word8
newFptr
IORef DynamicSink -> DynamicSink -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef DynamicSink
dRef (DynamicSink -> IO ()) -> DynamicSink -> IO ()
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> Int -> DynamicSink
BoundedGrowingBuffer ForeignPtr Word8
newFptr Int
bound
{-# INLINE growBufferBounded #-}
chunkOverflow :: IORef DynamicSink -> Int -> S.ByteString -> BuildM ()
chunkOverflow :: IORef DynamicSink -> Int -> ByteString -> BuildM ()
chunkOverflow !IORef DynamicSink
dRef !Int
minSize !ByteString
chunk = do
ThreadId
myTid <- IO ThreadId -> BuildM ThreadId
forall a. IO a -> BuildM a
io IO ThreadId
myThreadId
MVar Request
reqV <- IO (MVar Request) -> BuildM (MVar Request)
forall a. IO a -> BuildM a
io IO (MVar Request)
forall a. IO (MVar a)
newEmptyMVar
MVar Response
respV <- IO (MVar Response) -> BuildM (MVar Response)
forall a. IO a -> BuildM a
io IO (MVar Response)
forall a. IO (MVar a)
newEmptyMVar
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ ThreadId -> ChunkOverflowException -> IO ()
forall e. Exception e => ThreadId -> e -> IO ()
E.throwTo ThreadId
myTid (ChunkOverflowException -> IO ())
-> ChunkOverflowException -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString
-> MVar Request -> MVar Response -> Int -> ChunkOverflowException
ChunkOverflowException ByteString
chunk MVar Request
reqV MVar Response
respV Int
minSize
IO () -> BuildM ()
forall a. IO a -> BuildM a
io (IO () -> BuildM ()) -> IO () -> BuildM ()
forall a b. (a -> b) -> a -> b
$ IORef DynamicSink -> DynamicSink -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef DynamicSink
dRef (DynamicSink -> IO ()) -> DynamicSink -> IO ()
forall a b. (a -> b) -> a -> b
$ MVar Request -> MVar Response -> DynamicSink
ThreadedSink MVar Request
reqV MVar Response
respV
MVar Request -> BuildM ()
handleRequest MVar Request
reqV