Rollup merge of #128946 - orlp:faster-ip-hash, r=joboet
Hash Ipv*Addr as an integer The `Ipv4Addr` and `Ipv6Addr` structs always have a fixed size, but directly derive `Hash`. This causes them to call the bytestring hasher implementation, which adds extra work for most hashers. This PR converts the internal representation to a fixed-width integer before passing to the hasher to prevent this.
This commit is contained in:
commit
cd1b42c3e9
@ -1,6 +1,7 @@
|
|||||||
use super::display_buffer::DisplayBuffer;
|
use super::display_buffer::DisplayBuffer;
|
||||||
use crate::cmp::Ordering;
|
use crate::cmp::Ordering;
|
||||||
use crate::fmt::{self, Write};
|
use crate::fmt::{self, Write};
|
||||||
|
use crate::hash::{Hash, Hasher};
|
||||||
use crate::iter;
|
use crate::iter;
|
||||||
use crate::mem::transmute;
|
use crate::mem::transmute;
|
||||||
use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
|
use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
|
||||||
@ -67,12 +68,22 @@ pub enum IpAddr {
|
|||||||
/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
|
/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
|
||||||
/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
|
/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct Ipv4Addr {
|
pub struct Ipv4Addr {
|
||||||
octets: [u8; 4],
|
octets: [u8; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl Hash for Ipv4Addr {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
// Hashers are often more efficient at hashing a fixed-width integer
|
||||||
|
// than a bytestring, so convert before hashing. We don't use to_bits()
|
||||||
|
// here as that may involve a byteswap which is unnecessary.
|
||||||
|
u32::from_ne_bytes(self.octets).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An IPv6 address.
|
/// An IPv6 address.
|
||||||
///
|
///
|
||||||
/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
|
/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
|
||||||
@ -149,12 +160,22 @@ pub struct Ipv4Addr {
|
|||||||
/// assert_eq!("::1".parse(), Ok(localhost));
|
/// assert_eq!("::1".parse(), Ok(localhost));
|
||||||
/// assert_eq!(localhost.is_loopback(), true);
|
/// assert_eq!(localhost.is_loopback(), true);
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct Ipv6Addr {
|
pub struct Ipv6Addr {
|
||||||
octets: [u8; 16],
|
octets: [u8; 16],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl Hash for Ipv6Addr {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
// Hashers are often more efficient at hashing a fixed-width integer
|
||||||
|
// than a bytestring, so convert before hashing. We don't use to_bits()
|
||||||
|
// here as that may involve unnecessary byteswaps.
|
||||||
|
u128::from_ne_bytes(self.octets).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
|
/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
|
||||||
///
|
///
|
||||||
/// # Stability Guarantees
|
/// # Stability Guarantees
|
||||||
|
Loading…
Reference in New Issue
Block a user