module Network.Socket.BufferPool.Buffer (
newBufferPool,
withBufferPool,
tryWithBufferPool,
eitherWithBufferPool,
mallocBS,
copy,
) where
import qualified Data.ByteString as BS
import Data.ByteString.Internal (ByteString (..))
import Data.IORef (newIORef, readIORef, writeIORef)
import Foreign.ForeignPtr
import Foreign.Marshal.Alloc (finalizerFree, mallocBytes)
import Foreign.Marshal.Utils (copyBytes)
import Foreign.Ptr (castPtr, plusPtr)
import Network.Socket.BufferPool.Types
newBufferPool :: Int -> Int -> IO BufferPool
newBufferPool :: Int -> Int -> IO BufferPool
newBufferPool Int
l Int
h = Int -> Int -> IORef ByteString -> BufferPool
BufferPool Int
l Int
h (IORef ByteString -> BufferPool)
-> IO (IORef ByteString) -> IO BufferPool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> IO (IORef ByteString)
forall a. a -> IO (IORef a)
newIORef ByteString
BS.empty
withBufferPool :: BufferPool -> (Buffer -> BufSize -> IO Int) -> IO ByteString
withBufferPool :: BufferPool -> (Buffer -> Int -> IO Int) -> IO ByteString
withBufferPool pool :: BufferPool
pool@(BufferPool Int
_ Int
_ IORef ByteString
ref) Buffer -> Int -> IO Int
f = do
(ByteString
buf, Int
consumed) <- BufferPool -> (Buffer -> Int -> IO Int) -> IO (ByteString, Int)
forall r.
BufferPool -> (Buffer -> Int -> IO r) -> IO (ByteString, r)
applyBufferPool BufferPool
pool Buffer -> Int -> IO Int
f
IORef ByteString -> ByteString -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef ByteString
ref (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.drop Int
consumed ByteString
buf
ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> IO ByteString) -> ByteString -> IO ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.take Int
consumed ByteString
buf
tryWithBufferPool
:: BufferPool -> (Buffer -> BufSize -> IO Int) -> IO (Maybe ByteString)
tryWithBufferPool :: BufferPool -> (Buffer -> Int -> IO Int) -> IO (Maybe ByteString)
tryWithBufferPool pool :: BufferPool
pool@(BufferPool Int
_ Int
_ IORef ByteString
ref) Buffer -> Int -> IO Int
f = do
(ByteString
buf, Int
consumed) <- BufferPool -> (Buffer -> Int -> IO Int) -> IO (ByteString, Int)
forall r.
BufferPool -> (Buffer -> Int -> IO r) -> IO (ByteString, r)
applyBufferPool BufferPool
pool Buffer -> Int -> IO Int
f
if Int
consumed Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
then do
IORef ByteString -> ByteString -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef ByteString
ref ByteString
buf
Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ByteString
forall a. Maybe a
Nothing
else do
IORef ByteString -> ByteString -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef ByteString
ref (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.drop Int
consumed ByteString
buf
Maybe ByteString -> IO (Maybe ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ByteString -> IO (Maybe ByteString))
-> Maybe ByteString -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.take Int
consumed ByteString
buf
eitherWithBufferPool
:: BufferPool
-> (Buffer -> BufSize -> IO (Either a Int))
-> IO (Either a ByteString)
eitherWithBufferPool :: forall a.
BufferPool
-> (Buffer -> Int -> IO (Either a Int)) -> IO (Either a ByteString)
eitherWithBufferPool pool :: BufferPool
pool@(BufferPool Int
_ Int
_ IORef ByteString
ref) Buffer -> Int -> IO (Either a Int)
f = do
(ByteString
buf, Either a Int
r) <- BufferPool
-> (Buffer -> Int -> IO (Either a Int))
-> IO (ByteString, Either a Int)
forall r.
BufferPool -> (Buffer -> Int -> IO r) -> IO (ByteString, r)
applyBufferPool BufferPool
pool Buffer -> Int -> IO (Either a Int)
f
case Either a Int
r of
Left a
a -> do
IORef ByteString -> ByteString -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef ByteString
ref ByteString
buf
Either a ByteString -> IO (Either a ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either a ByteString -> IO (Either a ByteString))
-> Either a ByteString -> IO (Either a ByteString)
forall a b. (a -> b) -> a -> b
$ a -> Either a ByteString
forall a b. a -> Either a b
Left a
a
Right Int
consumed -> do
IORef ByteString -> ByteString -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef ByteString
ref (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.drop Int
consumed ByteString
buf
Either a ByteString -> IO (Either a ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either a ByteString -> IO (Either a ByteString))
-> Either a ByteString -> IO (Either a ByteString)
forall a b. (a -> b) -> a -> b
$ ByteString -> Either a ByteString
forall a b. b -> Either a b
Right (ByteString -> Either a ByteString)
-> ByteString -> Either a ByteString
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
BS.take Int
consumed ByteString
buf
applyBufferPool
:: BufferPool -> (Buffer -> BufSize -> IO r) -> IO (ByteString, r)
applyBufferPool :: forall r.
BufferPool -> (Buffer -> Int -> IO r) -> IO (ByteString, r)
applyBufferPool (BufferPool Int
l Int
h IORef ByteString
ref) Buffer -> Int -> IO r
f = do
ByteString
buf0 <- IORef ByteString -> IO ByteString
forall a. IORef a -> IO a
readIORef IORef ByteString
ref
ByteString
buf <-
if ByteString -> Int
BS.length ByteString
buf0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
l
then ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
buf0
else Int -> IO ByteString
mallocBS Int
h
r
consumed <- ByteString -> (Buffer -> Int -> IO r) -> IO r
forall r. ByteString -> (Buffer -> Int -> IO r) -> IO r
withForeignBuffer ByteString
buf Buffer -> Int -> IO r
f
(ByteString, r) -> IO (ByteString, r)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
buf, r
consumed)
withForeignBuffer :: ByteString -> (Buffer -> BufSize -> IO r) -> IO r
withForeignBuffer :: forall r. ByteString -> (Buffer -> Int -> IO r) -> IO r
withForeignBuffer (PS ForeignPtr Word8
ps Int
s Int
l) Buffer -> Int -> IO r
f = ForeignPtr Word8 -> (Buffer -> IO r) -> IO r
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
ps ((Buffer -> IO r) -> IO r) -> (Buffer -> IO r) -> IO r
forall a b. (a -> b) -> a -> b
$ \Buffer
p -> Buffer -> Int -> IO r
f (Buffer -> Ptr Any
forall a b. Ptr a -> Ptr b
castPtr Buffer
p Ptr Any -> Int -> Buffer
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
s) Int
l
{-# INLINE withForeignBuffer #-}
mallocBS :: Int -> IO ByteString
mallocBS :: Int -> IO ByteString
mallocBS Int
size = do
Buffer
ptr <- Int -> IO Buffer
forall a. Int -> IO (Ptr a)
mallocBytes Int
size
ForeignPtr Word8
fptr <- FinalizerPtr Word8 -> Buffer -> IO (ForeignPtr Word8)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr Word8
forall a. FinalizerPtr a
finalizerFree Buffer
ptr
ByteString -> IO ByteString
forall a. a -> IO a
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
PS ForeignPtr Word8
fptr Int
0 Int
size
{-# INLINE mallocBS #-}
copy :: Buffer -> ByteString -> IO Buffer
copy :: Buffer -> ByteString -> IO Buffer
copy Buffer
ptr (PS ForeignPtr Word8
fp Int
o Int
l) = ForeignPtr Word8 -> (Buffer -> IO Buffer) -> IO Buffer
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp ((Buffer -> IO Buffer) -> IO Buffer)
-> (Buffer -> IO Buffer) -> IO Buffer
forall a b. (a -> b) -> a -> b
$ \Buffer
p -> do
Buffer -> Buffer -> Int -> IO ()
forall a. Ptr a -> Ptr a -> Int -> IO ()
copyBytes Buffer
ptr (Buffer
p Buffer -> Int -> Buffer
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
o) (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)
Buffer -> IO Buffer
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Buffer -> IO Buffer) -> Buffer -> IO Buffer
forall a b. (a -> b) -> a -> b
$ Buffer
ptr Buffer -> Int -> Buffer
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
l
{-# INLINE copy #-}