Trait std::hash::Hasher

1.0.0 · source ·
pub trait Hasher {
Show 16 methods // Required methods fn finish(&self) -> u64; fn write(&mut self, bytes: &[u8]); // Provided methods fn write_u8(&mut self, i: u8) { ... } fn write_u16(&mut self, i: u16) { ... } fn write_u32(&mut self, i: u32) { ... } fn write_u64(&mut self, i: u64) { ... } fn write_u128(&mut self, i: u128) { ... } fn write_usize(&mut self, i: usize) { ... } fn write_i8(&mut self, i: i8) { ... } fn write_i16(&mut self, i: i16) { ... } fn write_i32(&mut self, i: i32) { ... } fn write_i64(&mut self, i: i64) { ... } fn write_i128(&mut self, i: i128) { ... } fn write_isize(&mut self, i: isize) { ... } fn write_length_prefix(&mut self, len: usize) { ... } fn write_str(&mut self, s: &str) { ... }
}
Expand description

对任意字节流进行散列的 trait。

Hasher 的实例通常表示在对数据进行哈希处理时更改的状态。

Hasher 提供了一个相当基本的接口,用于检索生成的散列 (使用 finish),并将整数和字节片写入实例 (使用 writewrite_u8 等)。 大多数情况下,Hasher 实例与 Hash trait 结合使用。

这个 trait 不保证如何定义各种 write_* 方法,并且 Hash 的实现不应假设它们以一种或另一种方式工作。 例如,您不能假设一个 write_u32 调用等同于 write_u8 的四个调用。 您也不能假设相邻的 write 调用是合并的,所以有可能,例如,

hasher.write(&[1, 2]);
hasher.write(&[3, 4, 5, 6]);
Run

and

hasher.write(&[1, 2, 3, 4]);
hasher.write(&[5, 6]);
Run

最终产生不同的哈希值。

因此,为了产生相同的散列值,Hash 实现必须确保对等价项进行完全相同的调用序列 – 相同的方法具有相同的参数以相同的顺序。

Examples

use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

let mut hasher = DefaultHasher::new();

hasher.write_u32(1989);
hasher.write_u8(11);
hasher.write_u8(9);
hasher.write(b"Huh?");

println!("Hash is {:x}!", hasher.finish());
Run

Required Methods§

source

fn finish(&self) -> u64

返回到目前为止写入的值的哈希值。

尽管名称如此,该方法不会重置哈希器的内部状态。 额外的 write 将从当前值继续。 如果需要开始一个新的哈希值,则必须创建一个新的哈希器。

Examples
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

let mut hasher = DefaultHasher::new();
hasher.write(b"Cool!");

println!("Hash is {:x}!", hasher.finish());
Run
source

fn write(&mut self, bytes: &[u8])

将一些数据写入此 Hasher

Examples
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;

let mut hasher = DefaultHasher::new();
let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

hasher.write(&data);

println!("Hash is {:x}!", hasher.finish());
Run
给实现者的注意事项

您通常不应该将长度前缀作为实现此方法的一部分。 在需要它的序列之前调用 Hasher::write_length_prefix 取决于 Hash 实现。

Provided Methods§

1.3.0 · source

fn write_u8(&mut self, i: u8)

将单个 u8 写入此哈希器。

1.3.0 · source

fn write_u16(&mut self, i: u16)

将单个 u16 写入此哈希器。

1.3.0 · source

fn write_u32(&mut self, i: u32)

将单个 u32 写入此哈希器。

1.3.0 · source

fn write_u64(&mut self, i: u64)

将单个 u64 写入此哈希器。

1.26.0 · source

fn write_u128(&mut self, i: u128)

将单个 u128 写入此哈希器。

1.3.0 · source

fn write_usize(&mut self, i: usize)

将单个 usize 写入此哈希器。

1.3.0 · source

fn write_i8(&mut self, i: i8)

将单个 i8 写入此哈希器。

1.3.0 · source

fn write_i16(&mut self, i: i16)

将单个 i16 写入此哈希器。

1.3.0 · source

fn write_i32(&mut self, i: i32)

将单个 i32 写入此哈希器。

1.3.0 · source

fn write_i64(&mut self, i: i64)

将单个 i64 写入此哈希器。

1.26.0 · source

fn write_i128(&mut self, i: i128)

将单个 i128 写入此哈希器。

1.3.0 · source

fn write_isize(&mut self, i: isize)

将单个 isize 写入此哈希器。

source

fn write_length_prefix(&mut self, len: usize)

🔬This is a nightly-only experimental API. (hasher_prefixfree_extras #96762)

将长度前缀写入此哈希器,作为无前缀的一部分。

如果您正在为自定义集合实现 Hash,请在将其内容写入此 Hasher 之前调用 this。 这样 (collection![1, 2, 3], collection![4, 5])(collection![1, 2], collection![3, 4, 5]) 将为 Hasher 提供不同的值序列

impl<T> Hash for [T] 包含对该方法的调用,因此如果您通过其 Hash::hash 方法对切片 (或数组或 vector) 进行哈希处理,您不应该 ** 自己调用 this。

此方法仅用于提供域分离。 如果您想对表示 data 的一部分的 usize 进行散列处理,那么将其传递给 Hasher::write_usize 而不是此方法很重要。

Examples
#![feature(hasher_prefixfree_extras)]

use std::hash::{Hash, Hasher};
impl<T: Hash> Hash for MyCollection<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        state.write_length_prefix(self.len());
        for elt in self {
            elt.hash(state);
        }
    }
}
Run
给实现者的注意事项

如果您确定您的 Hasher 愿意受到 Hash-DoS 攻击,那么您可以考虑跳过以提高性能为名提供的部分或全部 len 的散列。

source

fn write_str(&mut self, s: &str)

🔬This is a nightly-only experimental API. (hasher_prefixfree_extras #96762)

将单个 str 写入此哈希器。

如果您正在实现 Hash,您通常不需要像 impl Hash for str 那样调用 this,所以您应该更喜欢它。

这包括前缀自由的域分隔符,所以在调用它之前您不应该 ** 调用 Self::write_length_prefix

给实现者的注意事项

至少有两种合理的默认方式来实现这一点。 哪一个将是默认值尚未确定,所以现在您可能想要专门覆盖它。

一般答案

使用长度前缀来实现它总是正确的:

fn write_str(&mut self, s: &str) {
    self.write_length_prefix(s.len());
    self.write(s.as_bytes());
}
Run

而且,如果您的 Hasherusize 块中工作,这可能是一种非常有效的方法,因为任何更复杂的事情最终都可能比仅以长度运行一轮更慢。

如果您的 Hasher 按字节工作

str 是 UTF-8 的一个好处是 b'\xFF' 字节永远不会发生。这意味着您可以将其,追加,到被散列的字节流并保持前缀自由:

fn write_str(&mut self, s: &str) {
    self.write(s.as_bytes());
    self.write_u8(0xff);
}
Run

这确实要求您的实现不添加额外的填充,因此通常需要您维护一个缓冲区,仅在该缓冲区已满 (或调用 finish) 时运行一轮。

那是因为如果 write 将数据填充到固定的块大小,它很可能会以这样的方式进行,即 "a""a\x00" 最终会散列相同的事物序列,从而引入冲突。

Implementors§

1.13.0 · source§

impl Hasher for DefaultHasher

source§

impl Hasher for SipHasher

1.22.0 · source§

impl<H> Hasher for &mut Hwhere H: Hasher + ?Sized,

1.22.0 · source§

impl<T, A> Hasher for Box<T, A>where T: Hasher + ?Sized, A: Allocator,