packages feed

Z-IO 0.1.4.0 → 0.1.5.0

raw patch · 18 files changed

+1123/−362 lines, 18 filesdep ~Z-DataPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: Z-Data

API changes (from Hackage documentation)

- Z.IO.Environment: getPriority :: HasCallStack => PID -> IO CInt
- Z.IO.Environment: pattern PRIORITY_ABOVE_NORMAL :: CInt
- Z.IO.Environment: pattern PRIORITY_BELOW_NORMAL :: CInt
- Z.IO.Environment: pattern PRIORITY_HIGH :: CInt
- Z.IO.Environment: pattern PRIORITY_HIGHEST :: CInt
- Z.IO.Environment: pattern PRIORITY_LOW :: CInt
- Z.IO.Environment: pattern PRIORITY_NORMAL :: CInt
- Z.IO.Environment: setPriority :: HasCallStack => PID -> CInt -> IO ()
- Z.IO.FileSystem: data AccessMode
- Z.IO.FileSystem: data CopyFileFlag
- Z.IO.FileSystem: data FileFlag
- Z.IO.FileSystem: data FileMode
- Z.IO.FileSystem: data SymlinkFlag
- Z.IO.FileSystem.Threaded: data AccessMode
- Z.IO.FileSystem.Threaded: data CopyFileFlag
- Z.IO.FileSystem.Threaded: data FileFlag
- Z.IO.FileSystem.Threaded: data FileMode
- Z.IO.FileSystem.Threaded: data SymlinkFlag
- Z.IO.Network.IPC: [ipcServerWorker] :: IPCServerConfig -> UVStream -> IO ()
- Z.IO.Network.TCP: echoWorker :: UVStream -> IO ()
- Z.IO.Network.TCP: helloWorldWorker :: UVStream -> IO ()
- Z.IO.Network.UDP: data Membership
- Z.IO.Network.UDP: data UDPFlag
- Z.IO.StdStream: data TTYMode
- Z.IO.UV.FFI: AccessMode :: CInt -> AccessMode
- Z.IO.UV.FFI: CopyFileFlag :: CInt -> CopyFileFlag
- Z.IO.UV.FFI: FileFlag :: CInt -> FileFlag
- Z.IO.UV.FFI: FileMode :: CInt -> FileMode
- Z.IO.UV.FFI: Membership :: CInt -> Membership
- Z.IO.UV.FFI: SymlinkFlag :: CInt -> SymlinkFlag
- Z.IO.UV.FFI: TTYMode :: CInt -> TTYMode
- Z.IO.UV.FFI: UDPFlag :: CInt -> UDPFlag
- Z.IO.UV.FFI: UVDirEntType :: CChar -> UVDirEntType
- Z.IO.UV.FFI: UVHandleType :: CInt -> UVHandleType
- Z.IO.UV.FFI: UVRunMode :: CInt -> UVRunMode
- Z.IO.UV.FFI: data UVDirEnt
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Data.Bits.Bits Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Data.Bits.FiniteBits Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.UVRunMode
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.UVRunMode
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.UVRunMode
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance GHC.Num.Num Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.UVRunMode
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.AccessMode
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.CopyFileFlag
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.FileFlag
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.FileMode
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.Membership
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.SymlinkFlag
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.TTYMode
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.UDPFlag
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.UVDirEntType
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.UVHandleType
- Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.UVRunMode
- Z.IO.UV.FFI: newtype AccessMode
- Z.IO.UV.FFI: newtype CopyFileFlag
- Z.IO.UV.FFI: newtype FileFlag
- Z.IO.UV.FFI: newtype FileMode
- Z.IO.UV.FFI: newtype Membership
- Z.IO.UV.FFI: newtype SymlinkFlag
- Z.IO.UV.FFI: newtype TTYMode
- Z.IO.UV.FFI: newtype UDPFlag
- Z.IO.UV.FFI: newtype UVDirEntType
- Z.IO.UV.FFI: newtype UVHandleType
- Z.IO.UV.FFI: newtype UVRunMode
- Z.IO.UV.FFI: uV__DT_BLOCK :: UVDirEntType
- Z.IO.UV.FFI: uV__DT_CHAR :: UVDirEntType
- Z.IO.UV.FFI: uV__DT_DIR :: UVDirEntType
- Z.IO.UV.FFI: uV__DT_FIFO :: UVDirEntType
- Z.IO.UV.FFI: uV__DT_FILE :: UVDirEntType
- Z.IO.UV.FFI: uV__DT_LINK :: UVDirEntType
- Z.IO.UV.FFI: uV__DT_SOCKET :: UVDirEntType
- Z.IO.UV.Manager: UVStream :: {-# UNPACK #-} !Ptr UVHandle -> {-# UNPACK #-} !UVSlot -> UVManager -> {-# UNPACK #-} !IORef Bool -> UVStream
- Z.IO.UV.Manager: [uvsClosed] :: UVStream -> {-# UNPACK #-} !IORef Bool
- Z.IO.UV.Manager: [uvsHandle] :: UVStream -> {-# UNPACK #-} !Ptr UVHandle
- Z.IO.UV.Manager: [uvsManager] :: UVStream -> UVManager
- Z.IO.UV.Manager: [uvsSlot] :: UVStream -> {-# UNPACK #-} !UVSlot
- Z.IO.UV.Manager: data UVStream
- Z.IO.UV.Manager: initUVStream :: HasCallStack => (Ptr UVLoop -> Ptr UVHandle -> IO ()) -> UVManager -> Resource UVStream
- Z.IO.UV.Manager: instance GHC.Show.Show Z.IO.UV.Manager.UVStream
- Z.IO.UV.Manager: instance Z.IO.Buffered.Input Z.IO.UV.Manager.UVStream
- Z.IO.UV.Manager: instance Z.IO.Buffered.Output Z.IO.UV.Manager.UVStream
+ Z.IO.FileSystem: getFileFD :: File -> IO UVFD
+ Z.IO.FileSystem: pattern COPYFILE_FICLONE_FORCE :: CopyFileFlag
+ Z.IO.FileSystem: type AccessMode = CInt
+ Z.IO.FileSystem: type CopyFileFlag = CInt
+ Z.IO.FileSystem: type FileFlag = CInt
+ Z.IO.FileSystem: type FileMode = CInt
+ Z.IO.FileSystem: type SymlinkFlag = CInt
+ Z.IO.FileSystem.Threaded: getFileTFD :: FileT -> IO UVFD
+ Z.IO.FileSystem.Threaded: pattern COPYFILE_FICLONE_FORCE :: CopyFileFlag
+ Z.IO.FileSystem.Threaded: type AccessMode = CInt
+ Z.IO.FileSystem.Threaded: type CopyFileFlag = CInt
+ Z.IO.FileSystem.Threaded: type FileFlag = CInt
+ Z.IO.FileSystem.Threaded: type FileMode = CInt
+ Z.IO.FileSystem.Threaded: type SymlinkFlag = CInt
+ Z.IO.Network.IPC: echo :: UVStream -> IO ()
+ Z.IO.Network.IPC: helloWorld :: UVStream -> IO ()
+ Z.IO.Network.IPC: initIPCStream :: HasCallStack => UVManager -> Resource UVStream
+ Z.IO.Network.TCP: echo :: UVStream -> IO ()
+ Z.IO.Network.TCP: helloWorld :: UVStream -> IO ()
+ Z.IO.Network.UDP: type Membership = CInt
+ Z.IO.Network.UDP: type UDPFlag = CInt
+ Z.IO.Process: ExitFailure :: Int -> ExitCode
+ Z.IO.Process: ExitSuccess :: ExitCode
+ Z.IO.Process: ProcessCreate :: ProcessStdStream
+ Z.IO.Process: ProcessExited :: ExitCode -> ProcessState
+ Z.IO.Process: ProcessIgnore :: ProcessStdStream
+ Z.IO.Process: ProcessInherit :: UVFD -> ProcessStdStream
+ Z.IO.Process: ProcessOptions :: CBytes -> [CBytes] -> Maybe [(CBytes, CBytes)] -> CBytes -> ProcessFlag -> UID -> GID -> (ProcessStdStream, ProcessStdStream, ProcessStdStream) -> ProcessOptions
+ Z.IO.Process: ProcessRunning :: PID -> ProcessState
+ Z.IO.Process: [processArgs] :: ProcessOptions -> [CBytes]
+ Z.IO.Process: [processCWD] :: ProcessOptions -> CBytes
+ Z.IO.Process: [processEnv] :: ProcessOptions -> Maybe [(CBytes, CBytes)]
+ Z.IO.Process: [processFile] :: ProcessOptions -> CBytes
+ Z.IO.Process: [processFlags] :: ProcessOptions -> ProcessFlag
+ Z.IO.Process: [processGID] :: ProcessOptions -> GID
+ Z.IO.Process: [processStdStreams] :: ProcessOptions -> (ProcessStdStream, ProcessStdStream, ProcessStdStream)
+ Z.IO.Process: [processUID] :: ProcessOptions -> UID
+ Z.IO.Process: data ExitCode
+ Z.IO.Process: data ProcessOptions
+ Z.IO.Process: data ProcessState
+ Z.IO.Process: data ProcessStdStream
+ Z.IO.Process: defaultProcessOptions :: ProcessOptions
+ Z.IO.Process: getPriority :: HasCallStack => PID -> IO Priority
+ Z.IO.Process: getProcessPID :: TVar ProcessState -> IO (Maybe PID)
+ Z.IO.Process: initProcess :: ProcessOptions -> Resource (Maybe UVStream, Maybe UVStream, Maybe UVStream, TVar ProcessState)
+ Z.IO.Process: instance GHC.Classes.Eq Z.IO.Process.ProcessState
+ Z.IO.Process: instance GHC.Classes.Ord Z.IO.Process.ProcessState
+ Z.IO.Process: instance GHC.Generics.Generic Z.IO.Process.ProcessState
+ Z.IO.Process: instance GHC.Show.Show Z.IO.Process.ProcessState
+ Z.IO.Process: instance Z.Data.JSON.Base.EncodeJSON Z.IO.Process.ProcessState
+ Z.IO.Process: instance Z.Data.JSON.Base.FromValue Z.IO.Process.ProcessState
+ Z.IO.Process: instance Z.Data.JSON.Base.ToValue Z.IO.Process.ProcessState
+ Z.IO.Process: instance Z.Data.Text.ShowT.ShowT Z.IO.Process.ProcessState
+ Z.IO.Process: killPID :: HasCallStack => PID -> Signal -> IO ()
+ Z.IO.Process: pattern PRIORITY_ABOVE_NORMAL :: Priority
+ Z.IO.Process: pattern PRIORITY_BELOW_NORMAL :: Priority
+ Z.IO.Process: pattern PRIORITY_HIGH :: Priority
+ Z.IO.Process: pattern PRIORITY_HIGHEST :: Priority
+ Z.IO.Process: pattern PRIORITY_LOW :: Priority
+ Z.IO.Process: pattern PRIORITY_NORMAL :: Priority
+ Z.IO.Process: pattern SIGHUP :: Signal
+ Z.IO.Process: pattern SIGINT :: Signal
+ Z.IO.Process: pattern SIGKILL :: Signal
+ Z.IO.Process: pattern SIGTERM :: Signal
+ Z.IO.Process: readProcess :: HasCallStack => ProcessOptions -> Bytes -> IO (Bytes, Bytes, ExitCode)
+ Z.IO.Process: readProcessText :: HasCallStack => ProcessOptions -> Text -> IO (Text, Text, ExitCode)
+ Z.IO.Process: setPriority :: HasCallStack => PID -> Priority -> IO ()
+ Z.IO.Process: spawn :: HasCallStack => ProcessOptions -> IO (Maybe UVStream, Maybe UVStream, Maybe UVStream, TVar ProcessState)
+ Z.IO.Process: type Priority = CInt
+ Z.IO.Process: type Signal = CInt
+ Z.IO.Process: waitProcessExit :: TVar ProcessState -> IO ExitCode
+ Z.IO.StdStream: getStdStreamFD :: StdStream -> IO UVFD
+ Z.IO.StdStream: type TTYMode = CInt
+ Z.IO.StdStream: withMVar :: () => MVar a -> (a -> IO b) -> IO b
+ Z.IO.UV.FFI: GID :: Word32 -> GID
+ Z.IO.UV.FFI: ProcessCreate :: ProcessStdStream
+ Z.IO.UV.FFI: ProcessIgnore :: ProcessStdStream
+ Z.IO.UV.FFI: ProcessInherit :: UVFD -> ProcessStdStream
+ Z.IO.UV.FFI: ProcessOptions :: CBytes -> [CBytes] -> Maybe [(CBytes, CBytes)] -> CBytes -> ProcessFlag -> UID -> GID -> (ProcessStdStream, ProcessStdStream, ProcessStdStream) -> ProcessOptions
+ Z.IO.UV.FFI: UID :: Word32 -> UID
+ Z.IO.UV.FFI: [processArgs] :: ProcessOptions -> [CBytes]
+ Z.IO.UV.FFI: [processCWD] :: ProcessOptions -> CBytes
+ Z.IO.UV.FFI: [processEnv] :: ProcessOptions -> Maybe [(CBytes, CBytes)]
+ Z.IO.UV.FFI: [processFile] :: ProcessOptions -> CBytes
+ Z.IO.UV.FFI: [processFlags] :: ProcessOptions -> ProcessFlag
+ Z.IO.UV.FFI: [processGID] :: ProcessOptions -> GID
+ Z.IO.UV.FFI: [processStdStreams] :: ProcessOptions -> (ProcessStdStream, ProcessStdStream, ProcessStdStream)
+ Z.IO.UV.FFI: [processUID] :: ProcessOptions -> UID
+ Z.IO.UV.FFI: data ProcessOptions
+ Z.IO.UV.FFI: data ProcessStdStream
+ Z.IO.UV.FFI: hs_uv_spawn :: Ptr UVLoop -> MBA# ProcessOptions -> BA# Word8 -> BA# Word8 -> CSize -> BA# Word8 -> CSsize -> BA# Word8 -> MBA# ProcessStdStream -> IO Int
+ Z.IO.UV.FFI: instance Data.Primitive.Types.Prim Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Data.Primitive.Types.Prim Z.IO.UV.FFI.PID
+ Z.IO.UV.FFI: instance Data.Primitive.Types.Prim Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Foreign.Storable.Storable Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.ProcessOptions
+ Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.ProcessStdStream
+ Z.IO.UV.FFI: instance GHC.Classes.Eq Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.ProcessOptions
+ Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.ProcessStdStream
+ Z.IO.UV.FFI: instance GHC.Classes.Ord Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance GHC.Enum.Enum Z.IO.UV.FFI.AccessResult
+ Z.IO.UV.FFI: instance GHC.Enum.Enum Z.IO.UV.FFI.DirEntType
+ Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.ProcessOptions
+ Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.ProcessStdStream
+ Z.IO.UV.FFI: instance GHC.Generics.Generic Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.ProcessOptions
+ Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.ProcessStdStream
+ Z.IO.UV.FFI: instance GHC.Show.Show Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Z.Data.Array.Unaligned.Unaligned Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Z.Data.JSON.Base.EncodeJSON Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Z.Data.JSON.Base.FromValue Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Z.Data.JSON.Base.ToValue Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.GID
+ Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.ProcessOptions
+ Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.ProcessStdStream
+ Z.IO.UV.FFI: instance Z.Data.Text.ShowT.ShowT Z.IO.UV.FFI.UID
+ Z.IO.UV.FFI: newtype GID
+ Z.IO.UV.FFI: newtype UID
+ Z.IO.UV.FFI: pattern COPYFILE_FICLONE_FORCE :: CopyFileFlag
+ Z.IO.UV.FFI: pattern PROCESS_DETACHED :: ProcessFlag
+ Z.IO.UV.FFI: pattern PROCESS_SETGID :: ProcessFlag
+ Z.IO.UV.FFI: pattern PROCESS_SETUID :: ProcessFlag
+ Z.IO.UV.FFI: pattern PROCESS_WINDOWS_HIDE :: ProcessFlag
+ Z.IO.UV.FFI: pattern PROCESS_WINDOWS_HIDE_CONSOLE :: ProcessFlag
+ Z.IO.UV.FFI: pattern PROCESS_WINDOWS_HIDE_GUI :: ProcessFlag
+ Z.IO.UV.FFI: pattern PROCESS_WINDOWS_VERBATIM_ARGUMENTS :: ProcessFlag
+ Z.IO.UV.FFI: processStdStreamFlag :: ProcessStdStream -> CInt
+ Z.IO.UV.FFI: type AccessMode = CInt
+ Z.IO.UV.FFI: type CopyFileFlag = CInt
+ Z.IO.UV.FFI: type FileFlag = CInt
+ Z.IO.UV.FFI: type FileMode = CInt
+ Z.IO.UV.FFI: type Membership = CInt
+ Z.IO.UV.FFI: type Priority = CInt
+ Z.IO.UV.FFI: type ProcessFlag = CUInt
+ Z.IO.UV.FFI: type SymlinkFlag = CInt
+ Z.IO.UV.FFI: type TTYMode = CInt
+ Z.IO.UV.FFI: type UDPFlag = CInt
+ Z.IO.UV.FFI: type UVDirEntType = CChar
+ Z.IO.UV.FFI: type UVHandleType = CInt
+ Z.IO.UV.FFI: type UVRunMode = CInt
+ Z.IO.UV.FFI: uv_kill :: CInt -> CInt -> IO CInt
+ Z.IO.UV.UVStream: UVStream :: {-# UNPACK #-} !Ptr UVHandle -> {-# UNPACK #-} !UVSlot -> UVManager -> {-# UNPACK #-} !IORef Bool -> UVStream
+ Z.IO.UV.UVStream: [uvsClosed] :: UVStream -> {-# UNPACK #-} !IORef Bool
+ Z.IO.UV.UVStream: [uvsHandle] :: UVStream -> {-# UNPACK #-} !Ptr UVHandle
+ Z.IO.UV.UVStream: [uvsManager] :: UVStream -> UVManager
+ Z.IO.UV.UVStream: [uvsSlot] :: UVStream -> {-# UNPACK #-} !UVSlot
+ Z.IO.UV.UVStream: closeUVStream :: UVStream -> IO ()
+ Z.IO.UV.UVStream: data UVStream
+ Z.IO.UV.UVStream: echo :: UVStream -> IO ()
+ Z.IO.UV.UVStream: getUVStreamFD :: HasCallStack => UVStream -> IO UVFD
+ Z.IO.UV.UVStream: helloWorld :: UVStream -> IO ()
+ Z.IO.UV.UVStream: initUVStream :: HasCallStack => (Ptr UVLoop -> Ptr UVHandle -> IO ()) -> UVManager -> Resource UVStream
+ Z.IO.UV.UVStream: instance GHC.Show.Show Z.IO.UV.UVStream.UVStream
+ Z.IO.UV.UVStream: instance Z.IO.Buffered.Input Z.IO.UV.UVStream.UVStream
+ Z.IO.UV.UVStream: instance Z.IO.Buffered.Output Z.IO.UV.UVStream.UVStream
- Z.IO.Network.IPC: IPCServerConfig :: CBytes -> Int -> (UVStream -> IO ()) -> IPCServerConfig
+ Z.IO.Network.IPC: IPCServerConfig :: CBytes -> Int -> IPCServerConfig
- Z.IO.Network.IPC: startIPCServer :: HasCallStack => IPCServerConfig -> IO ()
+ Z.IO.Network.IPC: startIPCServer :: HasCallStack => IPCServerConfig -> (UVStream -> IO ()) -> IO ()
- Z.IO.UV.FFI: hs_uv_fs_scandir :: BA# Word8 -> MBA# (Ptr UVDirEnt) -> IO Int
+ Z.IO.UV.FFI: hs_uv_fs_scandir :: BA# Word8 -> MBA# (Ptr DirEntType) -> IO Int
- Z.IO.UV.FFI: hs_uv_fs_scandir_cleanup :: Ptr (Ptr UVDirEnt) -> Int -> IO ()
+ Z.IO.UV.FFI: hs_uv_fs_scandir_cleanup :: Ptr (Ptr DirEntType) -> Int -> IO ()
- Z.IO.UV.FFI: hs_uv_fs_scandir_extra_cleanup :: Ptr (Ptr (Ptr UVDirEnt)) -> Int -> IO ()
+ Z.IO.UV.FFI: hs_uv_fs_scandir_extra_cleanup :: Ptr (Ptr (Ptr DirEntType)) -> Int -> IO ()
- Z.IO.UV.FFI: hs_uv_fs_scandir_threaded :: BA# Word8 -> Ptr (Ptr (Ptr UVDirEnt)) -> Ptr UVLoop -> IO UVSlotUnsafe
+ Z.IO.UV.FFI: hs_uv_fs_scandir_threaded :: BA# Word8 -> Ptr (Ptr (Ptr DirEntType)) -> Ptr UVLoop -> IO UVSlotUnsafe
- Z.IO.UV.FFI: pattern PRIORITY_ABOVE_NORMAL :: CInt
+ Z.IO.UV.FFI: pattern PRIORITY_ABOVE_NORMAL :: Priority
- Z.IO.UV.FFI: pattern PRIORITY_BELOW_NORMAL :: CInt
+ Z.IO.UV.FFI: pattern PRIORITY_BELOW_NORMAL :: Priority
- Z.IO.UV.FFI: pattern PRIORITY_HIGH :: CInt
+ Z.IO.UV.FFI: pattern PRIORITY_HIGH :: Priority
- Z.IO.UV.FFI: pattern PRIORITY_HIGHEST :: CInt
+ Z.IO.UV.FFI: pattern PRIORITY_HIGHEST :: Priority
- Z.IO.UV.FFI: pattern PRIORITY_LOW :: CInt
+ Z.IO.UV.FFI: pattern PRIORITY_LOW :: Priority
- Z.IO.UV.FFI: pattern PRIORITY_NORMAL :: CInt
+ Z.IO.UV.FFI: pattern PRIORITY_NORMAL :: Priority
- Z.IO.UV.FFI: peekUVDirEnt :: Ptr UVDirEnt -> IO (CString, UVDirEntType)
+ Z.IO.UV.FFI: peekUVDirEnt :: Ptr DirEntType -> IO (CString, UVDirEntType)
- Z.IO.UV.FFI: type UVFD = Int32
+ Z.IO.UV.FFI: type UVFD = CInt

Files

ChangeLog.md view
@@ -1,5 +1,11 @@ # Revision history for Z-IO +## 0.1.5.0  -- 2020-10-02++* Add `Z.IO.Process` module.+* Move many flag type to type alias from newtype, adjust patterns haddock.+* Sync IPC's server API to TCP's.+ ## 0.1.4.0  -- 2020-10-02  * Add `Z.IO.Environment` module.
Z-IO.cabal view
@@ -1,6 +1,6 @@ cabal-version:              2.4 name:                       Z-IO-version:                    0.1.4.0+version:                    0.1.5.0 synopsis:                   Simple and high performance IO toolkit for Haskell description:                Simple and high performance IO toolkit for Haskell, including                             file system, network, ipc and more!@@ -92,20 +92,23 @@                             Z.IO.Exception                             Z.IO.LowResTimer                             Z.IO.Logger+                            Z.IO.Process                             Z.IO.Resource                             Z.IO.StdStream                              Z.IO.UV.Errno                             Z.IO.UV.FFI                             Z.IO.UV.Manager+                            Z.IO.UV.UVStream                             Z.IO.UV.Win                              Z.IO.Environment+                            Z.IO                              Z.Compression.Zlib      build-depends:          base                    >= 4.12 && <5.0-                          , Z-Data                  >= 0.1.6 && <0.1.7+                          , Z-Data                  >= 0.1.6.1 && <0.1.7                           , primitive               >= 0.7.1 && < 0.7.2                           , exceptions              == 0.10.*                           , time                    >= 1.8 && < 2.0@@ -167,6 +170,7 @@                             cbits/hs_uv_dns.c                             cbits/hs_uv_file.c                             cbits/hs_uv_stream.c+                            cbits/hs_uv_process.c                             cbits/hs_uv_udp.c                             cbits/hs_zlib.c @@ -223,7 +227,7 @@                             third_party/libuv/src/win/winapi.c                             third_party/libuv/src/win/winsock.c -        cc-options:         -Wall -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600 -O -march=native+        cc-options:         -Wall -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600 -march=native         cpp-options:        -Wall -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600         include-dirs:       third_party/libuv/include                             third_party/libuv/src@@ -272,7 +276,7 @@             include-dirs:       third_party/libuv/include                                 third_party/libuv/src/unix                                 third_party/libuv/src-            cc-options:        -Wall -O -march=native+            cc-options:        -Wall -march=native         else             if os(osx)                 c-sources:          third_party/libuv/src/fs-poll.c@@ -316,7 +320,7 @@                 include-dirs:       third_party/libuv/include                                     third_party/libuv/src/unix                                     third_party/libuv/src-                cc-options:         -Wall -O -march=native+                cc-options:         -Wall -march=native              else                 if flag(no-pkg-config)@@ -349,6 +353,7 @@                             Z.IO.Network.TCPSpec                             -- Z.IO.Network.IPCSpec                             Z.IO.LowResTimerSpec+                            Z.IO.ProcessSpec                             Z.IO.ResourceSpec      ghc-options:            -threaded
+ Z/IO.hs view
@@ -0,0 +1,29 @@+{-|+Module      : Z.IO+Description : IO Umbrella module+Copyright   : (c) Dong Han, 2017+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This re-exports several common module to be used together with file, network, and or specific module,+such as resource management, buffered IO and std streams.++-}++module Z.IO+  ( module Z.IO.Buffered+  , module Z.IO.Environment+  , module Z.IO.Exception+  , module Z.IO.Logger+  , module Z.IO.Resource+  , module Z.IO.StdStream+  ) where++import Z.IO.Buffered+import Z.IO.Environment+import Z.IO.Exception+import Z.IO.Logger+import Z.IO.Resource+import Z.IO.StdStream
Z/IO/Environment.hs view
@@ -24,13 +24,6 @@   , getHighResolutionTime   , PID(..)   , getPID, getPPID-  , getPriority, setPriority-  , pattern PRIORITY_LOW-  , pattern PRIORITY_BELOW_NORMAL-  , pattern PRIORITY_NORMAL-  , pattern PRIORITY_ABOVE_NORMAL-  , pattern PRIORITY_HIGH-  , pattern PRIORITY_HIGHEST   , getHostname   , getOSName, OSName(..)   , getRandom, getRandomT@@ -155,24 +148,6 @@ -- | Returns the parent process ID. getPPID :: IO PID getPPID = uv_os_getppid---- | Retrieves the scheduling priority of the process specified by pid.------ The returned value of priority is between -20 (high priority) and 19 (low priority).--- On Windows, the returned priority will equal one of the PRIORITY constants.-getPriority :: HasCallStack => PID -> IO CInt-getPriority pid = do-    (p, _) <- allocPrimUnsafe $ \ p_p -> throwUVIfMinus_ (uv_os_getpriority pid p_p)-    return p---- | Sets the scheduling priority of the process specified by pid.------ The priority value range is between -20 (high priority) and 19 (low priority).--- The constants 'PRIORITY_LOW', 'PRIORITY_BELOW_NORMAL', 'PRIORITY_NORMAL',--- 'PRIORITY_ABOVE_NORMAL', 'PRIORITY_HIGH', and 'PRIORITY_HIGHEST' are also provided for convenience.----setPriority :: HasCallStack => PID -> CInt -> IO ()-setPriority pid p = throwUVIfMinus_ (uv_os_setpriority pid p)  -- | Returns the hostname as a null-terminated string. --
Z/IO/FileSystem.hs view
@@ -13,17 +13,9 @@  module Z.IO.FileSystem   ( -- * regular file devices-    File, initFile, readFile, writeFile+    File, initFile, readFile, writeFile, getFileFD     -- * file offset bundle   , FilePtr, newFilePtr, getFileOffset, setFileOffset-    -- * opening constant-  , FileMode(DEFAULT_MODE, S_IRWXU, S_IRUSR, S_IWUSR-      , S_IXUSR, S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH-      )-  , FileFlag(O_APPEND, O_CREAT, O_DIRECT, O_DSYNC, O_EXCL-      , O_EXLOCK, O_NOATIME, O_NOFOLLOW, O_RDONLY, O_RDWR, O_SYMLINK-      , O_SYNC, O_TRUNC, O_WRONLY, O_RANDOM, O_SHORT_LIVED, O_SEQUENTIAL, O_TEMPORARY-      )   -- * filesystem operations   , mkdir   , unlink@@ -36,16 +28,64 @@   , rename   , fsync, fdatasync   , ftruncate-  , CopyFileFlag(COPYFILE_DEFAULT, COPYFILE_EXCL, COPYFILE_FICLONE)   , copyfile-  , AccessMode(F_OK, R_OK, W_OK, X_OK)   , AccessResult(..)   , access   , chmod, fchmod   , utime, futime, lutime-  , SymlinkFlag(SYMLINK_DEFAULT, SYMLINK_DIR, SYMLINK_JUNCTION)   , link, symlink   , readlink, realpath+  -- * opening constant+  -- ** AccessMode+  , AccessMode+  , pattern F_OK+  , pattern R_OK+  , pattern W_OK+  , pattern X_OK+  -- ** FileMode+  , FileMode+  , pattern DEFAULT_MODE+  , pattern S_IRWXU+  , pattern S_IRUSR+  , pattern S_IWUSR+  , pattern S_IXUSR+  , pattern S_IRWXG+  , pattern S_IRGRP+  , pattern S_IWGRP+  , pattern S_IXGRP+  , pattern S_IRWXO+  , pattern S_IROTH+  -- ** FileFlag+  , FileFlag+  , pattern O_APPEND+  , pattern O_CREAT+  , pattern O_DIRECT+  , pattern O_DSYNC+  , pattern O_EXCL+  , pattern O_EXLOCK+  , pattern O_NOATIME+  , pattern O_NOFOLLOW+  , pattern O_RDONLY+  , pattern O_RDWR+  , pattern O_SYMLINK+  , pattern O_SYNC+  , pattern O_TRUNC+  , pattern O_WRONLY+  , pattern O_RANDOM+  , pattern O_SHORT_LIVED+  , pattern O_SEQUENTIAL+  , pattern O_TEMPORARY+  -- ** CopyFileFlag+  , CopyFileFlag+  , pattern COPYFILE_DEFAULT+  , pattern COPYFILE_EXCL+  , pattern COPYFILE_FICLONE+  , pattern COPYFILE_FICLONE_FORCE+  -- ** SymlinkFlag+  , SymlinkFlag+  , pattern SYMLINK_DEFAULT+  , pattern SYMLINK_DIR+  , pattern SYMLINK_JUNCTION   ) where  import           Control.Monad@@ -77,6 +117,12 @@ data File =  File  {-# UNPACK #-} !UVFD      -- ^ the file                    {-# UNPACK #-} !(IORef Bool)  -- ^ closed flag +-- | Return File fd.+getFileFD :: File -> IO UVFD+getFileFD (File fd closedRef) = do+    closed <- readIORef closedRef+    if closed then throwECLOSED else return fd+ -- | If fd is -1 (closed), throw 'ResourceVanished' ECLOSED. checkFileClosed :: HasCallStack => File -> (UVFD -> IO a) -> IO a checkFileClosed (File fd closedRef) f = do@@ -295,6 +341,7 @@     withCBytesUnsafe path' $ \ p' -> hs_uv_fs_copyfile p p' flag  -- | Equivalent to <http://linux.die.net/man/2/access access(2)> on Unix.+-- -- Windows uses GetFileAttributesW(). access :: HasCallStack => CBytes -> AccessMode -> IO AccessResult access path mode = do
Z/IO/FileSystem/Threaded.hs view
@@ -19,17 +19,9 @@  module Z.IO.FileSystem.Threaded   ( -- * regular file devices-    FileT, initFileT, readFileT, writeFileT+    FileT, initFileT, readFileT, writeFileT, getFileTFD     -- * file offset bundle   , FilePtrT, newFilePtrT, getFileOffset, setFileOffset-    -- * opening constant-  , FileMode(DEFAULT_MODE, S_IRWXU, S_IRUSR, S_IWUSR-      , S_IXUSR, S_IRWXG, S_IRGRP, S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH-      )-  , FileFlag(O_APPEND, O_CREAT, O_DIRECT, O_DSYNC, O_EXCL-      , O_EXLOCK, O_NOATIME, O_NOFOLLOW, O_RDONLY, O_RDWR, O_SYMLINK-      , O_SYNC, O_TRUNC, O_WRONLY, O_RANDOM, O_SHORT_LIVED, O_SEQUENTIAL, O_TEMPORARY-      )   -- * filesystem operations   , mkdir   , unlink@@ -42,16 +34,64 @@   , rename   , fsync, fdatasync   , ftruncate-  , CopyFileFlag(COPYFILE_DEFAULT, COPYFILE_EXCL, COPYFILE_FICLONE)   , copyfile-  , AccessMode(F_OK, R_OK, W_OK, X_OK)   , AccessResult(..)   , access   , chmod, fchmod   , utime, futime, lutime-  , SymlinkFlag(SYMLINK_DEFAULT, SYMLINK_DIR, SYMLINK_JUNCTION)   , link, symlink   , readlink, realpath+  -- * opening constant+  -- ** AccessMode+  , AccessMode+  , pattern F_OK+  , pattern R_OK+  , pattern W_OK+  , pattern X_OK+  -- ** FileMode+  , FileMode+  , pattern DEFAULT_MODE+  , pattern S_IRWXU+  , pattern S_IRUSR+  , pattern S_IWUSR+  , pattern S_IXUSR+  , pattern S_IRWXG+  , pattern S_IRGRP+  , pattern S_IWGRP+  , pattern S_IXGRP+  , pattern S_IRWXO+  , pattern S_IROTH+  -- ** FileFlag+  , FileFlag+  , pattern O_APPEND+  , pattern O_CREAT+  , pattern O_DIRECT+  , pattern O_DSYNC+  , pattern O_EXCL+  , pattern O_EXLOCK+  , pattern O_NOATIME+  , pattern O_NOFOLLOW+  , pattern O_RDONLY+  , pattern O_RDWR+  , pattern O_SYMLINK+  , pattern O_SYNC+  , pattern O_TRUNC+  , pattern O_WRONLY+  , pattern O_RANDOM+  , pattern O_SHORT_LIVED+  , pattern O_SEQUENTIAL+  , pattern O_TEMPORARY+  -- ** CopyFileFlag+  , CopyFileFlag+  , pattern COPYFILE_DEFAULT+  , pattern COPYFILE_EXCL+  , pattern COPYFILE_FICLONE+  , pattern COPYFILE_FICLONE_FORCE+  -- ** SymlinkFlag+  , SymlinkFlag+  , pattern SYMLINK_DEFAULT+  , pattern SYMLINK_DIR+  , pattern SYMLINK_JUNCTION   ) where  import           Control.Monad@@ -85,6 +125,12 @@ -- data FileT =  FileT  {-# UNPACK #-} !UVFD      -- ^ the file                      {-# UNPACK #-} !(IORef Bool)  -- ^ closed flag++-- | Return FileT fd.+getFileTFD :: FileT -> IO UVFD+getFileTFD (FileT fd closedRef) = do+    closed <- readIORef closedRef+    if closed then throwECLOSED else return fd  -- | If fd is -1 (closed), throw 'ResourceVanished' ECLOSED. checkFileTClosed :: HasCallStack => FileT -> (UVFD -> IO a) -> IO a
Z/IO/Network/IPC.hs view
@@ -25,6 +25,11 @@   , IPCServerConfig(..)   , defaultIPCServerConfig   , startIPCServer+  -- * For test+  , helloWorld+  , echo+  -- * Internal helper+  , initIPCStream   ) where  import           Control.Concurrent.MVar@@ -32,13 +37,12 @@ import           Control.Monad.IO.Class import           Data.Primitive.PrimArray import           Foreign.Ptr-import           GHC.Ptr import           Z.Data.CBytes-import           Z.IO.Buffered import           Z.IO.Exception import           Z.IO.Resource import           Z.IO.UV.FFI import           Z.IO.UV.Manager+import           Z.IO.UV.UVStream import           Data.Coerce  --------------------------------------------------------------------------------@@ -79,8 +83,6 @@ data IPCServerConfig = IPCServerConfig     { ipcListenName       :: CBytes      -- ^ listening path (Unix) or a name (Windows).     , ipcListenBacklog    :: Int           -- ^ listening pipe's backlog size, should be large enough(>128)-    , ipcServerWorker     :: UVStream -> IO ()  -- ^ worker which get an accepted IPC stream,-                                                -- the socket will be closed upon exception or worker finishes.     }  -- | A default hello world server on @./ipc@@@ -91,14 +93,18 @@ defaultIPCServerConfig = IPCServerConfig     "./ipc"     256-    (\ uvs -> writeOutput uvs (Ptr "hello world"#) 11)  -- | Start a server -- -- Fork new worker thread upon a new connection. ---startIPCServer :: HasCallStack => IPCServerConfig -> IO ()-startIPCServer IPCServerConfig{..} = do+startIPCServer :: HasCallStack+               => IPCServerConfig+               -> (UVStream -> IO ())  -- ^ worker which get an accepted IPC stream,+                                        -- run in a seperated haskell thread,+                                       --  will be closed upon exception or worker finishes.+               -> IO ()+startIPCServer IPCServerConfig{..} ipcServerWorker = do     let backLog = max ipcListenBacklog 128     serverUVManager <- getUVManager     withResource (initIPCStream serverUVManager) $ \ (UVStream serverHandle serverSlot _ _) -> do
Z/IO/Network/TCP.hs view
@@ -23,8 +23,9 @@   , defaultTCPServerConfig   , startTCPServer   , getTCPPeerName-  , helloWorldWorker-  , echoWorker+  -- * For test+  , helloWorld+  , echo   -- * Internal helper   , setTCPNoDelay   , setTCPKeepAlive@@ -36,14 +37,12 @@ import           Control.Monad.IO.Class import           Data.Primitive.PrimArray import           Foreign.Ptr-import           Foreign.C-import           GHC.Ptr-import           Z.IO.Buffered import           Z.IO.Exception import           Z.IO.Network.SocketAddr import           Z.IO.Resource import           Z.IO.UV.FFI import           Z.IO.UV.Manager+import           Z.IO.UV.UVStream import           Z.Foreign import           Data.Coerce @@ -106,17 +105,6 @@     True     30 --- | A server worker output "hello world" and close the connection.-helloWorldWorker :: UVStream -> IO ()-helloWorldWorker uvs = writeOutput uvs (Ptr "hello world"#) 11---- | A server worker echo whatever received bytes.-echoWorker :: UVStream -> IO ()-echoWorker uvs = do-    i <- newBufferedInput uvs-    o <- newBufferedOutput uvs-    forever $ readBuffer i >>= writeBuffer o >> flushBuffer o- -- | Start a server -- -- Fork new worker thread upon a new connection.@@ -125,7 +113,7 @@                => TCPServerConfig                -> (UVStream -> IO ())   -- ^ worker which will get an accepted TCP stream and                                         -- run in a seperated haskell thread,-                                        -- the socket will be closed upon exception or worker finishes.+                                        -- will be closed upon exception or worker finishes.                -> IO () startTCPServer TCPServerConfig{..} tcpServerWorker = do     let backLog = max tcpListenBacklog 128@@ -155,6 +143,8 @@ -- we allocate a buffer to hold accepted FDs, pass it just like a normal reading buffer. -- then we can start listening.                 acceptBuf <- newPinnedPrimArray backLog+                -- https://stackoverflow.com/questions/1953639/is-it-safe-to-cast-socket-to-int-under-win64+                -- UVFD is 32bit CInt, it's large enough to hold uv_os_sock_t                 let acceptBufPtr = coerce (mutablePrimArrayContents acceptBuf :: Ptr UVFD)                  withUVManager' serverUVManager $ do
Z/IO/Network/UDP.hs view
@@ -25,7 +25,6 @@   , initUDP   , UDPConfig(..)   , defaultUDPConfig-  , UDPFlag(UDP_DEFAULT, UDP_IPV6ONLY, UDP_REUSEADDR)   , sendUDP   , UDPRecvConfig(..)   , defaultUDPRecvConfig@@ -39,7 +38,6 @@   , getPeerName   , sendConnectedUDP   -- * multicast and broadcast-  , Membership(JOIN_GROUP, LEAVE_GROUP)   , setMembership   , setSourceMembership   , setMulticastLoop@@ -47,6 +45,16 @@   , setMulticastInterface   , setBroadcast   , setTTL+  -- * Constants+  -- ** UDPFlag+  , UDPFlag+  , pattern UDP_DEFAULT+  , pattern UDP_IPV6ONLY+  , pattern UDP_REUSEADDR+  -- ** Membership+  , Membership+  , pattern JOIN_GROUP+  , pattern LEAVE_GROUP   ) where  import Control.Concurrent
+ Z/IO/Process.hsc view
@@ -0,0 +1,285 @@+{-|+Module      : Z.IO.Process+Description : Process utilities+Copyright   : (c) Dong Han, 2018~2019+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides process utilities.++@+import Control.Concurrent.MVar+import Z.IO.Process+@++-}++module Z.IO.Process (+    initProcess+  , readProcess +  , readProcessText+  , ProcessOptions(..)+  , defaultProcessOptions+  , ProcessStdStream(..)+  , ProcessState(..)+  , ExitCode(..)+  , waitProcessExit+  , getProcessPID+  , killPID+  , getPriority, setPriority+  -- * internal +  , spawn+  -- * Constant+  -- ** Signal+  , Signal+  , pattern SIGTERM +  , pattern SIGINT +  , pattern SIGKILL+  , pattern SIGHUP +  -- ** Priority+  , Priority+  , pattern PRIORITY_LOW+  , pattern PRIORITY_BELOW_NORMAL+  , pattern PRIORITY_NORMAL+  , pattern PRIORITY_ABOVE_NORMAL+  , pattern PRIORITY_HIGH+  , pattern PRIORITY_HIGHEST+  ) where++import Control.Concurrent+import Control.Concurrent.STM+import Control.Monad+import Data.Primitive.ByteArray+import GHC.Generics+import GHC.Conc.Signal (Signal)+import System.Exit+import Z.Data.CBytes+import Z.Data.CBytes        as CBytes+import Z.Data.JSON         (EncodeJSON, ToValue, FromValue)+import Z.Data.Vector        as V+import Z.Data.Text          as T+import Z.Data.Text.ShowT    (ShowT)+import qualified Data.List  as List+import Z.Data.Array.Unaligned+import Z.Foreign+import Z.IO.Buffered+import Z.IO.Exception+import Z.IO.Network.IPC+import Z.IO.Resource+import Z.IO.UV.FFI+import Z.IO.UV.Manager+import Z.IO.UV.UVStream++#include "uv.h"++-- | Default process options, start @"./main"@ with no arguments, redirect all std streams to @/dev/null@.+defaultProcessOptions :: ProcessOptions+defaultProcessOptions = ProcessOptions+    { processFile = "./main"+    , processArgs = []+    , processEnv = Nothing+    , processCWD = "."+    , processFlags = 0+    , processUID = UID 0+    , processGID = GID 0 +    , processStdStreams = (ProcessIgnore, ProcessIgnore, ProcessIgnore)+    }++-- | Process state+data ProcessState = ProcessRunning PID | ProcessExited ExitCode+  deriving (Show, Eq, Ord, Generic)+  deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)++-- | Wait until process exit and return the 'ExitCode'.+waitProcessExit :: TVar ProcessState -> IO ExitCode+waitProcessExit svar = atomically $ do+    s <- readTVar svar+    case s of ProcessExited e -> return e+              _ -> retry++-- | Get process 'PID' if process is running.+getProcessPID :: TVar ProcessState -> IO (Maybe PID)+getProcessPID svar = atomically $ do+    s <- readTVar svar+    case s of ProcessRunning pid -> return (Just pid)+              _ -> return Nothing++-- | Send signals to process.+killPID :: HasCallStack => PID -> Signal -> IO ()+killPID (PID pid) sig = throwUVIfMinus_ (uv_kill pid sig)++pattern SIGTERM :: Signal+pattern SIGINT  :: Signal+pattern SIGKILL :: Signal+pattern SIGHUP  :: Signal+pattern SIGTERM = #const SIGTERM+pattern SIGINT  = #const SIGINT+pattern SIGKILL = 9  -- on windows this is absent+pattern SIGHUP  = #const SIGHUP++-- | Resource spawn processes.+--+-- Return a resource spawn processes, when initiated return the @(stdin, stdout, stderr, pstate)@ tuple, +-- std streams are created when pass 'ProcessCreate' option, otherwise will be 'Nothing',+-- @pstate@ will be updated to `ProcessExited` automatically when the process exits.+-- +-- A cleanup thread will be started when you finish using the process resource, to close any std stream +-- created during spawn.+--+-- @+--    initProcess defaultProcessOptions{+--          processFile="your program" +--      ,   processStdStreams = (ProcessCreate, ProcessCreate, ProcessCreate)+--      } $ (stdin, stdout, stderr, pstate) -> do+--      ... -- read or write from child process's std stream, will clean up automatically+--      waitProcessExit pstate  -- wait for process exit on current thread.+-- @+initProcess :: ProcessOptions -> Resource (Maybe UVStream, Maybe UVStream, Maybe UVStream, TVar ProcessState)+initProcess opt = initResource (spawn opt) $ \ (s0,s1,s2, pstate) -> void . forkIO $ do+    _ <- waitProcessExit pstate+    forM_ s0 closeUVStream+    forM_ s1 closeUVStream+    forM_ s2 closeUVStream++-- | Spawn a processe with given input.+--+-- Child process's stdout and stderr output are collected, return with exit code.+readProcess :: HasCallStack +            => ProcessOptions                   -- ^ processStdStreams options are ignored+            -> V.Bytes                          -- ^ stdin+            -> IO (V.Bytes, V.Bytes, ExitCode)  -- ^ stdout, stderr, exit code+readProcess opts inp = do+    withResource (initProcess opts{processStdStreams=(ProcessCreate, ProcessCreate, ProcessCreate)}) +        $ \ (Just s0, Just s1, Just s2, pstate) -> do+            r1 <- newEmptyMVar +            r2 <- newEmptyMVar +            _ <- forkIO $ do+                withPrimVectorSafe inp (writeOutput s0)+                closeUVStream s0+            _ <- forkIO $ do+                b1 <- newBufferedInput s1+                readAll' b1 >>= putMVar r1+            _ <- forkIO $ do+                b2 <- newBufferedInput s2+                readAll' b2 >>= putMVar r2 +            (,,) <$> takeMVar r1 <*> takeMVar r2 <*> waitProcessExit pstate++-- | Spawn a processe with given UTF8 textual input.+--+-- Child process's stdout and stderr output are collected as UTF8 bytes, return with exit code.+readProcessText :: HasCallStack +                => ProcessOptions                   -- ^ processStdStreams options are ignored+                -> T.Text                           -- ^ stdin+                -> IO (T.Text, T.Text, ExitCode)    -- ^ stdout, stderr, exit code+readProcessText opts inp = do+    (out, err, e) <- readProcess opts (T.getUTF8Bytes inp)+    return (T.validate out, T.validate err, e)++-- | Spawn a new thread+--+-- Please manually close child process's std stream(if any) after process exists.+spawn :: HasCallStack => ProcessOptions -> IO (Maybe UVStream, Maybe UVStream, Maybe UVStream, TVar ProcessState)+spawn ProcessOptions{..} = do++    (MutableByteArray popts) <- newByteArray (#size uv_process_options_t)+    (MutableByteArray pstdio) <- newByteArray ((#size uv_stdio_container_t)*3)++    pokeMBA popts (#offset uv_process_options_t, flags) processFlags+    pokeMBA popts (#offset uv_process_options_t, uid) processUID+    pokeMBA popts (#offset uv_process_options_t, gid) processGID++    uvm <- getUVManager ++    let (s0, s1, s2) = processStdStreams++    pokeMBA pstdio (#offset uv_stdio_container_t, flags) (processStdStreamFlag s0)+    uvs0' <- case s0 of+        ProcessInherit fd -> do+            pokeMBA pstdio (#offset uv_stdio_container_t, data) fd+            return Nothing+        ProcessCreate -> do+            (uvs0, _) <- acquire (initIPCStream uvm)+            pokeMBA pstdio (#offset uv_stdio_container_t, data) (uvsHandle uvs0)+            return (Just uvs0)+        _ -> return Nothing+        +    pokeMBA pstdio ((#offset uv_stdio_container_t, flags)+(#size uv_stdio_container_t))+                (processStdStreamFlag s1)+    uvs1' <- case s1 of+        ProcessInherit fd -> do+            pokeMBA pstdio ((#offset uv_stdio_container_t, data)+(#size uv_stdio_container_t)) fd+            return Nothing+        ProcessCreate -> do+            (uvs1, _) <- acquire (initIPCStream uvm)+            pokeMBA pstdio ((#offset uv_stdio_container_t, data)+(#size uv_stdio_container_t))+                (uvsHandle uvs1)+            return (Just uvs1)+        _ -> return Nothing++    pokeMBA pstdio ((#offset uv_stdio_container_t, flags)+(#size uv_stdio_container_t)*2)+                (processStdStreamFlag s2)+    uvs2' <- case s2 of+        ProcessInherit fd -> do+            pokeMBA pstdio ((#offset uv_stdio_container_t, data)+(#size uv_stdio_container_t)*2) fd+            return Nothing+        ProcessCreate -> do+            (uvs2, _) <- acquire (initIPCStream uvm)+            pokeMBA pstdio ((#offset uv_stdio_container_t, data.stream)+(#size uv_stdio_container_t)*2)+                (uvsHandle uvs2)+            return (Just uvs2)+        _ -> return Nothing++    -- concat args+    let allArgs = V.intercalateElem 0 (List.map CBytes.toPrimArray processArgs ++ [mempty])  +        argsLen = fromIntegral $ List.length processArgs+    -- concat env+        mkEnv (k, v) = CBytes.toPrimArray (k <> "=" <> v)+        allEnv = case processEnv of+            Just e -> V.intercalateElem 0 (List.map mkEnv e ++ [mempty])  +            _ -> V.singleton 0 +        envLen = case processEnv of+            Just e -> fromIntegral $ List.length e+            _ -> -1++    (slot, pid) <- withCBytesUnsafe processFile $ \ pfile ->+        withCBytesUnsafe processCWD $ \ pcwd ->+            withPrimArrayUnsafe allArgs $ \ pargs _ ->+                withPrimArrayUnsafe allEnv $ \ penv _ ->+                    withUVManager uvm $ \ loop -> do+                        slot <- throwUVIfMinus (hs_uv_spawn loop popts pfile+                                        pargs argsLen penv envLen pcwd pstdio)+                        pid <- peekBufferTable uvm slot+                        return (slot, pid)++    exitLock <- getBlockMVar uvm slot+    ps <- newTVarIO (ProcessRunning (PID (fromIntegral pid)))++    _ <- forkFinally (takeMVar exitLock) $ \ r -> do+        case r of +            Left _ -> atomically (writeTVar ps (ProcessExited (ExitFailure (-1))))+            Right e -> +                let e' = if e == 0 then ExitSuccess else ExitFailure e+                in atomically (writeTVar ps (ProcessExited e'))+++    return (uvs0', uvs1', uvs2', ps)++-- | Retrieves the scheduling priority of the process specified by pid.+--+-- The returned value of priority is between -20 (high priority) and 19 (low priority).+-- On Windows, the returned priority will equal one of the PRIORITY constants.+getPriority :: HasCallStack => PID -> IO Priority+getPriority pid = do+    (p, _) <- allocPrimUnsafe $ \ p_p -> throwUVIfMinus_ (uv_os_getpriority pid p_p)+    return p++-- | Sets the scheduling priority of the process specified by pid.+--+-- The priority value range is between -20 (high priority) and 19 (low priority).+-- The constants 'PRIORITY_LOW', 'PRIORITY_BELOW_NORMAL', 'PRIORITY_NORMAL',+-- 'PRIORITY_ABOVE_NORMAL', 'PRIORITY_HIGH', and 'PRIORITY_HIGHEST' are also provided for convenience.+--+setPriority :: HasCallStack => PID -> Priority -> IO ()+setPriority pid p = throwUVIfMinus_ (uv_os_setpriority pid p)
Z/IO/StdStream.hs view
@@ -1,6 +1,6 @@ {-| Module      : Z.IO.StdStream-Description : TTY devices+Description : Standard Streams and TTY devices Copyright   : (c) Dong Han, 2018~2019 License     : BSD Maintainer  : winterland1989@gmail.com@@ -39,7 +39,7 @@   ( -- * Standard input & output streams     StdStream   , isStdStreamTTY-  , TTYMode(TTY_MODE_NORMAL, TTY_MODE_RAW)+  , getStdStreamFD   , setStdinTTYMode   , getStdoutWinSize   , stdin, stdout, stderr@@ -49,6 +49,13 @@   , readLineStd   , putStd   , putLineStd+    -- * re-export+  , withMVar+  -- * Constant+  -- ** TTYMode+  , TTYMode+  , pattern TTY_MODE_NORMAL+  , pattern TTY_MODE_RAW   ) where  import Control.Monad@@ -82,6 +89,10 @@ isStdStreamTTY (StdTTY _ _ _) = True isStdStreamTTY _              = False +getStdStreamFD :: StdStream -> IO UVFD+getStdStreamFD (StdTTY hdl _ _) = throwUVIfMinus (hs_uv_fileno hdl)+getStdStreamFD (StdFile fd) = return fd+ instance Input StdStream where     {-# INLINE readInput #-}     readInput (StdTTY hdl slot uvm) buf len = mask_ $ do@@ -191,23 +202,26 @@  -------------------------------------------------------------------------------- --- | print a 'ShowT' and flush to stdout.+-- | Print a 'ShowT' and flush to stdout. printStd :: HasCallStack => ShowT a => a -> IO () printStd s = putStd (toBuilder s) --- | print a 'Builder' and flush to stdout.+-- | Print a 'Builder' and flush to stdout. putStd :: HasCallStack => Builder a -> IO () putStd b = withMVar stdoutBuf $ \ o -> do     writeBuilder o b     flushBuffer o --- | print a 'Builder' and flush to stdout, with a linefeed.+-- | Print a 'Builder' and flush to stdout, with a linefeed. putLineStd :: HasCallStack => Builder a -> IO () putLineStd b = withMVar stdoutBuf $ \ o -> do     writeBuilder o (b >> B.char8 '\n')     flushBuffer o --- | read a line from stdin+-- | Read a line from stdin+--+-- This function will throw 'ECLOSED' when meet EOF, which may cause trouble if stdin is connected+-- to a file, use 'readLine' instead. readLineStd :: HasCallStack => IO V.Bytes readLineStd = withMVar stdinBuf $ \ s -> do     line <- readLine s
Z/IO/UV/FFI.hsc view
@@ -16,6 +16,7 @@ import           Data.Bits import           Data.Int import           Data.Word+import           Data.Primitive.Types   (Prim) import           Foreign.C.String import           Foreign.C.Types import           Foreign.Ptr@@ -25,7 +26,7 @@ import qualified Z.Data.Text   as T import           Z.Data.Text.ShowT   (ShowT(..)) import           Z.Data.JSON         (EncodeJSON, ToValue, FromValue)-import           Z.Data.CBytes+import           Z.Data.CBytes as CBytes import           Z.Foreign import           Z.IO.Exception (throwUVIfMinus_) import           Z.IO.Network.SocketAddr    (SocketAddr)@@ -48,7 +49,7 @@ -- | UVSlotUnsafe wrap a slot which may not have a 'MVar' in blocking table,  --   i.e. the blocking table need to be resized. newtype UVSlotUnsafe = UVSlotUnsafe { unsafeGetSlot :: UVSlot }-type UVFD = Int32+type UVFD = CInt  -------------------------------------------------------------------------------- -- CONSTANT@@ -77,15 +78,14 @@     <$> (#{peek hs_loop_data, buffer_table          } p)     <*> (#{peek hs_loop_data, buffer_size_table     } p) -newtype UVRunMode = UVRunMode CInt deriving (Show, Eq, Ord, Generic)-                                   deriving anyclass ShowT +type UVRunMode = CInt   pattern UV_RUN_DEFAULT :: UVRunMode-pattern UV_RUN_DEFAULT = UVRunMode #{const UV_RUN_DEFAULT}+pattern UV_RUN_DEFAULT = #const UV_RUN_DEFAULT pattern UV_RUN_ONCE :: UVRunMode-pattern UV_RUN_ONCE    = UVRunMode #{const UV_RUN_ONCE}+pattern UV_RUN_ONCE    = #const UV_RUN_ONCE pattern UV_RUN_NOWAIT :: UVRunMode-pattern UV_RUN_NOWAIT  = UVRunMode #{const UV_RUN_NOWAIT}+pattern UV_RUN_NOWAIT  = #const UV_RUN_NOWAIT  -- | Peek loop data pointer from uv loop  pointer. peekUVLoopData :: Ptr UVLoop -> IO (Ptr UVLoopData)@@ -150,7 +150,7 @@ foreign import ccall unsafe uv_tcp_getpeername :: Ptr UVHandle -> MBA## SocketAddr -> MBA## CInt -> IO CInt  uV_TCP_IPV6ONLY :: CUInt-uV_TCP_IPV6ONLY = #{const UV_TCP_IPV6ONLY}+uV_TCP_IPV6ONLY = #const UV_TCP_IPV6ONLY  foreign import ccall unsafe uv_tcp_bind :: Ptr UVHandle -> MBA## SocketAddr -> CUInt -> IO CInt foreign import ccall unsafe hs_uv_tcp_connect :: Ptr UVHandle -> MBA## SocketAddr -> IO UVSlotUnsafe@@ -168,28 +168,24 @@ foreign import ccall unsafe uv_udp_open :: Ptr UVHandle -> UVFD -> IO CInt foreign import ccall unsafe uv_udp_bind :: Ptr UVHandle -> MBA## SocketAddr -> UDPFlag -> IO CInt -newtype Membership = Membership CInt deriving (Show, Eq, Ord, Generic)-                                        deriving newtype (EncodeJSON, ToValue, FromValue)-                                        deriving anyclass ShowT+type Membership = CInt   pattern LEAVE_GROUP :: Membership-pattern LEAVE_GROUP = Membership #{const UV_LEAVE_GROUP}+pattern LEAVE_GROUP = #const UV_LEAVE_GROUP pattern JOIN_GROUP :: Membership-pattern JOIN_GROUP = Membership #{const UV_JOIN_GROUP}+pattern JOIN_GROUP = #const UV_JOIN_GROUP -newtype UDPFlag = UDPFlag CInt deriving (Show, Eq, Ord, Generic)-                                deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-                                deriving anyclass ShowT+type UDPFlag = CInt   pattern UDP_DEFAULT        :: UDPFlag-pattern UDP_DEFAULT         = UDPFlag 0+pattern UDP_DEFAULT         = 0 pattern UDP_IPV6ONLY       :: UDPFlag-pattern UDP_IPV6ONLY        = UDPFlag #{const UV_UDP_IPV6ONLY}+pattern UDP_IPV6ONLY        = #const UV_UDP_IPV6ONLY pattern UDP_REUSEADDR      :: UDPFlag-pattern UDP_REUSEADDR       = UDPFlag #{const UV_UDP_REUSEADDR}+pattern UDP_REUSEADDR       = #const UV_UDP_REUSEADDR  pattern UV_UDP_PARTIAL     :: Int32-pattern UV_UDP_PARTIAL      = #{const UV_UDP_PARTIAL}+pattern UV_UDP_PARTIAL      = #const UV_UDP_PARTIAL  foreign import ccall unsafe uv_udp_connect     :: Ptr UVHandle -> MBA## SocketAddr -> IO CInt@@ -233,17 +229,14 @@ -- When in 'UV_TTY_MODE_RAW' mode, input is always available character-by-character, -- not including modifiers. Additionally, all special processing of characters by the terminal is disabled,  -- including echoing input characters. Note that CTRL+C will no longer cause a SIGINT when in this mode.-newtype TTYMode = TTYMode CInt-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT+type TTYMode = CInt  pattern TTY_MODE_NORMAL :: TTYMode-pattern TTY_MODE_NORMAL = TTYMode #{const UV_TTY_MODE_NORMAL}+pattern TTY_MODE_NORMAL = #const UV_TTY_MODE_NORMAL pattern TTY_MODE_RAW :: TTYMode-pattern TTY_MODE_RAW = TTYMode #{const UV_TTY_MODE_RAW}+pattern TTY_MODE_RAW = #const UV_TTY_MODE_RAW pattern TTY_MODE_IO :: TTYMode-pattern TTY_MODE_IO = TTYMode #{const UV_TTY_MODE_IO}+pattern TTY_MODE_IO = #const UV_TTY_MODE_IO  foreign import ccall unsafe uv_tty_init :: Ptr UVLoop -> Ptr UVHandle -> CInt -> IO CInt foreign import ccall unsafe uv_tty_set_mode :: Ptr UVHandle -> TTYMode -> IO CInt@@ -252,62 +245,59 @@ -------------------------------------------------------------------------------- -- fs -newtype FileMode = FileMode CInt-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT+type FileMode = CInt  -- | 00700 user (file owner) has read, write and execute permission pattern S_IRWXU :: FileMode-pattern S_IRWXU = FileMode #{const S_IRWXU}+pattern S_IRWXU = #const S_IRWXU  -- | 00400 user has read permission pattern S_IRUSR :: FileMode-pattern S_IRUSR = FileMode #{const S_IRUSR}+pattern S_IRUSR = #const S_IRUSR  -- | 00200 user has write permission pattern S_IWUSR :: FileMode-pattern S_IWUSR = FileMode #{const S_IWUSR}+pattern S_IWUSR = #const S_IWUSR  -- | 00100 user has execute permission pattern S_IXUSR :: FileMode-pattern S_IXUSR = FileMode #{const S_IXUSR}+pattern S_IXUSR = #const S_IXUSR  -- | 00070 group has read, write and execute permission pattern S_IRWXG :: FileMode-pattern S_IRWXG = FileMode #{const S_IRWXG}+pattern S_IRWXG = #const S_IRWXG  -- | 00040 group has read permission pattern S_IRGRP :: FileMode-pattern S_IRGRP = FileMode #{const S_IRGRP}+pattern S_IRGRP = #const S_IRGRP  -- | 00020 group has write permission pattern S_IWGRP :: FileMode-pattern S_IWGRP = FileMode #{const S_IWGRP}+pattern S_IWGRP = #const S_IWGRP  -- | 00010 group has execute permission pattern S_IXGRP :: FileMode-pattern S_IXGRP = FileMode #{const S_IXGRP}+pattern S_IXGRP = #const S_IXGRP  -- | 00007 others have read, write and execute permission pattern S_IRWXO :: FileMode-pattern S_IRWXO = FileMode #{const S_IRWXO}+pattern S_IRWXO = #const S_IRWXO  -- | 00004 others have read permission pattern S_IROTH :: FileMode-pattern S_IROTH = FileMode #{const S_IROTH}+pattern S_IROTH = #const S_IROTH  -- | 00002 others have write permission pattern S_IWOTH :: FileMode-pattern S_IWOTH = FileMode #{const S_IWOTH}+pattern S_IWOTH = #const S_IWOTH  -- | 00001 others have execute permission pattern S_IXOTH :: FileMode-pattern S_IXOTH = FileMode #{const S_IXOTH}+pattern S_IXOTH = #const S_IXOTH  -- | Default mode for open, 0o666(readable and writable). pattern DEFAULT_MODE :: FileMode-pattern DEFAULT_MODE = FileMode 0o666+pattern DEFAULT_MODE = 0o666  -- non-threaded functions foreign import ccall unsafe hs_uv_fs_open    :: BA## Word8 -> FileFlag -> FileMode -> IO UVFD@@ -337,34 +327,31 @@ foreign import ccall unsafe hs_uv_fs_mkdtemp_threaded      :: BA## Word8 -> Int -> MBA## Word8 -> Ptr UVLoop -> IO UVSlotUnsafe -newtype FileFlag = FileFlag CInt-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT+type FileFlag = CInt  -- | The file is opened in append mode. Before each write, the file offset is positioned at the end of the file. pattern O_APPEND :: FileFlag-pattern O_APPEND = FileFlag #{const UV_FS_O_APPEND}+pattern O_APPEND = #const UV_FS_O_APPEND  -- | The file is created if it does not already exist. pattern O_CREAT :: FileFlag-pattern O_CREAT = FileFlag #{const UV_FS_O_CREAT}+pattern O_CREAT = #const UV_FS_O_CREAT  -- | File IO is done directly to and from user-space buffers, which must be aligned. Buffer size and address should be a multiple of the physical sector size of the block device, (DO NOT USE WITH Z-IO's @BufferedIO@) pattern O_DIRECT :: FileFlag-pattern O_DIRECT = FileFlag #{const UV_FS_O_DIRECT}+pattern O_DIRECT = #const UV_FS_O_DIRECT  -- | If the path is not a directory, fail the open. (Not useful on regular file) -- -- Note 'o_DIRECTORY' is not supported on Windows. pattern O_DIRECTORY :: FileFlag-pattern O_DIRECTORY = FileFlag #{const UV_FS_O_DIRECTORY}+pattern O_DIRECTORY = #const UV_FS_O_DIRECTORY  -- |The file is opened for synchronous IO. Write operations will complete once all data and a minimum of metadata are flushed to disk. -- -- Note 'o_DSYNC' is supported on Windows via @FILE_FLAG_WRITE_THROUGH@. pattern O_DSYNC :: FileFlag-pattern O_DSYNC = FileFlag #{const UV_FS_O_DSYNC}+pattern O_DSYNC = #const UV_FS_O_DSYNC  -- | If the 'o_CREAT' flag is set and the file already exists, fail the open. --@@ -372,98 +359,95 @@ -- Linux 2.6 and later, 'o_EXCL' can be used without 'o_CREAT' if pathname refers to a block device. If the block  -- device is in use by the system (e.g., mounted), the open will fail with the error @EBUSY@. pattern O_EXCL :: FileFlag-pattern O_EXCL = FileFlag #{const UV_FS_O_EXCL}+pattern O_EXCL = #const UV_FS_O_EXCL  -- | Atomically obtain an exclusive lock. -- -- Note UV_FS_O_EXLOCK is only supported on macOS and Windows. -- (libuv: Changed in version 1.17.0: support is added for Windows.) pattern O_EXLOCK :: FileFlag-pattern O_EXLOCK = FileFlag #{const UV_FS_O_EXLOCK}+pattern O_EXLOCK = #const UV_FS_O_EXLOCK  -- | Do not update the file access time when the file is read. --  -- Note 'o_NOATIME' is not supported on Windows. pattern O_NOATIME :: FileFlag-pattern O_NOATIME = FileFlag #{const UV_FS_O_NOATIME}+pattern O_NOATIME = #const UV_FS_O_NOATIME  -- | If the path identifies a terminal device, opening the path will not cause that terminal to become the controlling terminal for the process (if the process does not already have one). (Not sure if this flag is useful) -- -- Note 'o_NOCTTY' is not supported on Windows. pattern O_NOCTTY :: FileFlag-pattern O_NOCTTY = FileFlag #{const UV_FS_O_NOCTTY}+pattern O_NOCTTY = #const UV_FS_O_NOCTTY  -- | If the path is a symbolic link, fail the open. -- -- Note 'o_NOFOLLOW' is not supported on Windows. pattern O_NOFOLLOW :: FileFlag-pattern O_NOFOLLOW = FileFlag #{const UV_FS_O_NOFOLLOW}+pattern O_NOFOLLOW = #const UV_FS_O_NOFOLLOW  -- | Open the file in nonblocking mode if possible. (Definitely not useful in Z-IO) -- -- Note 'o_NONBLOCK' is not supported on Windows. (Not useful on regular file anyway) pattern O_NONBLOCK :: FileFlag-pattern O_NONBLOCK = FileFlag #{const UV_FS_O_NONBLOCK}+pattern O_NONBLOCK = #const UV_FS_O_NONBLOCK  -- | Access is intended to be random. The system can use this as a hint to optimize file caching. --  -- Note 'o_RANDOM' is only supported on Windows via @FILE_FLAG_RANDOM_ACCESS@. pattern O_RANDOM :: FileFlag-pattern O_RANDOM = FileFlag #{const UV_FS_O_RANDOM}+pattern O_RANDOM = #const UV_FS_O_RANDOM  -- | Open the file for read-only access. pattern O_RDONLY :: FileFlag-pattern O_RDONLY = FileFlag #{const UV_FS_O_RDONLY}+pattern O_RDONLY = #const UV_FS_O_RDONLY  -- | Open the file for read-write access. pattern O_RDWR :: FileFlag-pattern O_RDWR = FileFlag #{const UV_FS_O_RDWR}+pattern O_RDWR = #const UV_FS_O_RDWR   -- | Access is intended to be sequential from beginning to end. The system can use this as a hint to optimize file caching. --  -- Note 'o_SEQUENTIAL' is only supported on Windows via @FILE_FLAG_SEQUENTIAL_SCAN@. pattern O_SEQUENTIAL :: FileFlag-pattern O_SEQUENTIAL = FileFlag #{const UV_FS_O_SEQUENTIAL}+pattern O_SEQUENTIAL = #const UV_FS_O_SEQUENTIAL  -- | The file is temporary and should not be flushed to disk if possible. -- -- Note 'o_SHORT_LIVED' is only supported on Windows via @FILE_ATTRIBUTE_TEMPORARY@. pattern O_SHORT_LIVED :: FileFlag-pattern O_SHORT_LIVED = FileFlag #{const UV_FS_O_SHORT_LIVED}+pattern O_SHORT_LIVED = #const UV_FS_O_SHORT_LIVED  -- | Open the symbolic link itself rather than the resource it points to. pattern O_SYMLINK :: FileFlag-pattern O_SYMLINK = FileFlag #{const UV_FS_O_SYMLINK}+pattern O_SYMLINK = #const UV_FS_O_SYMLINK  -- | The file is opened for synchronous IO. Write operations will complete once all data and all metadata are flushed to disk. -- -- Note 'o_SYNC' is supported on Windows via @FILE_FLAG_WRITE_THROUGH@. pattern O_SYNC :: FileFlag-pattern O_SYNC = FileFlag #{const UV_FS_O_SYNC}+pattern O_SYNC = #const UV_FS_O_SYNC  -- | The file is temporary and should not be flushed to disk if possible. -- -- Note 'o_TEMPORARY' is only supported on Windows via @FILE_ATTRIBUTE_TEMPORARY@. pattern O_TEMPORARY :: FileFlag-pattern O_TEMPORARY = FileFlag #{const UV_FS_O_TEMPORARY}+pattern O_TEMPORARY = #const UV_FS_O_TEMPORARY  -- | If the file exists and is a regular file, and the file is opened successfully for write access, its length shall be truncated to zero. pattern O_TRUNC :: FileFlag-pattern O_TRUNC = FileFlag #{const UV_FS_O_TRUNC}+pattern O_TRUNC = #const UV_FS_O_TRUNC  -- | Open the file for write-only access. pattern O_WRONLY :: FileFlag-pattern O_WRONLY = FileFlag #{const UV_FS_O_WRONLY}+pattern O_WRONLY = #const UV_FS_O_WRONLY  #if defined(_WIN32)-newtype UVDirEntType = UVDirEntType CInt+type UVDirEntType = CInt #else-newtype UVDirEntType = UVDirEntType CChar+type UVDirEntType = CChar #endif-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT  data DirEntType     = DirEntUnknown@@ -474,32 +458,21 @@     | DirEntSocket     | DirEntChar     | DirEntBlock-  deriving (Read, Show, Eq, Ord, Generic)+  deriving (Read, Show, Eq, Ord, Enum, Generic)     deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)  fromUVDirEntType :: UVDirEntType -> DirEntType fromUVDirEntType t-    | t == uV__DT_FILE   = DirEntFile-    | t == uV__DT_DIR    = DirEntDir-    | t == uV__DT_LINK   = DirEntLink-    | t == uV__DT_FIFO   = DirEntFIFO-    | t == uV__DT_SOCKET = DirEntSocket-    | t == uV__DT_CHAR   = DirEntChar-    | t == uV__DT_BLOCK  = DirEntBlock+    | t == #{const UV__DT_FILE  } = DirEntFile+    | t == #{const UV__DT_DIR   } = DirEntDir+    | t == #{const UV__DT_LINK  } = DirEntLink+    | t == #{const UV__DT_FIFO  } = DirEntFIFO+    | t == #{const UV__DT_SOCKET} = DirEntSocket+    | t == #{const UV__DT_CHAR  } = DirEntChar+    | t == #{const UV__DT_BLOCK } = DirEntBlock     | otherwise          = DirEntUnknown -#{enum UVDirEntType, UVDirEntType,-    uV__DT_FILE    = UV__DT_FILE,-    uV__DT_DIR     = UV__DT_DIR,-    uV__DT_LINK    = UV__DT_LINK,-    uV__DT_FIFO    = UV__DT_FIFO,-    uV__DT_SOCKET  = UV__DT_SOCKET,-    uV__DT_CHAR    = UV__DT_CHAR,-    uV__DT_BLOCK   = UV__DT_BLOCK}--data UVDirEnt--peekUVDirEnt :: Ptr UVDirEnt -> IO (CString, UVDirEntType)+peekUVDirEnt :: Ptr DirEntType -> IO (CString, UVDirEntType) #ifdef HAVE_DIRENT_TYPES peekUVDirEnt p = (,) (#{ptr hs_uv__dirent_t, d_name } p) <$> (#{peek hs_uv__dirent_t, d_type } p) #else@@ -507,13 +480,13 @@ #endif  foreign import ccall unsafe hs_uv_fs_scandir_cleanup-    :: Ptr (Ptr UVDirEnt) -> Int -> IO ()+    :: Ptr (Ptr DirEntType) -> Int -> IO () foreign import ccall unsafe hs_uv_fs_scandir-    :: BA## Word8 -> MBA## (Ptr UVDirEnt) -> IO Int+    :: BA## Word8 -> MBA## (Ptr DirEntType) -> IO Int foreign import ccall unsafe hs_uv_fs_scandir_extra_cleanup -    :: Ptr (Ptr (Ptr UVDirEnt)) -> Int -> IO ()+    :: Ptr (Ptr (Ptr DirEntType)) -> Int -> IO () foreign import ccall unsafe hs_uv_fs_scandir_threaded-    :: BA## Word8 -> Ptr (Ptr (Ptr UVDirEnt)) -> Ptr UVLoop -> IO UVSlotUnsafe+    :: BA## Word8 -> Ptr (Ptr (Ptr DirEntType)) -> Ptr UVLoop -> IO UVSlotUnsafe  data UVTimeSpec = UVTimeSpec      { uvtSecond     :: {-# UNPACK #-} !CLong@@ -597,47 +570,41 @@  -- | Flags control copying. -- ---   * 'COPYFILE_EXCL': If present, uv_fs_copyfile() will fail with UV_EEXIST if the destination path already exists. The default behavior is to overwrite the destination if it exists.---   * 'COPYFILE_FICLONE': If present, uv_fs_copyfile() will attempt to create a copy-on-write reflink. If the underlying platform does not support copy-on-write, then a fallback copy mechanism is used.--- -newtype CopyFileFlag = CopyFileFlag CInt-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT+--  * 'COPYFILE_EXCL': If present, uv_fs_copyfile() will fail with UV_EEXIST if the destination path already exists. The default behavior is to overwrite the destination if it exists.+--  * 'COPYFILE_FICLONE': If present, uv_fs_copyfile() will attempt to create a copy-on-write reflink. If the underlying platform does not support copy-on-write, then a fallback copy mechanism is used.+--  * 'COPYFILE_FICLONE_FORCE': If present, uv_fs_copyfile() will attempt to create a copy-on-write reflink. If the underlying platform does not support copy-on-write, or an error occurs while attempting to use copy-on-write, then an error is returned.+type CopyFileFlag = CInt  pattern COPYFILE_DEFAULT :: CopyFileFlag-pattern COPYFILE_DEFAULT = CopyFileFlag 0+pattern COPYFILE_DEFAULT = 0  pattern COPYFILE_EXCL :: CopyFileFlag-pattern COPYFILE_EXCL = CopyFileFlag #{const UV_FS_COPYFILE_EXCL}+pattern COPYFILE_EXCL = #const UV_FS_COPYFILE_EXCL  pattern COPYFILE_FICLONE :: CopyFileFlag-#ifdef UV_FS_COPYFILE_FICLONE-pattern COPYFILE_FICLONE = CopyFileFlag #{const UV_FS_COPYFILE_FICLONE}-#else-pattern COPYFILE_FICLONE = CopyFileFlag 0   -- fallback to normal copy.-#endif+pattern COPYFILE_FICLONE = #const UV_FS_COPYFILE_FICLONE +pattern COPYFILE_FICLONE_FORCE :: CopyFileFlag+pattern COPYFILE_FICLONE_FORCE = #const UV_FS_COPYFILE_FICLONE_FORCE+ foreign import ccall unsafe hs_uv_fs_copyfile :: BA## Word8 -> BA## Word8 -> CopyFileFlag -> IO Int foreign import ccall unsafe hs_uv_fs_copyfile_threaded     :: BA## Word8 -> BA## Word8 -> CopyFileFlag -> Ptr UVLoop -> IO UVSlotUnsafe -newtype AccessMode = AccessMode CInt-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT+type AccessMode = CInt  pattern F_OK :: AccessMode-pattern F_OK = AccessMode #{const F_OK}+pattern F_OK = #const F_OK pattern R_OK :: AccessMode-pattern R_OK = AccessMode #{const R_OK}+pattern R_OK = #const R_OK pattern W_OK :: AccessMode-pattern W_OK = AccessMode #{const W_OK}+pattern W_OK = #const W_OK pattern X_OK :: AccessMode-pattern X_OK = AccessMode #{const X_OK}+pattern X_OK = #const X_OK -data AccessResult = NoExistence | NoPermission | AccessOK deriving (Show, Eq, Ord, Generic)-                                                          deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)+data AccessResult = NoExistence | NoPermission | AccessOK +    deriving (Show, Eq, Ord, Enum, Generic)+    deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)  foreign import ccall unsafe hs_uv_fs_access :: BA## Word8 -> AccessMode -> IO Int foreign import ccall unsafe hs_uv_fs_access_threaded@@ -663,19 +630,20 @@ foreign import ccall unsafe hs_uv_fs_lutime_threaded     :: BA## Word8 -> Double -> Double -> Ptr UVLoop -> IO UVSlotUnsafe -newtype SymlinkFlag = SymlinkFlag CInt-    deriving (Eq, Ord, Show, Generic)-    deriving newtype (Storable, Unaligned, Bits, FiniteBits, Num, EncodeJSON, ToValue, FromValue)-    deriving anyclass ShowT+-- | On Windows the flags parameter can be specified to control how the symlink will be created:+--+-- * 'SYMLINK_DIR': indicates that path points to a directory.+-- * 'SYMLINK_JUNCTION': request that the symlink is created using junction points.+type SymlinkFlag = CInt  pattern SYMLINK_DEFAULT :: SymlinkFlag-pattern SYMLINK_DEFAULT = SymlinkFlag 0+pattern SYMLINK_DEFAULT = 0  pattern SYMLINK_DIR :: SymlinkFlag-pattern SYMLINK_DIR = SymlinkFlag #{const UV_FS_SYMLINK_DIR}+pattern SYMLINK_DIR = #const UV_FS_SYMLINK_DIR  pattern SYMLINK_JUNCTION :: SymlinkFlag-pattern SYMLINK_JUNCTION = SymlinkFlag #{const UV_FS_SYMLINK_JUNCTION}+pattern SYMLINK_JUNCTION = #const UV_FS_SYMLINK_JUNCTION  foreign import ccall unsafe hs_uv_fs_link :: BA## Word8 -> BA## Word8 -> IO Int foreign import ccall unsafe hs_uv_fs_link_threaded@@ -700,48 +668,169 @@     :: BA## Word8  -> Ptr CString -> Ptr UVLoop -> IO UVSlotUnsafe  --------------------------------------------------------------------------------+-- process++newtype UID = UID +#if defined(_WIN32)+    Word8+#else+    Word32+#endif+   deriving (Eq, Ord, Show, Generic)+   deriving newtype (Storable, Prim, Unaligned, EncodeJSON, ToValue, FromValue)+   deriving anyclass ShowT++newtype GID = GID +#if defined(_WIN32)+    Word8+#else+    Word32+#endif+   deriving (Eq, Ord, Show, Generic)+   deriving newtype (Storable, Prim, Unaligned, EncodeJSON, ToValue, FromValue)+   deriving anyclass ShowT++type ProcessFlag = CUInt++-- | Set the child process' user id.+--+-- This is not supported on Windows, uv_spawn() will fail and set the error to UV_ENOTSUP.+pattern PROCESS_SETUID :: ProcessFlag+pattern PROCESS_SETUID = (#const UV_PROCESS_SETUID)+-- | Set the child process' user id.+--+-- This is not supported on Windows, uv_spawn() will fail and set the error to UV_ENOTSUP.+pattern PROCESS_SETGID :: ProcessFlag+pattern PROCESS_SETGID = (#const UV_PROCESS_SETGID)+-- | Do not wrap any arguments in quotes, or perform any other escaping, when+-- converting the argument list into a command line string. +--+-- This option is only meaningful on Windows systems. On Unix it is silently ignored.+pattern PROCESS_WINDOWS_VERBATIM_ARGUMENTS :: ProcessFlag+pattern PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (#const UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)+-- | Spawn the child process in a detached state +--+-- This will make it a process group leader, and will effectively enable the child to keep running after+-- the parent exits. Note that the child process will still keep the+-- parent's event loop alive unless the parent process calls uv_unref() on+-- the child's process handle.+pattern PROCESS_DETACHED :: ProcessFlag+pattern PROCESS_DETACHED = (#const UV_PROCESS_DETACHED)+-- | Hide the subprocess window that would normally be created.+--+-- This option is only meaningful on Windows systems. On Unix it is silently ignored.+pattern PROCESS_WINDOWS_HIDE :: ProcessFlag+pattern PROCESS_WINDOWS_HIDE = (#const UV_PROCESS_WINDOWS_HIDE)+-- | Hide the subprocess console window that would normally be created. +--+-- This option is only meaningful on Windows systems. On Unix it is silently ignored.+pattern PROCESS_WINDOWS_HIDE_CONSOLE :: ProcessFlag+pattern PROCESS_WINDOWS_HIDE_CONSOLE = (#const UV_PROCESS_WINDOWS_HIDE_CONSOLE)+-- | Hide the subprocess GUI window that would normally be created. +--+-- This option is only meaningful on Windows systems. On Unix it is silently ignored.+pattern PROCESS_WINDOWS_HIDE_GUI :: ProcessFlag+pattern PROCESS_WINDOWS_HIDE_GUI = (#const UV_PROCESS_WINDOWS_HIDE_GUI)+++{- typedef struct uv_process_options_s {+    uv_exit_cb exit_cb;+    const char* file;+    char** args;+    char** env;+    const char* cwd;+    unsigned int flags;+    int stdio_count;+    uv_stdio_container_t* stdio;+    uv_uid_t uid;+    uv_gid_t gid;+} uv_process_options_t;+-}++data ProcessOptions = ProcessOptions+    { processFile :: CBytes                     -- ^ Path pointing to the program to be executed.+    , processArgs :: [CBytes]                   -- ^ Command line arguments. +                                                -- On Windows this uses CreateProcess which concatenates+                                                -- the arguments into a string this can cause some strange errors.+                                                -- See the 'PROCESS_WINDOWS_VERBATIM_ARGUMENTS'.+    , processEnv  :: Maybe [(CBytes, CBytes)]   -- ^ Optional environment(otherwise inherit from the current process).+    , processCWD :: CBytes                      -- ^ Current working directory for the subprocess.+    , processFlags :: ProcessFlag               -- ^ Various flags that control how spawn behaves+    , processUID :: UID -- ^ This happens only when the appropriate bits are set in the flags fields.+    , processGID :: GID -- ^ This happens only when the appropriate bits are set in the flags fields.+    , processStdStreams :: (ProcessStdStream, ProcessStdStream, ProcessStdStream) -- ^ Specifying how (stdin, stdout, stderr) should be passed/created to the child, see 'ProcessStdStream'+                            +    }  deriving (Eq, Ord, Show, Generic)+       deriving anyclass ShowT++data ProcessStdStream+    = ProcessIgnore     -- ^ redirect process std stream to /dev/null+    | ProcessCreate     -- ^ create a new std stream+    | ProcessInherit UVFD -- ^ pass an existing FD to child process as std stream+  deriving  (Eq, Ord, Show, Generic)+  deriving anyclass ShowT++processStdStreamFlag :: ProcessStdStream -> CInt+processStdStreamFlag ProcessIgnore = #const UV_IGNORE+processStdStreamFlag ProcessCreate = (#const UV_CREATE_PIPE) +                            .|. (#const UV_READABLE_PIPE)+                            .|. (#const UV_WRITABLE_PIPE)+processStdStreamFlag (ProcessInherit _) = #const UV_INHERIT_FD++foreign import ccall unsafe hs_uv_spawn :: Ptr UVLoop +                                        -> MBA## ProcessOptions         --  option+                                        -> BA## Word8                   --  file+                                        -> BA## Word8                   --  all args+                                        -> CSize                        --  args len+                                        -> BA## Word8                   --  all envs+                                        -> CSsize                        --  envs len+                                        -> BA## Word8                   --  cwd+                                        -> MBA## ProcessStdStream       -- stdio+                                        -> IO Int++foreign import ccall unsafe uv_kill :: CInt -> CInt -> IO CInt++-------------------------------------------------------------------------------- -- misc -newtype UVHandleType = UVHandleType CInt deriving (Eq, Ord, Show, Generic)-                                         deriving newtype (Storable, Unaligned, EncodeJSON, ToValue, FromValue)-                                         deriving anyclass ShowT+type UVHandleType = CInt  pattern UV_UNKNOWN_HANDLE :: UVHandleType-pattern UV_UNKNOWN_HANDLE = UVHandleType #{const UV_UNKNOWN_HANDLE}+pattern UV_UNKNOWN_HANDLE = #{const UV_UNKNOWN_HANDLE} pattern UV_ASYNC :: UVHandleType-pattern UV_ASYNC = UVHandleType #{const UV_ASYNC}+pattern UV_ASYNC = #const UV_ASYNC pattern UV_CHECK :: UVHandleType-pattern UV_CHECK = UVHandleType #{const UV_CHECK}+pattern UV_CHECK = #const UV_CHECK pattern UV_FS_EVENT :: UVHandleType-pattern UV_FS_EVENT = UVHandleType #{const UV_FS_EVENT}+pattern UV_FS_EVENT = #const UV_FS_EVENT pattern UV_FS_POLL :: UVHandleType-pattern UV_FS_POLL = UVHandleType #{const UV_FS_POLL}+pattern UV_FS_POLL = #const UV_FS_POLL pattern UV_HANDLE :: UVHandleType-pattern UV_HANDLE = UVHandleType #{const UV_HANDLE}+pattern UV_HANDLE = #const UV_HANDLE pattern UV_IDLE :: UVHandleType-pattern UV_IDLE = UVHandleType #{const UV_IDLE}+pattern UV_IDLE = #const UV_IDLE pattern UV_NAMED_PIPE :: UVHandleType-pattern UV_NAMED_PIPE = UVHandleType #{const UV_NAMED_PIPE}+pattern UV_NAMED_PIPE = #const UV_NAMED_PIPE pattern UV_POLL :: UVHandleType-pattern UV_POLL = UVHandleType #{const UV_POLL}+pattern UV_POLL = #const UV_POLL pattern UV_PREPARE :: UVHandleType-pattern UV_PREPARE = UVHandleType #{const UV_PREPARE}+pattern UV_PREPARE = #const UV_PREPARE pattern UV_PROCESS :: UVHandleType-pattern UV_PROCESS = UVHandleType #{const UV_PROCESS}+pattern UV_PROCESS = #const UV_PROCESS pattern UV_STREAM :: UVHandleType-pattern UV_STREAM = UVHandleType #{const UV_STREAM}+pattern UV_STREAM = #const UV_STREAM pattern UV_TCP :: UVHandleType-pattern UV_TCP = UVHandleType #{const UV_TCP}+pattern UV_TCP = #const UV_TCP pattern UV_TIMER :: UVHandleType-pattern UV_TIMER = UVHandleType #{const UV_TIMER}+pattern UV_TIMER = #const UV_TIMER pattern UV_TTY :: UVHandleType-pattern UV_TTY = UVHandleType #{const UV_TTY}+pattern UV_TTY = #const UV_TTY pattern UV_UDP :: UVHandleType-pattern UV_UDP = UVHandleType #{const UV_UDP}+pattern UV_UDP = #const UV_UDP pattern UV_SIGNAL :: UVHandleType-pattern UV_SIGNAL = UVHandleType #{const UV_SIGNAL}+pattern UV_SIGNAL = #const UV_SIGNAL pattern UV_FILE :: UVHandleType-pattern UV_FILE = UVHandleType #{const UV_FILE}+pattern UV_FILE = #const UV_FILE  foreign import ccall unsafe uv_guess_handle :: UVFD -> IO UVHandleType @@ -754,8 +843,8 @@ data TimeVal = TimeVal      { tv_sec  :: {-# UNPACK #-} !CLong     , tv_usec :: {-# UNPACK #-} !CLong-    } deriving (Show, Read, Eq, Ord, Generic)-      deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)+    }   deriving (Show, Read, Eq, Ord, Generic)+        deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)  -- | Data type for resource usage results. --@@ -778,8 +867,8 @@     , ru_nsignals :: {-# UNPACK #-} !Word64    -- ^  signals received (X)     , ru_nvcsw    :: {-# UNPACK #-} !Word64    -- ^  voluntary context switches (X)     , ru_nivcsw   :: {-# UNPACK #-} !Word64    -- ^  involuntary context switches (X)-    } deriving (Show, Read, Eq, Ord, Generic)-      deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)+    }   deriving (Show, Read, Eq, Ord, Generic)+        deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)  sizeOfResUsage :: Int sizeOfResUsage = #size uv_rusage_t@@ -813,22 +902,24 @@ foreign import ccall unsafe uv_os_getpriority :: PID -> MBA## CInt -> IO CInt foreign import ccall unsafe uv_os_setpriority :: PID -> CInt -> IO CInt -newtype PID = PID CInt deriving (Eq, Ord, Show, Generic)-                       deriving newtype (Storable, Unaligned, EncodeJSON, ToValue, FromValue)-                       deriving anyclass ShowT+newtype PID = PID CInt +    deriving (Eq, Ord, Show, Generic)+    deriving newtype (Storable, Prim, Unaligned, EncodeJSON, ToValue, FromValue)+    deriving anyclass ShowT -pattern PRIORITY_LOW          :: CInt-pattern PRIORITY_BELOW_NORMAL :: CInt-pattern PRIORITY_NORMAL       :: CInt-pattern PRIORITY_ABOVE_NORMAL :: CInt-pattern PRIORITY_HIGH         :: CInt-pattern PRIORITY_HIGHEST      :: CInt-pattern PRIORITY_LOW           = (#const UV_PRIORITY_LOW           )-pattern PRIORITY_BELOW_NORMAL  = (#const UV_PRIORITY_BELOW_NORMAL  )-pattern PRIORITY_NORMAL        = (#const UV_PRIORITY_NORMAL        )-pattern PRIORITY_ABOVE_NORMAL  = (#const UV_PRIORITY_ABOVE_NORMAL  )-pattern PRIORITY_HIGH          = (#const UV_PRIORITY_HIGH          )-pattern PRIORITY_HIGHEST       = (#const UV_PRIORITY_HIGHEST       )+type Priority = CInt+pattern PRIORITY_LOW          :: Priority+pattern PRIORITY_BELOW_NORMAL :: Priority+pattern PRIORITY_NORMAL       :: Priority+pattern PRIORITY_ABOVE_NORMAL :: Priority+pattern PRIORITY_HIGH         :: Priority+pattern PRIORITY_HIGHEST      :: Priority+pattern PRIORITY_LOW           = #const UV_PRIORITY_LOW         +pattern PRIORITY_BELOW_NORMAL  = #const UV_PRIORITY_BELOW_NORMAL  +pattern PRIORITY_NORMAL        = #const UV_PRIORITY_NORMAL        +pattern PRIORITY_ABOVE_NORMAL  = #const UV_PRIORITY_ABOVE_NORMAL  +pattern PRIORITY_HIGH          = #const UV_PRIORITY_HIGH          +pattern PRIORITY_HIGHEST       = #const UV_PRIORITY_HIGHEST         foreign import ccall unsafe uv_hrtime :: IO Word64 @@ -847,8 +938,8 @@     , os_release :: T.Text     , os_version :: T.Text     , os_machine :: T.Text-    } deriving (Eq, Ord, Show, Generic)-       deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)+    }   deriving (Eq, Ord, Show, Generic)+        deriving anyclass (ShowT, EncodeJSON, ToValue, FromValue)  getOSName :: IO OSName getOSName = do
Z/IO/UV/Manager.hs view
@@ -37,9 +37,6 @@   , withUVRequest_   , withUVRequest'   , withUVRequestEx-  -- * uv_stream abstraction-  , initUVStream-  , UVStream(..)   -- * concurrent helpers   , forkBa   ) where@@ -50,15 +47,13 @@ import           Data.IORef import           Data.Bits (shiftL) import           Data.Word-import           Foreign.Ptr+import           GHC.Ptr import           Foreign.Storable import           GHC.Conc.Sync            (labelThread) import           System.IO.Unsafe import           Z.Data.Array import           Z.Data.PrimRef.PrimIORef-import           Z.IO.Buffered import           Z.IO.Exception-import           Z.IO.UV.Errno import           Z.IO.Resource import           Z.IO.UV.FFI @@ -363,101 +358,3 @@     {-# NOINLINE counter #-}     counter = unsafePerformIO $ newCounter 0 ------------------------------------------------------------------------------------ UVStream---- | A haskell data type wrap an @uv_stream_t@ inside------ 'UVStream' DO NOT provide thread safety! Use 'UVStream' concurrently in multiple--- threads will lead to undefined behavior.-data UVStream = UVStream-    { uvsHandle  :: {-# UNPACK #-} !(Ptr UVHandle)-    , uvsSlot    :: {-# UNPACK #-} !UVSlot-    , uvsManager :: UVManager-    , uvsClosed  :: {-# UNPACK #-} !(IORef Bool)    -- We have no thread-safe guarantee,-                                                    -- so no need to use atomic read&write-    }--instance Show UVStream where-    show (UVStream hdl slot uvm _) =-        "UVStream{uvsHandle=" ++ show hdl ++-                ",uvsSlot=" ++ show slot ++-                ",uvsManager=" ++ show uvm ++ "}"---- | Safely lock an uv manager and perform uv_handle initialization.------ Initialization an UV stream usually take two step:------   * allocate an uv_stream struct with proper size---   * lock a particular uv_loop from a uv manager, and perform custom initialization, such as @uv_tcp_init@.------ And this is what 'initUVStream' do, all you need to do is to provide the manager you want to hook the handle--- onto(usually the one on the same capability, i.e. the one obtained by 'getUVManager'),--- and provide a custom initialization function (which should throw an exception if failed).----initUVStream :: HasCallStack-             => (Ptr UVLoop -> Ptr UVHandle -> IO ())-             -> UVManager-             -> Resource UVStream-initUVStream f uvm = initResource-    (withUVManager uvm $ \ loop -> do-        hdl <- hs_uv_handle_alloc loop-        slot <- getUVSlot uvm (peekUVHandleData hdl)-        _ <- tryTakeMVar =<< getBlockMVar uvm slot   -- clear the parking spot-        f loop hdl `onException` hs_uv_handle_free hdl-        closed <- newIORef False-        return (UVStream hdl slot uvm closed))-    closeUVStream--closeUVStream :: UVStream -> IO ()-closeUVStream (UVStream hdl _ uvm closed) = withUVManager' uvm $ do-    c <- readIORef closed-    -- hs_uv_handle_close won't return error-    unless c $ writeIORef closed True >> hs_uv_handle_close hdl--instance Input UVStream where-    -- readInput :: HasCallStack => UVStream -> Ptr Word8 ->  Int -> IO Int-    {-# INLINABLE readInput  #-}-    readInput (UVStream hdl slot uvm closed) buf len = mask_ $ do-        c <- readIORef closed-        when c throwECLOSED-        -- set up buffer-        pokeBufferTable uvm slot buf len-        m <- getBlockMVar uvm slot-        -- clean up-        _ <- tryTakeMVar m--        throwUVIfMinus_ $ withUVManager' uvm (hs_uv_read_start hdl)-        -- since we are inside mask, this is the only place-        -- async exceptions could possibly kick in, and we should stop reading-        r <- takeMVar m `onException` (do-                -- normally we call 'uv_read_stop' in C read callback-                -- but when exception raise, here's the place to stop-                throwUVIfMinus_ $ withUVManager' uvm (uv_read_stop hdl)-                void (tryTakeMVar m))--        if  | r > 0  -> return r-            -- r == 0 should be impossible, since we guard this situation in c side-            | r == fromIntegral UV_EOF -> return 0-            | r < 0 ->  throwUVIfMinus (return r)--instance Output UVStream where-    -- writeOutput :: HasCallStack => UVStream -> Ptr Word8 -> Int -> IO ()-    {-# INLINABLE writeOutput  #-}-    writeOutput (UVStream hdl _ uvm closed) buf len = mask_ $ do-        c <- readIORef closed-        when c throwECLOSED-        m <- withUVManager' uvm $ do-            reqSlot <- getUVSlot uvm (hs_uv_write hdl buf len)-            m <- getBlockMVar uvm reqSlot-            _ <- tryTakeMVar m-            return m-        -- we can't cancel uv_write_t with current libuv,-        -- otherwise disaster will happen if buffer got collected.-        -- so we have to turn to uninterruptibleMask_'s help.-        -- i.e. writing UVStream is an uninterruptible operation.-        -- OS will guarantee writing TTY and socket will not-        -- hang forever anyway.-        throwUVIfMinus_  (uninterruptibleMask_ $ takeMVar m)----------------------------------------------------------------------------------
+ Z/IO/UV/UVStream.hs view
@@ -0,0 +1,150 @@+{-|+Module      : Z.IO.UV.UVStream+Description : IO manager based on libuv+Copyright   : (c) Dong Han, 2017-2018+License     : BSD+Maintainer  : winterland1989@gmail.com+Stability   : experimental+Portability : non-portable++This module provides 'UVStream' handle type.++-}++module Z.IO.UV.UVStream+  ( -- * uv_stream abstraction+    initUVStream+  , UVStream(..)+  , getUVStreamFD+  , closeUVStream+  , helloWorld, echo+  ) where++import          Control.Concurrent+import          Control.Monad+import          Z.IO.UV.Errno+import          Z.IO.UV.FFI+import          Z.IO.UV.Manager+import          Z.IO.Buffered+import          Z.IO.Exception+import          Z.IO.Resource+import          Data.IORef+import          GHC.Ptr++--------------------------------------------------------------------------------+-- UVStream++-- | A haskell data type wrap an @uv_stream_t@ inside+--+-- 'UVStream' DO NOT provide thread safety! Use 'UVStream' concurrently in multiple+-- threads will lead to undefined behavior.+data UVStream = UVStream+    { uvsHandle  :: {-# UNPACK #-} !(Ptr UVHandle)+    , uvsSlot    :: {-# UNPACK #-} !UVSlot+    , uvsManager :: UVManager+    , uvsClosed  :: {-# UNPACK #-} !(IORef Bool)    -- We have no thread-safe guarantee,+                                                    -- so no need to use atomic read&write+    }++instance Show UVStream where+    show (UVStream hdl slot uvm _) =+        "UVStream{uvsHandle=" ++ show hdl +++                ",uvsSlot=" ++ show slot +++                ",uvsManager=" ++ show uvm ++ "}"++-- | Safely lock an uv manager and perform uv_handle initialization.+--+-- Initialization an UV stream usually take two step:+--+--   * allocate an uv_stream struct with proper size+--   * lock a particular uv_loop from a uv manager, and perform custom initialization, such as @uv_tcp_init@.+--+-- And this is what 'initUVStream' do, all you need to do is to provide the manager you want to hook the handle+-- onto(usually the one on the same capability, i.e. the one obtained by 'getUVManager'),+-- and provide a custom initialization function (which should throw an exception if failed).+--+initUVStream :: HasCallStack+             => (Ptr UVLoop -> Ptr UVHandle -> IO ())+             -> UVManager+             -> Resource UVStream+initUVStream f uvm = initResource+    (withUVManager uvm $ \ loop -> do+        hdl <- hs_uv_handle_alloc loop+        slot <- getUVSlot uvm (peekUVHandleData hdl)+        _ <- tryTakeMVar =<< getBlockMVar uvm slot   -- clear the parking spot+        f loop hdl `onException` hs_uv_handle_free hdl+        closed <- newIORef False+        return (UVStream hdl slot uvm closed))+    closeUVStream++-- | Manually close a uv stream.+closeUVStream :: UVStream -> IO ()+closeUVStream (UVStream hdl _ uvm closed) = withUVManager' uvm $ do+    c <- readIORef closed+    -- hs_uv_handle_close won't return error+    unless c $ writeIORef closed True >> hs_uv_handle_close hdl++-- | Get stream fd+getUVStreamFD :: HasCallStack => UVStream -> IO UVFD+getUVStreamFD (UVStream hdl _ _ closed) = do+    c <- readIORef closed+    when c throwECLOSED+    throwUVIfMinus (hs_uv_fileno hdl)++instance Input UVStream where+    -- readInput :: HasCallStack => UVStream -> Ptr Word8 ->  Int -> IO Int+    {-# INLINABLE readInput  #-}+    readInput (UVStream hdl slot uvm closed) buf len = mask_ $ do+        c <- readIORef closed+        when c throwECLOSED+        -- set up buffer+        pokeBufferTable uvm slot buf len+        m <- getBlockMVar uvm slot+        -- clean up+        _ <- tryTakeMVar m++        throwUVIfMinus_ $ withUVManager' uvm (hs_uv_read_start hdl)+        -- since we are inside mask, this is the only place+        -- async exceptions could possibly kick in, and we should stop reading+        r <- takeMVar m `onException` (do+                -- normally we call 'uv_read_stop' in C read callback+                -- but when exception raise, here's the place to stop+                throwUVIfMinus_ $ withUVManager' uvm (uv_read_stop hdl)+                void (tryTakeMVar m))++        if  | r > 0  -> return r+            -- r == 0 should be impossible, since we guard this situation in c side+            | r == fromIntegral UV_EOF -> return 0+            | r < 0 ->  throwUVIfMinus (return r)++instance Output UVStream where+    -- writeOutput :: HasCallStack => UVStream -> Ptr Word8 -> Int -> IO ()+    {-# INLINABLE writeOutput  #-}+    writeOutput (UVStream hdl _ uvm closed) buf len = mask_ $ do+        c <- readIORef closed+        when c throwECLOSED+        m <- withUVManager' uvm $ do+            reqSlot <- getUVSlot uvm (hs_uv_write hdl buf len)+            m <- getBlockMVar uvm reqSlot+            _ <- tryTakeMVar m+            return m+        -- we can't cancel uv_write_t with current libuv,+        -- otherwise disaster will happen if buffer got collected.+        -- so we have to turn to uninterruptibleMask_'s help.+        -- i.e. writing UVStream is an uninterruptible operation.+        -- OS will guarantee writing TTY and socket will not+        -- hang forever anyway.+        throwUVIfMinus_  (uninterruptibleMask_ $ takeMVar m)++--------------------------------------------------------------------------------++-- | Write "hello world" to a 'UVStream'.+helloWorld :: UVStream -> IO ()+helloWorld uvs = writeOutput uvs (Ptr "hello world"#) 11++-- | Echo whatever received bytes.+echo :: UVStream -> IO ()+echo uvs = do+    i <- newBufferedInput uvs+    o <- newBufferedOutput uvs+    forever $ readBuffer i >>= writeBuffer o >> flushBuffer o
+ cbits/hs_uv_process.c view
@@ -0,0 +1,115 @@+/*+ * Copyright (c) 2017-2019 Dong Han+ *+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ * 3. Neither the names of the authors or the names of any contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+ * SUCH DAMAGE.+ */++#include <hs_uv.h>+#include <stdlib.h>++////////////////////////////////////////////////////////////////////////////////+//+// process+++void hs_uv_exit_cb(uv_process_t* handle, int64_t exit_status, int term_signal){+    HsInt slot = (HsInt)handle->data;+    uv_loop_t* loop = handle->loop;+    hs_loop_data* loop_data = loop->data;+    loop_data->buffer_size_table[slot] = (HsInt)exit_status;     +    loop_data->event_queue[loop_data->event_counter] = slot;   // push the slot to event queue+    loop_data->event_counter += 1;+    free_slot(loop_data, slot);  // free the uv_process_t+}++HsInt hs_uv_spawn(uv_loop_t* loop+                 , uv_process_options_t* options+                 , const char* file+                 , const char* all_args+                 , const size_t args_len+                 , const char* all_env+                 , const ssize_t env_len+                 , const char* cwd+                 , uv_stdio_container_t* stdio){+    int r, i;+    char* p;+    char **args = NULL, **env = NULL;++    hs_loop_data* loop_data = loop->data;+    HsInt slot = alloc_slot(loop_data);+    if (slot < 0) return UV_ENOMEM;+    uv_process_t* handle = +        (uv_process_t*)fetch_uv_struct(loop_data, slot);+    handle->data = (void*)slot;++    options->exit_cb = hs_uv_exit_cb;+    options->file = file;++    i = 0;+    args = (char**)malloc(sizeof(char*)*(args_len + 2));+    if (args == NULL) return UV_ENOMEM;+    args[i++] = (char*)file;+    if (args_len > 0) args[i++] = (char*)all_args;+    for(p = (char*)all_args; i <= args_len; p++){+        if (*p == 0) {+            args[i++] = p+1;+        }+    }+    args[i] = NULL;+    options->args = args;++    i = 0;+    if (env_len >= 0){+        env = (char**)malloc(sizeof(char*)*(env_len+1));+        if (env == NULL) return UV_ENOMEM;+        if (env_len > 0) env[i++] = (char*)all_env;+        for(p = (char*)all_env; i < env_len; p++){+            if (*p == 0) {+                env[i++] = p+1;+            }+        }+        env[i] = NULL;+    }+    options->env = env;++    options->stdio_count = 3;+    options->stdio = stdio;+    options->cwd = cwd;++    r = uv_spawn(loop, handle, options);++    free(args);+    if (env != NULL) free(env);++    if (r < 0) {+        free_slot(loop_data, slot);  // free the uv_process_t, the callback won't fired+        return (HsInt)r;+    } else { +        loop_data->buffer_size_table[slot] = (HsInt)handle->pid;     +        return slot;+    }+}
include/hs_uv.h view
@@ -648,6 +648,19 @@ HsInt hs_uv_fs_realpath_threaded(const char* path, char** result_path, uv_loop_t* loop);  ////////////////////////////////////////////////////////////////////////////////+// process++HsInt hs_uv_spawn(uv_loop_t* loop+                 , uv_process_options_t* options+                 , const char* file+                 , const char* all_args+                 , const size_t args_len+                 , const char* all_env+                 , const ssize_t env_len+                 , const char* cwd+                 , uv_stdio_container_t* container);++//////////////////////////////////////////////////////////////////////////////// // dns int uv__getaddrinfo_translate_error(int sys_err); HsInt hs_getaddrinfo(const char *node, const char *service,
test/Z/IO/Network/TCPSpec.hs view
@@ -24,7 +24,7 @@             longMsg = V.cycleN 2048 "abcdefg"             addr = SocketAddrInet 12345 inetLoopback -        serverThread <- forkIO $ startTCPServer defaultTCPServerConfig{ tcpListenAddr = addr } echoWorker+        serverThread <- forkIO $ startTCPServer defaultTCPServerConfig{ tcpListenAddr = addr } echo          threadDelay 100000 
+ test/Z/IO/ProcessSpec.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE OverloadedStrings #-}+module Z.IO.ProcessSpec where++import           Control.Concurrent+import           Control.Monad+import           Control.Monad.IO.Class+import           Data.Bits+import           Z.IO.Buffered+import           Z.IO.Process+import           Z.IO.Resource+import           Z.IO.FileSystem+import           Test.Hspec+import           Test.HUnit++spec :: Spec+spec = describe "process" $ do+    it "arguments should be passed" $ do+        (out, err, ecode) <- readProcess defaultProcessOptions{+                processFile = "echo"+            ,   processArgs = ["-n", "hello", "world", "good", "byte"]+            } ""++        assertEqual "echo back arguments" "hello world good byte" out+        assertEqual "echo exit successfully" ExitSuccess ecode++    it "UTF8 input should be passed" $ do+        (out, err, ecode) <- readProcess defaultProcessOptions{+                processFile = "cat"+            } "你好世界再见"++        assertEqual "cat echo back stdin" "你好世界再见" out+        assertEqual "cat exit successfully" ExitSuccess ecode++    it "environment should be passed" $ do+        (out, err, ecode) <- readProcess defaultProcessOptions{+                processFile = "env"+            ,   processEnv = Just [("hello", "world"), ("good", "byte")]+            } ""++        assertEqual "env echo back environment" "hello=world\ngood=byte\n" out+        assertEqual "env exit successfully" ExitSuccess ecode++    it "exit code should be passed" $ do+        (out, err, ecode) <- readProcess defaultProcessOptions{+                processFile = "sh"+            ,   processArgs = ["-c", "exit 8"]+            } ""++        assertEqual "exit code" (ExitFailure 8) ecode++    it "redirect stdin, stdout to file" $ do++        tempdir <- mkdtemp "stdio-filesystem-unit"+        let ifilename = tempdir <> "/test-stdin"+            ofilename = tempdir <> "/test-stdout"+        withResource (initFile ifilename (O_RDWR .|. O_CREAT) DEFAULT_MODE) $ \ input -> do+            bi <- newBufferedOutput' 4096 input+            writeBuffer bi "hello world" >> flushBuffer bi++        ecode <- withResource (initFile ifilename O_RDWR DEFAULT_MODE) $ \ input -> do++            withResource (initFile ofilename (O_RDWR .|. O_CREAT) DEFAULT_MODE) $ \ output -> do++                iF <- getFileFD input+                oF <- getFileFD output++                withResource (initProcess defaultProcessOptions{+                        processFile = "cat"+                    ,   processStdStreams = (ProcessInherit iF, ProcessInherit oF, ProcessIgnore)+                    }) $ \ (_, _, _, pstate) -> do++                        waitProcessExit pstate++        withResource (initFile ofilename (O_RDWR .|. O_CREAT) DEFAULT_MODE) $ \ output -> do+            bo <- newBufferedInput' 4096 output+            o <- readBuffer bo+            assertEqual "cat echo back" "hello world" o++        assertEqual "exit code" ecode ExitSuccess++        -- clean up file+        unlink ifilename+        unlink ofilename+        rmdir tempdir