{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
module System.Posix.IO.ByteString.Ext.Lazy
(
fdRead
, fdPread
, fdWrites
, fdWritev
) where
import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BSU
import qualified System.Posix.IO.ByteString.Ext as PosixBS
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Internal as BLI
import System.Posix.Types (Fd, ByteCount, FileOffset)
fdRead
:: Fd
-> ByteCount
-> IO BL.ByteString
fdRead :: Fd -> ByteCount -> IO ByteString
fdRead Fd
fd ByteCount
nbytes
| ByteCount
nbytes ByteCount -> ByteCount -> Bool
forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BL.empty
| Bool
otherwise = do
ByteString
s <- Fd -> ByteCount -> IO ByteString
PosixBS.fdRead Fd
fd ByteCount
nbytes
ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString -> ByteString
BLI.chunk ByteString
s ByteString
BL.empty)
fdPread
:: Fd
-> ByteCount
-> FileOffset
-> IO BL.ByteString
fdPread :: Fd -> ByteCount -> FileOffset -> IO ByteString
fdPread Fd
fd ByteCount
nbytes FileOffset
offset
| ByteCount
nbytes ByteCount -> ByteCount -> Bool
forall a. Ord a => a -> a -> Bool
<= ByteCount
0 = ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
BL.empty
| Bool
otherwise = do
ByteString
s <- Fd -> ByteCount -> FileOffset -> IO ByteString
PosixBS.fdPread Fd
fd ByteCount
nbytes FileOffset
offset
ByteString -> IO ByteString
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> ByteString -> ByteString
BLI.chunk ByteString
s ByteString
BL.empty)
fdWrites
:: Fd
-> BL.ByteString
-> IO (ByteCount, BL.ByteString)
fdWrites :: Fd -> ByteString -> IO (ByteCount, ByteString)
fdWrites Fd
fd = ByteCount -> ByteString -> IO (ByteCount, ByteString)
go ByteCount
0
where
go :: ByteCount -> ByteString -> IO (ByteCount, ByteString)
go ByteCount
acc ByteString
BLI.Empty = (ByteCount, ByteString) -> IO (ByteCount, ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteCount
acc, ByteString
BL.empty)
go ByteCount
acc (BLI.Chunk ByteString
c ByteString
cs) =
Fd -> ByteString -> IO ByteCount
PosixBS.fdWrite Fd
fd ByteString
c IO ByteCount
-> (ByteCount -> IO (ByteCount, ByteString))
-> IO (ByteCount, ByteString)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ByteCount
rc ->
let acc' :: ByteCount
acc' = ByteCount
accByteCount -> ByteCount -> ByteCount
forall a. Num a => a -> a -> a
+ByteCount
rc in ByteCount
acc' ByteCount
-> IO (ByteCount, ByteString) -> IO (ByteCount, ByteString)
forall a b. a -> b -> b
`seq`
let rcInt :: Int
rcInt = ByteCount -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral ByteCount
rc in Int
rcInt Int -> IO (ByteCount, ByteString) -> IO (ByteCount, ByteString)
forall a b. a -> b -> b
`seq`
if Int
rcInt Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString -> Int
BS.length ByteString
c
then ByteCount -> ByteString -> IO (ByteCount, ByteString)
go ByteCount
acc' ByteString
cs
else (ByteCount, ByteString) -> IO (ByteCount, ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteCount
acc', ByteString -> ByteString -> ByteString
BLI.Chunk (Int -> ByteString -> ByteString
BSU.unsafeDrop Int
rcInt ByteString
c) ByteString
cs)
fdWritev
:: Fd
-> BL.ByteString
-> IO ByteCount
fdWritev :: Fd -> ByteString -> IO ByteCount
fdWritev Fd
fd ByteString
s = Fd -> [ByteString] -> IO ByteCount
PosixBS.fdWritev Fd
fd (ByteString -> [ByteString]
BL.toChunks ByteString
s)
{-# INLINE fdWritev #-}