// 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.
///|
#owned(buffer)
extern "c" fn uv_os_uname(buffer : Bytes) -> Int = "moonbit_uv_os_uname"
///|
struct Utsname {
sysname : BytesView
release : BytesView
version : BytesView
machine : BytesView
}
///|
pub fn Utsname::sysname(self : Utsname) -> BytesView {
self.sysname
}
///|
pub fn Utsname::release(self : Utsname) -> BytesView {
self.release
}
///|
pub fn Utsname::version(self : Utsname) -> BytesView {
self.version
}
///|
pub fn Utsname::machine(self : Utsname) -> BytesView {
self.machine
}
///|
/// Retrieves system information including the system name, release, version, and
/// machine architecture.
///
/// Returns a `Utsname` structure containing system identification information.
///
/// Throws an error of type `Errno` if the underlying system call fails.
///
/// Example:
///
/// ```moonbit nocheck
/// let info = @uv.os_uname()
/// println(info.sysname())
/// println(info.release())
/// println(info.machine())
/// ```
pub fn os_uname() -> Utsname raise Errno {
let buffer = Bytes::make(256 * 4, 0)
let status = uv_os_uname(buffer)
if status < 0 {
raise Errno::of_int(status)
}
fn shrink(s : BytesView) -> BytesView {
let mut len = 0
for b in s {
if b == 0 {
break
}
len = len + 1
}
s[:len]
}
let sysname = shrink(buffer[0:256])
let release = shrink(buffer[256:512])
let version = shrink(buffer[512:768])
let machine = shrink(buffer[768:1024])
{ sysname, release, version, machine }
}
///|
#owned(bytes, size)
extern "c" fn uv_os_tmpdir(bytes : Bytes, size : FixedArray[Int]) -> Int = "moonbit_uv_os_tmpdir"
///|
/// Retrieves the path to the system's temporary directory.
///
/// Returns a `String` containing the path to the temporary directory where
/// temporary files can be created.
///
/// Throws an error of type `Errno` if the underlying system call fails or if
/// there are insufficient resources to complete the operation.
///
/// Example:
///
/// ```moonbit nocheck
/// println(@uv.os_tmpdir())
/// ```
pub fn os_tmpdir() -> Bytes raise Errno {
let mut buffer = Bytes::make(64, 0)
let length : FixedArray[Int] = [buffer.length()]
let mut status = uv_os_tmpdir(buffer, length)
if status == _ENOBUFS {
buffer = Bytes::make(length[0] + 1, 0)
status = uv_os_tmpdir(buffer, length)
}
if status < 0 {
raise Errno::of_int(status)
}
buffer.shrink(length[0])
buffer
}
///|
#owned(bytes, size)
extern "c" fn uv_exepath(bytes : Bytes, size : FixedArray[Int]) -> Int = "moonbit_uv_exepath"
///|
pub fn exepath() -> Bytes raise Errno {
let mut buffer = Bytes::make(256, 0)
let length : FixedArray[Int] = [buffer.length()]
let mut status = uv_exepath(buffer, length)
if status == _ENOBUFS {
buffer = Bytes::make(length[0], 0)
status = uv_exepath(buffer, length)
}
if status < 0 {
raise Errno::of_int(status)
}
buffer.shrink(length[0])
buffer
}
///|
#owned(bytes, size)
extern "c" fn uv_os_homedir(bytes : Bytes, size : FixedArray[Int]) -> Int = "moonbit_uv_os_homedir"
///|
pub fn os_homedir() -> Bytes raise Errno {
let mut buffer = Bytes::make(256, 0)
let length : FixedArray[Int] = [buffer.length()]
let mut status = uv_os_homedir(buffer, length)
if status == _ENOBUFS {
buffer = Bytes::make(length[0], 0)
status = uv_os_homedir(buffer, length)
}
if status < 0 {
raise Errno::of_int(status)
}
buffer.shrink(length[0])
buffer
}
///|
#owned(path)
extern "c" fn uv_chdir(path : Bytes) -> Int = "moonbit_uv_chdir"
///|
pub fn chdir(path : Bytes) -> Unit raise Errno {
let status = uv_chdir(path)
if status < 0 {
raise Errno::of_int(status)
}
}
///|
struct CpuInfo {
model : Bytes
speed : Int
cpu_times : CpuTimes
}
///|
pub fn CpuInfo::model(self : CpuInfo) -> Bytes {
self.model
}
///|
pub fn CpuInfo::speed(self : CpuInfo) -> Int {
self.speed
}
///|
pub fn CpuInfo::cpu_times(self : CpuInfo) -> CpuTimes {
self.cpu_times
}
///|
struct CpuTimes {
user : UInt64
nice : UInt64
sys : UInt64
idle : UInt64
irq : UInt64
}
///|
pub fn CpuTimes::user(self : CpuTimes) -> UInt64 {
self.user
}
///|
pub fn CpuTimes::nice(self : CpuTimes) -> UInt64 {
self.nice
}
///|
pub fn CpuTimes::sys(self : CpuTimes) -> UInt64 {
self.sys
}
///|
pub fn CpuTimes::idle(self : CpuTimes) -> UInt64 {
self.idle
}
///|
pub fn CpuTimes::irq(self : CpuTimes) -> UInt64 {
self.irq
}
///|
#owned(cpu_infos, count)
extern "c" fn uv_cpu_info(
cpu_infos : FixedArray[@c.Pointer[CpuInfo]],
count : FixedArray[Int],
) -> Int = "moonbit_uv_cpu_info"
///|
extern "c" fn uv_cpu_info_sizeof() -> UInt64 = "moonbit_uv_cpu_info_sizeof"
///|
impl @sizeof.Sized for CpuInfo with size() -> @c.Size {
uv_cpu_info_sizeof()
}
///|
extern "c" fn uv_cpu_info_get_model(
cpu_info : @c.Pointer[CpuInfo],
) -> @c.Pointer[Byte] = "moonbit_uv_cpu_info_get_model"
///|
extern "c" fn uv_cpu_info_get_speed(cpu_info : @c.Pointer[CpuInfo]) -> Int = "moonbit_uv_cpu_info_get_speed"
///|
extern "c" fn uv_cpu_info_get_cpu_times_user(
cpu_info : @c.Pointer[CpuInfo],
) -> UInt64 = "moonbit_uv_cpu_info_get_cpu_times_user"
///|
extern "c" fn uv_cpu_info_get_cpu_times_nice(
cpu_info : @c.Pointer[CpuInfo],
) -> UInt64 = "moonbit_uv_cpu_info_get_cpu_times_nice"
///|
extern "c" fn uv_cpu_info_get_cpu_times_sys(
cpu_info : @c.Pointer[CpuInfo],
) -> UInt64 = "moonbit_uv_cpu_info_get_cpu_times_sys"
///|
extern "c" fn uv_cpu_info_get_cpu_times_idle(
cpu_info : @c.Pointer[CpuInfo],
) -> UInt64 = "moonbit_uv_cpu_info_get_cpu_times_idle"
///|
extern "c" fn uv_cpu_info_get_cpu_times_irq(
cpu_info : @c.Pointer[CpuInfo],
) -> UInt64 = "moonbit_uv_cpu_info_get_cpu_times_irq"
///|
impl @pointer.Load for CpuInfo with load(self : @c.Pointer[CpuInfo]) -> CpuInfo {
let model = {
let buffer = @buffer.new()
let pointer = uv_cpu_info_get_model(self)
for i = 0; pointer[i] != 0; i = i + 1 {
buffer.write_byte(pointer[i])
}
buffer.contents()
}
let speed = uv_cpu_info_get_speed(self)
let cpu_times = {
user: uv_cpu_info_get_cpu_times_user(self),
nice: uv_cpu_info_get_cpu_times_nice(self),
sys: uv_cpu_info_get_cpu_times_sys(self),
idle: uv_cpu_info_get_cpu_times_idle(self),
irq: uv_cpu_info_get_cpu_times_irq(self),
}
{ model, speed, cpu_times }
}
///|
extern "c" fn uv_free_cpu_info(cpu_infos : @c.Pointer[CpuInfo], count : Int) = "moonbit_uv_free_cpu_info"
///|
/// Returns current CPU information.
///
/// Example:
///
/// ```moonbit nocheck
/// let cpu_infos = @uv.cpu_info()
/// for cpu_info in cpu_infos {
/// println(cpu_info.model())
/// }
/// ```
pub fn cpu_info() -> Array[CpuInfo] raise Errno {
let uv_cpu_infos : FixedArray[@c.Pointer[CpuInfo]] = [@c.Pointer::null()]
let count : FixedArray[Int] = [0]
let status = uv_cpu_info(uv_cpu_infos, count)
if status < 0 {
raise Errno::of_int(status)
}
let uv_cpu_infos = uv_cpu_infos[0]
let count = count[0]
let cpu_infos = []
for i in 0.. UInt64 = "moonbit_uv_get_free_memory"
///|
pub extern "c" fn get_total_memory() -> UInt64 = "moonbit_uv_get_total_memory"
///|
pub extern "c" fn get_constrained_memory() -> UInt64 = "moonbit_uv_get_constrained_memory"
///|
pub extern "c" fn get_available_memory() -> UInt64 = "moonbit_uv_get_available_memory"
///|
pub struct Timeval {
sec : Int64
usec : Int64
}
///|
#owned(name, size)
extern "c" fn uv_os_gethostname(name : Bytes, size : Ref[Int]) -> Int = "moonbit_uv_os_gethostname"
///|
pub fn os_gethostname() -> Bytes raise Errno {
let mut buffer = Bytes::make(257, 0)
let length = Ref::new(buffer.length())
let mut status = uv_os_gethostname(buffer, length)
if status == _ENOBUFS {
buffer = Bytes::make(length.val, 0)
length.val = buffer.length()
status = uv_os_gethostname(buffer, length)
}
if status < 0 {
raise Errno::of_int(status)
}
buffer.shrink(length.val)
buffer
}
///|
#borrow(uptime)
extern "c" fn uv_uptime(uptime : Ref[Double]) -> Int = "moonbit_uv_uptime"
///|
pub fn uptime() -> Double raise Errno {
let uptime : Ref[Double] = Ref::new(0.0)
let status = uv_uptime(uptime)
if status < 0 {
raise Errno::of_int(status)
}
uptime.val
}
///|
#owned(rss)
extern "c" fn uv_resident_set_memory(rss : Ref[UInt64]) -> Int = "moonbit_uv_resident_set_memory"
///|
pub fn resident_set_memory() -> UInt64 raise Errno {
let rss : Ref[UInt64] = Ref::new(0)
let status = uv_resident_set_memory(rss)
if status < 0 {
raise Errno::of_int(status)
}
rss.val
}
///|
#owned(avg)
extern "c" fn uv_loadavg(avg : FixedArray[Double]) = "moonbit_uv_loadavg"
///|
pub fn loadavg() -> (Double, Double, Double) {
let avg = FixedArray::make(3, 0.0)
uv_loadavg(avg)
(avg[0], avg[1], avg[2])
}
///|
pub extern "c" fn available_parallelism() -> Int = "moonbit_uv_available_parallelism"
///|
#owned(priority)
extern "c" fn uv_os_getpriority(pid : Pid, priority : Ref[Int]) -> Int = "moonbit_uv_os_getpriority"
///|
/// Retrieves the scheduling priority of the process specified by pid. The
/// returned value of priority is between -20 (high priority) and 19
/// (low priority).
///
/// **Note**: On Windows, the returned priority will equal one of the
/// `Priority` constants.
pub fn os_getpriority(pid : Pid) -> Int raise Errno {
let priority : Ref[Int] = Ref::new(0)
let status = uv_os_getpriority(pid, priority)
if status < 0 {
raise Errno::of_int(status)
}
priority.val
}
///|
pub const PriorityLow = 19
///|
pub const PriorityBelowNormal = 10
///|
pub const PriorityNormal = 0
///|
pub const PriorityAboveNormal = -7
///|
pub const PriorityHigh = -14
///|
pub const PriorityHighest = -20
///|
extern "c" fn uv_os_setpriority(pid : Pid, priority : Int) -> Int = "moonbit_uv_os_setpriority"
///|
/// Sets the scheduling priority of the process specified by `pid`. The
/// `priority` value range is between -20 (high priority) and 19 (low priority).
///
/// **Note**: On Windows, this function utilizes `SetPriorityClass()`. The
/// `priority` argument is mapped to a Windows priority class. When retrieving
/// the process priority, the result will equal one of the `@uv.Priority
/// constants, and not necessarily the exact value of `priority`.
///
/// **Note**: On Windows, setting `@uv.PriorityHighest` will only work for
/// elevated user, for others it will be silently reduced to `@uv.PriorityHigh`.
pub fn os_setpriority(pid : Pid, priority : Int) -> Unit raise Errno {
let status = uv_os_setpriority(pid, priority)
if status < 0 {
raise Errno::of_int(status)
}
}