{-# LINE 1 "src/Unix/IOVec.hsc" #-}
{-# LANGUAGE NamedFieldPuns #-}
module Unix.IOVec
    ( CIOVec(..)
    , unsafeFromByteString
    ) where

import Foreign.C.Types
import Foreign.Ptr
import Foreign.ForeignPtr
import Foreign.Storable
import System.IO.Unsafe (unsafePerformIO)
import Zhp
import qualified Data.ByteString.Internal as BS



data CIOVec = CIOVec
    { CIOVec -> Ptr Word8
iovBase :: !(Ptr Word8)
    , CIOVec -> CSize
iovLen :: !CSize
    }

-- | Unsafe O(1) conversion from a bytestring. This is unsafe in two
-- respects:
--
-- 1. Since the underlying storage is shared with the original bytestring,
--    if the CIOVec is mutated, then the bytestring will be as well, violating
--    referential transparency.
-- 2. Holding a reference to the CIOVec does not keep the underlying storage
--    from being garbage collected, so you must use touchForeignPtr on the
--    underlying foreign pointer after the last use of the CIOVec.
unsafeFromByteString :: BS.ByteString -> CIOVec
unsafeFromByteString :: ByteString -> CIOVec
unsafeFromByteString ByteString
bs =
    let (ForeignPtr Word8
fptr, Int
off, Int
len) = ByteString -> (ForeignPtr Word8, Int, Int)
BS.toForeignPtr ByteString
bs in
    IO CIOVec -> CIOVec
forall a. IO a -> a
unsafePerformIO (IO CIOVec -> CIOVec) -> IO CIOVec -> CIOVec
forall a b. (a -> b) -> a -> b
$ ForeignPtr Word8 -> (Ptr Word8 -> IO CIOVec) -> IO CIOVec
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fptr ((Ptr Word8 -> IO CIOVec) -> IO CIOVec)
-> (Ptr Word8 -> IO CIOVec) -> IO CIOVec
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr ->
        CIOVec -> IO CIOVec
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CIOVec -> IO CIOVec) -> CIOVec -> IO CIOVec
forall a b. (a -> b) -> a -> b
$ CIOVec :: Ptr Word8 -> CSize -> CIOVec
CIOVec { iovBase :: Ptr Word8
iovBase = Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
off, iovLen :: CSize
iovLen = Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len }

instance Storable CIOVec where
    alignment :: CIOVec -> Int
alignment CIOVec
_ = Int
8
{-# LINE 39 "src/Unix/IOVec.hsc" #-}
    sizeOf _ = (16)
{-# LINE 40 "src/Unix/IOVec.hsc" #-}
    peek ptr = do
        iovBase <- (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 42 "src/Unix/IOVec.hsc" #-}
        iovLen <- (\hsc_ptr -> peekByteOff hsc_ptr 8) ptr
{-# LINE 43 "src/Unix/IOVec.hsc" #-}
        pure CIOVec {iovBase, iovLen}
    poke :: Ptr CIOVec -> CIOVec -> IO ()
poke Ptr CIOVec
ptr CIOVec
v = do
        (\Ptr CIOVec
hsc_ptr -> Ptr CIOVec -> Int -> Ptr Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr CIOVec
hsc_ptr Int
0) Ptr CIOVec
ptr (CIOVec -> Ptr Word8
iovBase CIOVec
v)
{-# LINE 46 "src/Unix/IOVec.hsc" #-}
        (\Ptr CIOVec
hsc_ptr -> Ptr CIOVec -> Int -> CSize -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr CIOVec
hsc_ptr Int
8) Ptr CIOVec
ptr (CIOVec -> CSize
iovLen CIOVec
v)
{-# LINE 47 "src/Unix/IOVec.hsc" #-}