1use super::super::c;
2
3/// The windows `sockaddr_in6` type is a union with accessor functions which
4/// are not `const fn`. Define our own layout-compatible version so that we
5/// can transmute in and out of it.
6#[cfg(windows)]
7#[repr(C)]
8struct sockaddr_in6 {
9    sin6_family: u16,
10    sin6_port: u16,
11    sin6_flowinfo: u32,
12    sin6_addr: c::in6_addr,
13    sin6_scope_id: u32,
14}
15
16#[cfg(not(windows))]
17#[inline]
18pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
19    addr.s_addr
20}
21
22#[cfg(not(feature = "std"))]
23#[cfg(windows)]
24#[inline]
25pub(crate) const fn in_addr_s_addr(addr: c::in_addr) -> u32 {
26    // This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`.
27    unsafe { core::mem::transmute(addr) }
28}
29
30// TODO: With Rust 1.55, we can use the above `in_addr_s_addr` definition that
31// uses a const-fn transmute.
32#[cfg(feature = "std")]
33#[cfg(windows)]
34#[inline]
35pub(crate) fn in_addr_s_addr(addr: c::in_addr) -> u32 {
36    // This should be `*addr.S_un.S_addr()`, except that isn't a `const fn`.
37    unsafe { core::mem::transmute(addr) }
38}
39
40#[cfg(not(windows))]
41#[inline]
42pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
43    c::in_addr { s_addr }
44}
45
46#[cfg(not(feature = "std"))]
47#[cfg(windows)]
48#[inline]
49pub(crate) const fn in_addr_new(s_addr: u32) -> c::in_addr {
50    unsafe { core::mem::transmute(s_addr) }
51}
52
53// TODO: With Rust 1.55, we can use the above `in_addr_new` definition that
54// uses a const-fn transmute.
55#[cfg(feature = "std")]
56#[cfg(windows)]
57#[inline]
58pub(crate) fn in_addr_new(s_addr: u32) -> c::in_addr {
59    unsafe { core::mem::transmute(s_addr) }
60}
61
62#[cfg(not(windows))]
63#[inline]
64pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
65    addr.s6_addr
66}
67
68#[cfg(not(feature = "std"))]
69#[cfg(windows)]
70#[inline]
71pub(crate) const fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
72    unsafe { core::mem::transmute(addr) }
73}
74
75// TODO: With Rust 1.55, we can use the above `in6_addr_s6_addr` definition
76// that uses a const-fn transmute.
77#[cfg(feature = "std")]
78#[cfg(windows)]
79#[inline]
80pub(crate) fn in6_addr_s6_addr(addr: c::in6_addr) -> [u8; 16] {
81    unsafe { core::mem::transmute(addr) }
82}
83
84#[cfg(not(windows))]
85#[inline]
86pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
87    c::in6_addr { s6_addr }
88}
89
90#[cfg(not(feature = "std"))]
91#[cfg(windows)]
92#[inline]
93pub(crate) const fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
94    unsafe { core::mem::transmute(s6_addr) }
95}
96
97// TODO: With Rust 1.55, we can use the above `in6_addr_new` definition that
98// uses a const-fn transmute.
99#[cfg(feature = "std")]
100#[cfg(windows)]
101#[inline]
102pub(crate) fn in6_addr_new(s6_addr: [u8; 16]) -> c::in6_addr {
103    unsafe { core::mem::transmute(s6_addr) }
104}
105
106#[cfg(not(windows))]
107#[inline]
108pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
109    addr.sin6_scope_id
110}
111
112#[cfg(not(feature = "std"))]
113#[cfg(windows)]
114#[inline]
115pub(crate) const fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
116    let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) };
117    addr.sin6_scope_id
118}
119
120// TODO: With Rust 1.55, we can use the above `sockaddr_in6_sin6_scope_id`
121// definition that uses a const-fn transmute.
122#[cfg(feature = "std")]
123#[cfg(windows)]
124#[inline]
125pub(crate) fn sockaddr_in6_sin6_scope_id(addr: c::sockaddr_in6) -> u32 {
126    let addr: sockaddr_in6 = unsafe { core::mem::transmute(addr) };
127    addr.sin6_scope_id
128}
129
130#[cfg(not(windows))]
131#[inline]
132pub(crate) const fn sockaddr_in6_new(
133    #[cfg(any(
134        target_os = "dragonfly",
135        target_os = "freebsd",
136        target_os = "haiku",
137        target_os = "ios",
138        target_os = "macos",
139        target_os = "netbsd",
140        target_os = "openbsd",
141    ))]
142    sin6_len: u8,
143    sin6_family: c::sa_family_t,
144    sin6_port: u16,
145    sin6_flowinfo: u32,
146    sin6_addr: c::in6_addr,
147    sin6_scope_id: u32,
148) -> c::sockaddr_in6 {
149    c::sockaddr_in6 {
150        #[cfg(any(
151            target_os = "dragonfly",
152            target_os = "freebsd",
153            target_os = "haiku",
154            target_os = "ios",
155            target_os = "macos",
156            target_os = "netbsd",
157            target_os = "openbsd",
158        ))]
159        sin6_len,
160        sin6_family,
161        sin6_port,
162        sin6_flowinfo,
163        sin6_addr,
164        sin6_scope_id,
165        #[cfg(any(target_os = "illumos", target_os = "solaris"))]
166        __sin6_src_id: 0,
167    }
168}
169
170#[cfg(not(feature = "std"))]
171#[cfg(windows)]
172#[inline]
173pub(crate) const fn sockaddr_in6_new(
174    sin6_family: u16,
175    sin6_port: u16,
176    sin6_flowinfo: u32,
177    sin6_addr: c::in6_addr,
178    sin6_scope_id: u32,
179) -> c::sockaddr_in6 {
180    let addr = sockaddr_in6 {
181        sin6_family,
182        sin6_port,
183        sin6_flowinfo,
184        sin6_addr,
185        sin6_scope_id,
186    };
187    unsafe { core::mem::transmute(addr) }
188}
189
190// TODO: With Rust 1.55, we can use the above `sockaddr_in6_new` definition
191// that uses a const-fn transmute.
192#[cfg(feature = "std")]
193#[cfg(windows)]
194#[inline]
195pub(crate) fn sockaddr_in6_new(
196    sin6_family: u16,
197    sin6_port: u16,
198    sin6_flowinfo: u32,
199    sin6_addr: c::in6_addr,
200    sin6_scope_id: u32,
201) -> c::sockaddr_in6 {
202    let addr = sockaddr_in6 {
203        sin6_family,
204        sin6_port,
205        sin6_flowinfo,
206        sin6_addr,
207        sin6_scope_id,
208    };
209    unsafe { core::mem::transmute(addr) }
210}
211