{-# LINE 1 "src/System/Posix/ByteLevel.hsc" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module System.Posix.ByteLevel (fdWrite, fdWriteB, writeAllB, writeAllL) where

import Control.Applicative ((<$>))
import Control.Monad (unless)
import qualified Data.ByteString as Strict
import Data.ByteString.Lazy (ByteString, toChunks)
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Function (fix)
import Foreign.C.Error (throwErrnoIfMinus1Retry)
import Foreign.C.String (CString, CStringLen)
import Foreign.C.Types (CInt(..), CSize(..))
import System.Posix.Types (ByteCount, Fd(..))



foreign import ccall "write"
       c_write :: CInt -> CString -> CSize -> IO CSize

fdWrite :: Fd -> CStringLen -> IO ByteCount
fdWrite :: Fd -> CStringLen -> IO ByteCount
fdWrite (Fd fd :: CInt
fd) (cs :: Ptr CChar
cs, l :: Int
l) =  String -> IO ByteCount -> IO ByteCount
forall a. (Eq a, Num a) => String -> IO a -> IO a
throwErrnoIfMinus1Retry "write" (IO ByteCount -> IO ByteCount)
-> (ByteCount -> IO ByteCount) -> ByteCount -> IO ByteCount
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CInt -> Ptr CChar -> ByteCount -> IO ByteCount
c_write CInt
fd Ptr CChar
cs (ByteCount -> IO ByteCount) -> ByteCount -> IO ByteCount
forall a b. (a -> b) -> a -> b
$ Int -> ByteCount
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l

fdWriteB :: Fd -> Strict.ByteString -> IO Int
fdWriteB :: Fd -> ByteString -> IO Int
fdWriteB fd :: Fd
fd bs :: ByteString
bs = ByteCount -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (ByteCount -> Int) -> IO ByteCount -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> (CStringLen -> IO ByteCount) -> IO ByteCount
forall a. ByteString -> (CStringLen -> IO a) -> IO a
unsafeUseAsCStringLen ByteString
bs (Fd -> CStringLen -> IO ByteCount
fdWrite Fd
fd)

-- | Write the entire contents of the strict bytestring. Assumes blocking mode.
writeAllB :: Fd -> Strict.ByteString -> IO ()
writeAllB :: Fd -> ByteString -> IO ()
writeAllB fd :: Fd
fd = ((ByteString -> IO ()) -> ByteString -> IO ())
-> ByteString -> IO ()
forall a. (a -> a) -> a
fix (((ByteString -> IO ()) -> ByteString -> IO ())
 -> ByteString -> IO ())
-> ((ByteString -> IO ()) -> ByteString -> IO ())
-> ByteString
-> IO ()
forall a b. (a -> b) -> a -> b
$ \me :: ByteString -> IO ()
me s :: ByteString
s -> Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString -> Bool
Strict.null ByteString
s) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    Int
count <- Fd -> ByteString -> IO Int
fdWriteB Fd
fd ByteString
s
    ByteString -> IO ()
me (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> ByteString -> ByteString
Strict.drop (Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
count) ByteString
s

-- | Write the entire contents of the lazy bytestring. Assumes blocking mode.
writeAllL :: Fd -> ByteString -> IO ()
writeAllL :: Fd -> ByteString -> IO ()
writeAllL fd :: Fd
fd = (ByteString -> IO ()) -> [ByteString] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Fd -> ByteString -> IO ()
writeAllB Fd
fd) ([ByteString] -> IO ())
-> (ByteString -> [ByteString]) -> ByteString -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
toChunks