Transmute between big endian s6_addr
and [u16; 8]
.
The old code already made the assumption to reinterpret `Ipv6Addr` as `[u16; 8]`. Glibc, Linux, FreeBSD, Win32 all makes this assumption. The main motivation of using union it to better optimize code. ref: * https://docs.microsoft.com/en-us/windows/win32/api/in6addr/ns-in6addr-in6_addr *1d6e424741/contrib/ntp/lib/isc/include/isc/ipv6.h (L63)
*8b531aa996/include/net/net_ip.h (L137)
* https://sourceware.org/git/?p=glibc.git;a=blob;f=inet/netinet/in.h;h=f6355c7efe5192b88337b136ef687fe9a5ed648c;hb=HEAD#l216 Co-authored-by: Josh Stone <cuviper@gmail.com> Co-authored-by: Peter Atashian <retep998@gmail.com>
This commit is contained in:
parent
f5fef3c715
commit
0210fd3d73
2 changed files with 28 additions and 27 deletions
|
@ -249,6 +249,7 @@
|
||||||
#![feature(clamp)]
|
#![feature(clamp)]
|
||||||
#![feature(concat_idents)]
|
#![feature(concat_idents)]
|
||||||
#![feature(const_cstr_unchecked)]
|
#![feature(const_cstr_unchecked)]
|
||||||
|
#![feature(const_fn_transmute)]
|
||||||
#![feature(const_raw_ptr_deref)]
|
#![feature(const_raw_ptr_deref)]
|
||||||
#![feature(container_error_extra)]
|
#![feature(container_error_extra)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::cmp::Ordering;
|
||||||
use crate::fmt::{self, Write as FmtWrite};
|
use crate::fmt::{self, Write as FmtWrite};
|
||||||
use crate::hash;
|
use crate::hash;
|
||||||
use crate::io::Write as IoWrite;
|
use crate::io::Write as IoWrite;
|
||||||
|
use crate::mem::transmute;
|
||||||
use crate::sys::net::netc as c;
|
use crate::sys::net::netc as c;
|
||||||
use crate::sys_common::{AsInner, FromInner};
|
use crate::sys_common::{AsInner, FromInner};
|
||||||
|
|
||||||
|
@ -1045,27 +1046,23 @@ impl Ipv6Addr {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
|
#[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
|
||||||
|
#[allow_internal_unstable(const_fn_transmute)]
|
||||||
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
|
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
|
||||||
|
let addr16 = [
|
||||||
|
a.to_be(),
|
||||||
|
b.to_be(),
|
||||||
|
c.to_be(),
|
||||||
|
d.to_be(),
|
||||||
|
e.to_be(),
|
||||||
|
f.to_be(),
|
||||||
|
g.to_be(),
|
||||||
|
h.to_be(),
|
||||||
|
];
|
||||||
Ipv6Addr {
|
Ipv6Addr {
|
||||||
inner: c::in6_addr {
|
inner: c::in6_addr {
|
||||||
s6_addr: [
|
// All elements in `addr16` are big endian.
|
||||||
(a >> 8) as u8,
|
// SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
|
||||||
a as u8,
|
s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
|
||||||
(b >> 8) as u8,
|
|
||||||
b as u8,
|
|
||||||
(c >> 8) as u8,
|
|
||||||
c as u8,
|
|
||||||
(d >> 8) as u8,
|
|
||||||
d as u8,
|
|
||||||
(e >> 8) as u8,
|
|
||||||
e as u8,
|
|
||||||
(f >> 8) as u8,
|
|
||||||
f as u8,
|
|
||||||
(g >> 8) as u8,
|
|
||||||
g as u8,
|
|
||||||
(h >> 8) as u8,
|
|
||||||
h as u8,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1108,16 +1105,19 @@ impl Ipv6Addr {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn segments(&self) -> [u16; 8] {
|
pub fn segments(&self) -> [u16; 8] {
|
||||||
let arr = &self.inner.s6_addr;
|
// All elements in `s6_addr` must be big endian.
|
||||||
|
// SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
|
||||||
|
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
|
||||||
|
// We want native endian u16
|
||||||
[
|
[
|
||||||
u16::from_be_bytes([arr[0], arr[1]]),
|
u16::from_be(a),
|
||||||
u16::from_be_bytes([arr[2], arr[3]]),
|
u16::from_be(b),
|
||||||
u16::from_be_bytes([arr[4], arr[5]]),
|
u16::from_be(c),
|
||||||
u16::from_be_bytes([arr[6], arr[7]]),
|
u16::from_be(d),
|
||||||
u16::from_be_bytes([arr[8], arr[9]]),
|
u16::from_be(e),
|
||||||
u16::from_be_bytes([arr[10], arr[11]]),
|
u16::from_be(f),
|
||||||
u16::from_be_bytes([arr[12], arr[13]]),
|
u16::from_be(g),
|
||||||
u16::from_be_bytes([arr[14], arr[15]]),
|
u16::from_be(h),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue