///|
type GetAddrInfo

///|
type GetNameInfo

///|
type AddrInfo

///|
extern "c" fn uv_ai_next(addrinfo : AddrInfo) -> AddrInfo = "moonbit_uv_ai_next"

///|
extern "c" fn uv_getaddrinfo(
  self : Loop,
  req : GetAddrInfo,
  getaddrinfo_cb : (GetAddrInfo, Int, AddrInfo) -> Unit,
  node : Bytes,
  service : Bytes,
  hints : FixedArray[AddrInfo]
) -> Int = "moonbit_uv_getaddrinfo"

///|
extern "c" fn uv_getnameinfo(
  self : Loop,
  req : GetNameInfo,
  getnameinfo_cb : (GetNameInfo, Int, AddrInfo) -> Unit,
  addr : Sockaddr,
  flags : Int
) -> Int = "moonbit_uv_getnameinfo"

///|
pub fn getaddrinfo(
  self : Loop,
  req : GetAddrInfo,
  getaddrinfo_cb : (GetAddrInfo, AddrInfo) -> Unit,
  error_cb : (GetAddrInfo, Errno) -> Unit,
  node : Bytes,
  service : Bytes,
  hints : FixedArray[AddrInfo]
) -> Unit!Errno {
  fn uv_cb(req : GetAddrInfo, status : Int, addrinfo : AddrInfo) {
    if status < 0 {
      error_cb(req, Errno::of_int(status))
    } else {
      getaddrinfo_cb(req, addrinfo)
    }
  }

  let status = uv_getaddrinfo(self, req, uv_cb, node, service, hints)
  if status < 0 {
    raise Errno::of_int(status)
  }
}