1use core::net::{
4 IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6,
5};
6
7use munge::munge;
8
9use crate::{
10 primitive::{ArchivedU16, ArchivedU32},
11 Archive, Place, Portable,
12};
13
14#[derive(Portable)]
16#[rkyv(crate)]
17#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
18#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
19#[repr(transparent)]
20pub struct ArchivedIpv4Addr {
21 octets: [u8; 4],
22}
23
24impl ArchivedIpv4Addr {
25 #[inline]
27 pub const fn octets(&self) -> [u8; 4] {
28 self.octets
29 }
30
31 #[inline]
33 pub const fn as_ipv4(&self) -> Ipv4Addr {
34 let octets = self.octets();
35 Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])
36 }
37
38 #[inline]
42 pub const fn is_broadcast(&self) -> bool {
43 self.as_ipv4().is_broadcast()
44 }
45
46 #[inline]
51 pub const fn is_documentation(&self) -> bool {
52 self.as_ipv4().is_documentation()
53 }
54
55 #[inline]
59 pub const fn is_link_local(&self) -> bool {
60 self.as_ipv4().is_link_local()
61 }
62
63 #[inline]
67 pub const fn is_loopback(&self) -> bool {
68 self.as_ipv4().is_loopback()
69 }
70
71 #[inline]
75 pub const fn is_multicast(&self) -> bool {
76 self.as_ipv4().is_multicast()
77 }
78
79 #[inline]
83 pub const fn is_private(&self) -> bool {
84 self.as_ipv4().is_private()
85 }
86
87 #[inline]
91 pub const fn is_unspecified(&self) -> bool {
92 self.as_ipv4().is_unspecified()
93 }
94
95 #[inline]
101 #[allow(clippy::wrong_self_convention)]
102 pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
103 self.as_ipv4().to_ipv6_compatible()
104 }
105
106 #[inline]
111 #[allow(clippy::wrong_self_convention)]
112 pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
113 self.as_ipv4().to_ipv6_mapped()
114 }
115
116 #[inline]
118 pub fn emplace(octets: [u8; 4], out: Place<Self>) {
119 unsafe {
120 out.cast_unchecked::<[u8; 4]>().write(octets);
121 }
122 }
123}
124
125#[derive(Portable)]
127#[rkyv(crate)]
128#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
129#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
130#[repr(transparent)]
131pub struct ArchivedIpv6Addr {
132 octets: [u8; 16],
133}
134
135impl ArchivedIpv6Addr {
136 #[inline]
138 pub const fn segments(&self) -> [u16; 8] {
139 [
140 u16::from_be_bytes([self.octets[0], self.octets[1]]),
141 u16::from_be_bytes([self.octets[2], self.octets[3]]),
142 u16::from_be_bytes([self.octets[4], self.octets[5]]),
143 u16::from_be_bytes([self.octets[6], self.octets[7]]),
144 u16::from_be_bytes([self.octets[8], self.octets[9]]),
145 u16::from_be_bytes([self.octets[10], self.octets[11]]),
146 u16::from_be_bytes([self.octets[12], self.octets[13]]),
147 u16::from_be_bytes([self.octets[14], self.octets[15]]),
148 ]
149 }
150
151 #[inline]
153 pub const fn as_ipv6(&self) -> Ipv6Addr {
154 let segments = self.segments();
155 Ipv6Addr::new(
156 segments[0],
157 segments[1],
158 segments[2],
159 segments[3],
160 segments[4],
161 segments[5],
162 segments[6],
163 segments[7],
164 )
165 }
166
167 #[inline]
172 pub const fn is_loopback(&self) -> bool {
173 self.as_ipv6().is_loopback()
174 }
175
176 #[inline]
181 pub const fn is_multicast(&self) -> bool {
182 self.as_ipv6().is_multicast()
183 }
184
185 #[inline]
190 pub const fn is_unspecified(&self) -> bool {
191 self.as_ipv6().is_unspecified()
192 }
193
194 #[inline]
196 pub const fn octets(&self) -> [u8; 16] {
197 self.as_ipv6().octets()
198 }
199
200 #[inline]
204 #[allow(clippy::wrong_self_convention)]
205 pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
206 self.as_ipv6().to_ipv4()
207 }
208
209 #[inline]
211 pub fn emplace(octets: [u8; 16], out: Place<Self>) {
212 unsafe {
213 out.cast_unchecked::<[u8; 16]>().write(octets);
214 }
215 }
216}
217
218#[derive(Portable)]
220#[rkyv(crate)]
221#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
222#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
223#[repr(u8)]
224pub enum ArchivedIpAddr {
225 V4(ArchivedIpv4Addr),
227 V6(ArchivedIpv6Addr),
229}
230
231impl ArchivedIpAddr {
232 #[inline]
235 pub const fn is_ipv4(&self) -> bool {
236 matches!(self, ArchivedIpAddr::V4(_))
237 }
238
239 #[inline]
242 pub const fn is_ipv6(&self) -> bool {
243 matches!(self, ArchivedIpAddr::V6(_))
244 }
245
246 #[inline]
248 pub const fn as_ipaddr(&self) -> IpAddr {
249 match self {
250 ArchivedIpAddr::V4(ipv4) => IpAddr::V4(ipv4.as_ipv4()),
251 ArchivedIpAddr::V6(ipv6) => IpAddr::V6(ipv6.as_ipv6()),
252 }
253 }
254
255 #[inline]
260 pub const fn is_loopback(&self) -> bool {
261 match self {
262 ArchivedIpAddr::V4(ip) => ip.is_loopback(),
263 ArchivedIpAddr::V6(ip) => ip.is_loopback(),
264 }
265 }
266
267 #[inline]
272 pub const fn is_multicast(&self) -> bool {
273 match self {
274 ArchivedIpAddr::V4(ip) => ip.is_multicast(),
275 ArchivedIpAddr::V6(ip) => ip.is_multicast(),
276 }
277 }
278
279 #[inline]
284 pub const fn is_unspecified(&self) -> bool {
285 match self {
286 ArchivedIpAddr::V4(ip) => ip.is_unspecified(),
287 ArchivedIpAddr::V6(ip) => ip.is_unspecified(),
288 }
289 }
290}
291
292#[derive(
294 Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, Portable, PartialOrd,
295)]
296#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
297#[rkyv(crate)]
298#[repr(C)]
299pub struct ArchivedSocketAddrV4 {
300 ip: ArchivedIpv4Addr,
301 port: ArchivedU16,
302}
303
304impl ArchivedSocketAddrV4 {
305 #[inline]
307 pub const fn ip(&self) -> &ArchivedIpv4Addr {
308 &self.ip
309 }
310
311 #[inline]
313 pub const fn port(&self) -> u16 {
314 self.port.to_native()
315 }
316
317 #[inline]
319 pub fn as_socket_addr_v4(&self) -> SocketAddrV4 {
320 SocketAddrV4::new(self.ip().as_ipv4(), self.port())
321 }
322
323 #[inline]
325 pub fn emplace(value: &SocketAddrV4, out: Place<Self>) {
326 munge!(let ArchivedSocketAddrV4 { ip, port } = out);
327 value.ip().resolve((), ip);
328 value.port().resolve((), port);
329 }
330}
331
332#[derive(
334 Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, Portable, PartialOrd,
335)]
336#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
337#[rkyv(crate)]
338#[repr(C)]
339pub struct ArchivedSocketAddrV6 {
340 ip: ArchivedIpv6Addr,
341 port: ArchivedU16,
342 flowinfo: ArchivedU32,
343 scope_id: ArchivedU32,
344}
345
346impl ArchivedSocketAddrV6 {
347 #[inline]
352 pub const fn flowinfo(&self) -> u32 {
353 self.flowinfo.to_native()
354 }
355
356 #[inline]
358 pub const fn ip(&self) -> &ArchivedIpv6Addr {
359 &self.ip
360 }
361
362 #[inline]
364 pub const fn port(&self) -> u16 {
365 self.port.to_native()
366 }
367
368 #[inline]
373 pub const fn scope_id(&self) -> u32 {
374 self.scope_id.to_native()
375 }
376
377 #[inline]
379 pub fn as_socket_addr_v6(&self) -> SocketAddrV6 {
380 SocketAddrV6::new(
381 self.ip().as_ipv6(),
382 self.port(),
383 self.flowinfo(),
384 self.scope_id(),
385 )
386 }
387
388 #[inline]
390 pub fn emplace(value: &SocketAddrV6, out: Place<Self>) {
391 munge!(let ArchivedSocketAddrV6 { ip, port, flowinfo, scope_id } = out);
392 value.ip().resolve((), ip);
393 value.port().resolve((), port);
394 value.flowinfo().resolve((), flowinfo);
395 value.scope_id().resolve((), scope_id);
396 }
397}
398
399#[derive(Portable)]
401#[rkyv(crate)]
402#[cfg_attr(feature = "bytecheck", derive(bytecheck::CheckBytes))]
403#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
404#[repr(u8)]
405pub enum ArchivedSocketAddr {
406 V4(ArchivedSocketAddrV4),
408 V6(ArchivedSocketAddrV6),
410}
411
412impl ArchivedSocketAddr {
413 #[inline]
415 pub fn port(&self) -> u16 {
416 match self {
417 ArchivedSocketAddr::V4(addr) => addr.port(),
418 ArchivedSocketAddr::V6(addr) => addr.port(),
419 }
420 }
421
422 #[inline]
426 pub fn is_ipv4(&self) -> bool {
427 matches!(self, ArchivedSocketAddr::V4(_))
428 }
429
430 #[inline]
434 pub fn is_ipv6(&self) -> bool {
435 matches!(self, ArchivedSocketAddr::V6(_))
436 }
437
438 #[inline]
440 pub fn as_socket_addr(&self) -> SocketAddr {
441 match self {
442 ArchivedSocketAddr::V4(addr) => {
443 SocketAddr::V4(addr.as_socket_addr_v4())
444 }
445 ArchivedSocketAddr::V6(addr) => {
446 SocketAddr::V6(addr.as_socket_addr_v6())
447 }
448 }
449 }
450
451 #[inline]
453 pub fn ip(&self) -> IpAddr {
454 match self {
455 ArchivedSocketAddr::V4(addr) => IpAddr::V4(addr.ip().as_ipv4()),
456 ArchivedSocketAddr::V6(addr) => IpAddr::V6(addr.ip().as_ipv6()),
457 }
458 }
459}