// 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.
///|
type GetAddrInfo
///|
extern "c" fn uv_getaddrinfo_make() -> GetAddrInfo = "moonbit_uv_getaddrinfo_make"
///|
pub impl ToReq for GetAddrInfo with to_req(self : GetAddrInfo) -> Req = "%identity"
///|
type AddrInfoHints
///|
extern "c" fn uv_addrinfo_hints(
flags : Int,
family : Int,
socktype : Int,
protocol : Int,
) -> AddrInfoHints = "moonbit_uv_addrinfo_hints"
///|
struct AddrInfoFlags(Int)
///|
extern "c" fn uv_AI_PASSIVE() -> Int = "moonbit_uv_AI_PASSIVE"
///|
let _AI_PASSIVE : Int = uv_AI_PASSIVE()
///|
extern "c" fn uv_AI_CANONNAME() -> Int = "moonbit_uv_AI_CANONNAME"
///|
let _AI_CANONNAME : Int = uv_AI_CANONNAME()
///|
extern "c" fn uv_AI_NUMERICHOST() -> Int = "moonbit_uv_AI_NUMERICHOST"
///|
let _AI_NUMERICHOST : Int = uv_AI_NUMERICHOST()
///|
extern "c" fn uv_AI_NUMERICSERV() -> Int = "moonbit_uv_AI_NUMERICSERV"
///|
let _AI_NUMERICSERV : Int = uv_AI_NUMERICSERV()
///|
extern "c" fn uv_AI_ALL() -> Int = "moonbit_uv_AI_ALL"
///|
let _AI_ALL : Int = uv_AI_ALL()
///|
extern "c" fn uv_AI_ADDRCONFIG() -> Int = "moonbit_uv_AI_ADDRCONFIG"
///|
let _AI_ADDRCONFIG : Int = uv_AI_ADDRCONFIG()
///|
extern "c" fn uv_AI_V4MAPPED() -> Int = "moonbit_uv_AI_V4MAPPED"
///|
let _AI_V4MAPPED : Int = uv_AI_V4MAPPED()
///|
pub fn AddrInfoFlags::new(
passive? : Bool = false,
canonname? : Bool = false,
numeric_host? : Bool = false,
numeric_serv? : Bool = false,
all? : Bool = false,
addrconfig? : Bool = false,
v4mapped? : Bool = false,
) -> AddrInfoFlags {
let mut flags = 0
if passive {
flags = flags | _AI_PASSIVE
}
if canonname {
flags = flags | _AI_CANONNAME
}
if numeric_host {
flags = flags | _AI_NUMERICHOST
}
if numeric_serv {
flags = flags | _AI_NUMERICSERV
}
if all {
flags = flags | _AI_ALL
}
if addrconfig {
flags = flags | _AI_ADDRCONFIG
}
if v4mapped {
flags = flags | _AI_V4MAPPED
}
return flags
}
///|
pub fn AddrInfoHints::new(
flags? : AddrInfoFlags,
family? : AddressFamily,
socktype? : SockType,
protocol? : Protocol,
) -> AddrInfoHints {
let flags = match flags {
Some(flags) => flags.0
None => 0
}
let family = match family {
Some(family) => family.to_int()
None => _AF_UNSPEC
}
let socktype = match socktype {
Some(socktype) => socktype.to_int()
None => 0
}
let protocol = match protocol {
Some(protocol) => protocol.to_int()
None => 0
}
uv_addrinfo_hints(flags, family, socktype, protocol)
}
///|
priv type AddrInfoResults
///|
#borrow(addrinfo_results, cb)
extern "c" fn uv_addrinfo_results_iterate(
addrinfo_results : AddrInfoResults,
cb : (Int, Int, Int, Int, Sockaddr, @c.Pointer[Byte]) -> Bool,
) -> Bool = "moonbit_uv_addrinfo_results_iterate"
///|
struct AddrInfo {
family : Int
socktype : Int
protocol : Int
addr : Sockaddr
canonname : Bytes?
}
///|
extern "c" fn uv_AF_INET() -> Int = "moonbit_uv_AF_INET"
///|
let _AF_INET : Int = uv_AF_INET()
///|
extern "c" fn uv_AF_INET6() -> Int = "moonbit_uv_AF_INET6"
///|
let _AF_INET6 : Int = uv_AF_INET6()
///|
extern "c" fn uv_AF_UNSPEC() -> Int = "moonbit_uv_AF_UNSPEC"
///|
let _AF_UNSPEC : Int = uv_AF_UNSPEC()
///|
/// Represents the address family for network communication, specifying the
/// format of network addresses.
///
/// Constructors:
///
/// * `Inet` : IPv4 address family
/// * `Inet6` : IPv6 address family
///
/// Example:
///
/// ```moonbit nocheck
/// let ipv4 = AddressFamily::inet()
/// let ipv6 = AddressFamily::inet6()
/// @assert.t(ipv4 is Inet)
/// @assert.t(ipv6 is Inet6)
/// ```
pub(all) enum AddressFamily {
Inet
Inet6
}
///|
pub fn AddressFamily::inet() -> AddressFamily {
return Inet
}
///|
pub fn AddressFamily::inet6() -> AddressFamily {
return Inet6
}
///|
fn AddressFamily::of_int(self : Int) -> AddressFamily raise Errno {
if self == _AF_INET {
return Inet
}
if self == _AF_INET6 {
return Inet6
}
raise EINVAL
}
///|
fn AddressFamily::to_int(self : AddressFamily) -> Int {
match self {
Inet => _AF_INET
Inet6 => _AF_INET6
}
}
///|
pub fn AddrInfo::family(self : AddrInfo) -> AddressFamily raise Errno {
AddressFamily::of_int(self.family)
}
///|
pub fn AddrInfo::addr(self : AddrInfo) -> Sockaddr {
self.addr
}
///|
pub fn AddrInfo::socktype(self : AddrInfo) -> SockType raise Errno {
return SockType::of_int(self.socktype)
}
///|
pub fn AddrInfo::protocol(self : AddrInfo) -> Protocol raise Errno {
Protocol::of_int(self.protocol)
}
///|
pub fn AddrInfo::canonname(self : AddrInfo) -> Bytes? {
self.canonname
}
///|
fn AddrInfoResults::iterator(self : AddrInfoResults) -> Iter[AddrInfo] {
let items : Array[AddrInfo] = []
ignore(
uv_addrinfo_results_iterate(self, fn(
_,
family,
socktype,
protocol,
addr,
canonname,
) {
let canonname = if canonname.is_null() {
None
} else {
let buffer = @buffer.new()
for i = 0; canonname[i] != 0; i = i + 1 {
buffer.write_byte(canonname[i])
}
Some(buffer.contents())
}
items.push({ family, socktype, protocol, addr, canonname })
false
}),
)
let mut i = 0
Iter::new(fn() {
if i < items.length() {
let item = items[i]
i = i + 1
Some(item)
} else {
None
}
})
}
///|
fn AddrInfoResults::iter(self : AddrInfoResults) -> Iter[AddrInfo] {
self.iterator().iter()
}
///|
#owned(uv, req, node, service, hints)
extern "c" fn uv_getaddrinfo(
uv : Loop,
req : GetAddrInfo,
getaddrinfo_cb : (GetAddrInfo, Int, AddrInfoResults) -> Unit,
node : Bytes,
service : Bytes,
hints : AddrInfoHints,
) -> Int = "moonbit_uv_getaddrinfo"
///|
#owned(uv, req, node, service)
extern "c" fn uv_getaddrinfo_no_hints(
uv : Loop,
req : GetAddrInfo,
getaddrinfo_cb : (GetAddrInfo, Int, AddrInfoResults) -> Unit,
node : Bytes,
service : Bytes,
hints : @c.Pointer[Unit],
) -> Int = "moonbit_uv_getaddrinfo"
///|
#as_free_fn
pub fn Loop::getaddrinfo(
self : Loop,
getaddrinfo_cb : (Iter[AddrInfo]) -> Unit,
error_cb : (Errno) -> Unit,
node : Bytes,
service : Bytes,
hints? : AddrInfoHints,
) -> GetAddrInfo raise Errno {
fn uv_cb(_ : GetAddrInfo, status : Int, addrinfo : AddrInfoResults) {
if status < 0 {
error_cb(Errno::of_int(status))
} else {
getaddrinfo_cb(addrinfo.iter())
}
}
let req = uv_getaddrinfo_make()
let status = match hints {
Some(hints) => uv_getaddrinfo(self, req, uv_cb, node, service, hints)
None =>
uv_getaddrinfo_no_hints(
self,
req,
uv_cb,
node,
service,
@c.Pointer::null(),
)
}
if status < 0 {
raise Errno::of_int(status)
}
return req
}
///|
type GetNameInfo
///|
extern "c" fn uv_getnameinfo_make() -> GetNameInfo = "moonbit_uv_getnameinfo_make"
///|
pub impl ToReq for GetNameInfo with to_req(self : GetNameInfo) -> Req = "%identity"
///|
#owned(uv, req, getnameinfo_cb, addr)
extern "c" fn uv_getnameinfo(
uv : Loop,
req : GetNameInfo,
getnameinfo_cb : (GetNameInfo, Int, Bytes?, Bytes?) -> Unit,
addr : Sockaddr,
flags : Int,
) -> Int = "moonbit_uv_getnameinfo"
///|
#as_free_fn
pub fn Loop::getnameinfo(
self : Loop,
getnameinfo_cb : (Bytes?, Bytes?) -> Unit,
error_cb : (Errno) -> Unit,
addr : Sockaddr,
flags? : Int = 0,
) -> GetNameInfo raise Errno {
fn uv_cb(_ : GetNameInfo, status : Int, hostname : Bytes?, service : Bytes?) {
if status < 0 {
error_cb(Errno::of_int(status))
} else {
getnameinfo_cb(hostname, service)
}
}
let req = uv_getnameinfo_make()
let status = uv_getnameinfo(self, req, uv_cb, addr, flags)
if status < 0 {
raise Errno::of_int(status)
}
return req
}