// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
pub extern "c" fn disable_stdio_inheritance() = "moonbit_uv_disable_stdio_inheritance"
///|
type Process
///|
pub impl ToHandle for Process with to_handle(self : Process) -> Handle = "%identity"
///|
pub impl ToHandle for Process with of_handle(handle) = "%identity"
///|
struct Pid(Int) derive(Show, Eq, Compare, Hash)
///|
pub fn Pid::to_int(self : Pid) -> Int {
self.0
}
///|
pub fn Pid::of_int(pid : Int) -> Pid {
Pid(pid)
}
///|
#owned(process)
extern "c" fn uv_process_get_pid(process : Process) -> Int = "moonbit_uv_process_get_pid"
///|
pub fn Process::pid(self : Process) -> Pid {
return uv_process_get_pid(self)
}
///|
extern "c" fn uv_process_make() -> Process = "moonbit_uv_process_make"
///|
type ProcessOptions
///|
priv enum ProcessFlag {
SetUID = 1
SetGID = 2
WindowsVerbatimArguments = 4
Detached = 8
WindowsHide = 16
WindowsHideConsole = 32
WindowsHideGui = 64
WindowsFilePathExactName = 128
}
///|
fn ProcessFlag::to_int(self : ProcessFlag) -> UInt = "%identity"
///|
extern "c" fn uv_process_options_make() -> ProcessOptions = "moonbit_uv_process_options_make"
///|
#owned(process_options)
extern "c" fn uv_process_options_set_exit_cb(
process_options : ProcessOptions,
exit_cb : (Process, Int64, Int) -> Unit,
) = "moonbit_uv_process_options_set_exit_cb"
///|
#owned(process_options, file)
extern "c" fn uv_process_options_set_file(
process_options : ProcessOptions,
file : Bytes,
) = "moonbit_uv_process_options_set_file"
///|
#owned(process_options, args)
extern "c" fn uv_process_options_set_args(
process_options : ProcessOptions,
args : FixedArray[Bytes?],
) = "moonbit_uv_process_options_set_args"
///|
#owned(process_options, env)
extern "c" fn uv_process_options_set_env(
process_options : ProcessOptions,
env : FixedArray[Bytes?],
) = "moonbit_uv_process_options_set_env"
///|
#owned(process_options, cwd)
extern "c" fn uv_process_options_set_cwd(
process_options : ProcessOptions,
cwd : Bytes,
) = "moonbit_uv_process_options_set_cwd"
///|
#owned(process_options)
extern "c" fn uv_process_options_set_flags(
process_options : ProcessOptions,
flags : UInt,
) = "moonbit_uv_process_options_set_flags"
///|
#owned(process_options, stdio)
extern "c" fn uv_process_options_set_stdio(
process_options : ProcessOptions,
stdio : FixedArray[StdioContainer],
) = "moonbit_uv_process_options_set_stdio"
///|
#owned(process_options)
extern "c" fn uv_process_options_set_uid(
process_options : ProcessOptions,
uid : Uid,
) = "moonbit_uv_process_options_set_uid"
///|
#owned(process_options)
extern "c" fn uv_process_options_set_gid(
process_options : ProcessOptions,
gid : Gid,
) = "moonbit_uv_process_options_set_gid"
///|
pub fn ProcessOptions::new(
file : Bytes,
args : Array[Bytes],
env? : Array[Bytes],
cwd? : Bytes,
stdio? : Array[StdioContainer],
uid? : Uid,
gid? : Gid,
exit_cb : (Process, Int64, Int) -> Unit,
) -> ProcessOptions {
let mut flags = 0U
let options = uv_process_options_make()
uv_process_options_set_exit_cb(options, exit_cb)
uv_process_options_set_file(options, file)
let args = FixedArray::makei(args.length() + 1, fn(i) {
if i == args.length() {
return None
} else {
return Some(args[i])
}
})
uv_process_options_set_args(options, args)
if env is Some(env) {
let env = FixedArray::makei(env.length() + 1, fn(i) {
if i == env.length() {
return None
} else {
return Some(env[i])
}
})
uv_process_options_set_env(options, env)
}
if cwd is Some(cwd) {
uv_process_options_set_cwd(options, cwd)
}
if stdio is Some(stdio) {
let stdio = FixedArray::makei(stdio.length(), fn(i) { return stdio[i] })
uv_process_options_set_stdio(options, stdio)
}
if uid is Some(uid) {
flags = flags | SetUID.to_int()
uv_process_options_set_uid(options, uid)
}
if gid is Some(gid) {
flags = flags | SetGID.to_int()
uv_process_options_set_gid(options, gid)
}
uv_process_options_set_flags(options, flags)
return options
}
///|
struct StdioContainer(Bytes)
///|
pub extern "c" fn StdioContainer::ignore() -> StdioContainer = "moonbit_uv_stdio_container_ignore"
///|
#owned(stream)
extern "c" fn uv_stdio_container_create_pipe(
stream : Stream,
readable? : Bool = false,
writable? : Bool = false,
non_block? : Bool = false,
) -> StdioContainer = "moonbit_uv_stdio_container_create_pipe"
///|
pub fn[Stream : ToStream] StdioContainer::create_pipe(
stream : Stream,
readable? : Bool = false,
writable? : Bool = false,
non_block? : Bool = false,
) -> StdioContainer {
return uv_stdio_container_create_pipe(
stream.to_stream(),
readable~,
writable~,
non_block~,
)
}
///|
extern "c" fn uv_stdio_container_inherit_fd(fd : Int) -> StdioContainer = "moonbit_uv_stdio_container_inherit_fd"
///|
pub fn StdioContainer::inherit_file(file : File) -> StdioContainer {
return uv_stdio_container_inherit_fd(file.0)
}
///|
#owned(stream)
pub extern "c" fn StdioContainer::inherit_stream(
stream : Stream,
) -> StdioContainer = "moonbit_uv_stdio_container_inherit_stream"
///|
pub(all) struct Uid(UInt64)
///|
pub(all) struct Gid(UInt64)
///|
#owned(uv, process, options)
extern "c" fn uv_spawn(
uv : Loop,
process : Process,
options : ProcessOptions,
) -> Int = "moonbit_uv_spawn"
///|
#as_free_fn
pub fn Loop::spawn(
self : Loop,
options : ProcessOptions,
) -> Process raise Errno {
let process = uv_process_make()
let status = uv_spawn(self, process, options)
if status < 0 {
raise Errno::of_int(status)
}
return process
}
///|
#owned(process)
extern "c" fn uv_process_kill(process : Process, signum : Int) -> Int = "moonbit_uv_process_kill"
///|
pub fn Process::kill(self : Process, signum : Signum) -> Unit raise Errno {
let status = uv_process_kill(self, signum.0)
if status < 0 {
raise Errno::of_int(status)
}
}
///|
extern "c" fn uv_kill(pid : Int, signum : Signum) -> Int = "moonbit_uv_kill"
///|
pub fn kill(pid : Pid, signum : Signum) -> Unit raise Errno {
let status = uv_kill(pid.0, signum.0)
if status < 0 {
raise Errno::of_int(status)
}
}
///|
pub extern "c" fn os_getpid() -> Pid = "moonbit_uv_os_getpid"
///|
pub extern "c" fn os_getppid() -> Pid = "moonbit_uv_os_getppid"