module Network.HTTP2.Arch.ReadN where
import qualified Data.ByteString as B
import Data.IORef
import Network.Socket
import qualified Network.Socket.ByteString as N
defaultReadN :: Socket -> IORef (Maybe B.ByteString) -> Int -> IO B.ByteString
defaultReadN :: Socket -> IORef (Maybe ByteString) -> Int -> IO ByteString
defaultReadN Socket
_ IORef (Maybe ByteString)
_ Int
0 = forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
B.empty
defaultReadN Socket
s IORef (Maybe ByteString)
ref Int
n = do
Maybe ByteString
mbs <- forall a. IORef a -> IO a
readIORef IORef (Maybe ByteString)
ref
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe ByteString)
ref forall a. Maybe a
Nothing
case Maybe ByteString
mbs of
Maybe ByteString
Nothing -> do
ByteString
bs <- Socket -> Int -> IO ByteString
N.recv Socket
s Int
n
if ByteString -> Bool
B.null ByteString
bs then
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
B.empty
else if ByteString -> Int
B.length ByteString
bs forall a. Eq a => a -> a -> Bool
== Int
n then
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs
else
ByteString -> IO ByteString
loop ByteString
bs
Just ByteString
bs
| ByteString -> Int
B.length ByteString
bs forall a. Eq a => a -> a -> Bool
== Int
n -> forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs
| ByteString -> Int
B.length ByteString
bs forall a. Ord a => a -> a -> Bool
> Int
n -> do
let (ByteString
bs0, ByteString
bs1) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
n ByteString
bs
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe ByteString)
ref (forall a. a -> Maybe a
Just ByteString
bs1)
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs0
| Bool
otherwise -> ByteString -> IO ByteString
loop ByteString
bs
where
loop :: ByteString -> IO ByteString
loop ByteString
bs = do
let n' :: Int
n' = Int
n forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
bs
ByteString
bs1 <- Socket -> Int -> IO ByteString
N.recv Socket
s Int
n'
if ByteString -> Bool
B.null ByteString
bs1 then
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
B.empty
else do
let bs2 :: ByteString
bs2 = ByteString
bs ByteString -> ByteString -> ByteString
`B.append` ByteString
bs1
if ByteString -> Int
B.length ByteString
bs2 forall a. Eq a => a -> a -> Bool
== Int
n then
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
bs2
else
ByteString -> IO ByteString
loop ByteString
bs2