bun_cares_sys/lib.rs
1#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
2#![warn(unused_must_use)]
3
4#[path = "c_ares.rs"]
5pub mod c_ares_draft;
6
7/// Winsock typedefs not provided by `libc` on `x86_64-pc-windows-msvc`.
8#[cfg(windows)]
9pub mod winsock {
10 use core::ffi::{c_int, c_long};
11 pub(crate) type socklen_t = c_int; // ws2tcpip.h: `typedef int socklen_t;`
12 // Same nominal type as `bun_sys::posix::sockaddr*`; sin_addr is `in_addr{s_addr}`
13 // (vs the previous `[u8;4]`) but the only caller (c_ares.rs `get_sockaddr`)
14 // takes `&raw mut → cast<c_void>`, so the field's nominal type is transparent.
15 pub(crate) use bun_libuv_sys::{sockaddr, sockaddr_in, sockaddr_in6};
16 #[repr(C)]
17 #[derive(Clone, Copy)]
18 pub struct timeval {
19 pub tv_sec: c_long,
20 pub tv_usec: c_long,
21 }
22 /// c-ares' `ares.h` defines its own POSIX-layout `struct iovec { void *iov_base; size_t iov_len; }`
23 /// on Windows for the `asendv` socket-function callback — it does NOT use `WSABUF`.
24 #[repr(C)]
25 #[derive(Clone, Copy)]
26 pub struct iovec {
27 pub iov_base: *mut core::ffi::c_void,
28 pub iov_len: usize,
29 }
30}
31
32/// The full c-ares FFI module. The temporary inline scaffold that previously
33/// duplicated `ares_socklen_t` / `AddrInfo_hints` / `ares_inet_*` here has been
34/// collapsed to a re-export of the canonical `c_ares.rs` module now that it is
35/// un-gated. `c_ares` and `c_ares_draft` resolve to the SAME module, so the two
36/// `AddrInfo_hints` definitions are now nominally identical (previously a latent
37/// type-mismatch footgun for callers mixing the two paths).
38pub use c_ares_draft as c_ares;
39
40// Crate-root re-exports for callers that reference `bun_cares_sys::ares_inet_*`
41// directly (e.g. `bun_boringssl`).
42pub use c_ares::{ares_inet_ntop, ares_inet_pton};
43
44/// Thin wrapper over `ares_inet_ntop`: writes the textual address into `dst`
45/// and returns the slice up to (excluding) the trailing NUL on success.
46/// `dst[len] == 0` is guaranteed on `Some`, so callers needing a C string can
47/// rely on it.
48///
49/// # Safety
50/// `src` must point to a valid `in_addr` (af == AF_INET) or `in6_addr`
51/// (af == AF_INET6).
52#[inline]
53pub unsafe fn ntop(
54 af: core::ffi::c_int,
55 src: *const core::ffi::c_void,
56 dst: &mut [u8],
57) -> Option<&[u8]> {
58 // SAFETY: caller contract guarantees `src` points to a valid `in_addr` /
59 // `in6_addr` matching `af`; `dst` is a Rust slice so `dst.as_mut_ptr()` is
60 // valid for `dst.len()` writes, and `ares_inet_ntop` writes at most `size`
61 // bytes (including the trailing NUL) per c-ares docs.
62 if unsafe {
63 c_ares::ares_inet_ntop(
64 af,
65 src,
66 dst.as_mut_ptr(),
67 dst.len() as c_ares::ares_socklen_t,
68 )
69 }
70 .is_null()
71 {
72 return None;
73 }
74 Some(bun_core::ffi::slice_to_nul(dst))
75}