#hasher #hashing #hash

bufhash

缓冲哈希功能

2个版本

0.1.1 2023年12月27日
0.1.0 2023年12月27日

#1959算法

MIT/Apache

14KB
143

bufhash

Rust的缓冲哈希实用工具。

概述

请参阅文档了解该包的详细信息以及如何编写缓冲哈希器。


lib.rs:

缓冲哈希功能。

此crate提供编写利用各种方式缓冲的哈希器的功能。最值得注意的是,它提供了“分区”哈希器的概念,这是一种在哈希前将数据分成固定大小块的一类哈希器。此crate及其所有功能均使用100% Rust编写,并旨在与现有的Rust特质集成,例如std::hash::Hasher

概述

分区哈希器是一类在固定大小数据块上工作的哈希器(例如,MurmurHash3)。从根本上说,在partitioned命名空间下提供的设施旨在解决在增量哈希时分区数据的问题。在底层,分区哈希器跟踪将分块流输入到适当大小,并在内部缓冲区中存储多余数据,以便在下一次write()调用中使用。

例如,考虑以下调用虚构的哈希算法的示例,该算法以每次4字节的大小工作

let mut hasher = MyHasher::default();

hasher.write(b"Hi,");
hasher.write(b"there ");
hasher.write(b"world!");

println!("Result: 0x{:X}", hasher.finish());

在这个例子中,要哈希的数据通过三次不同的write()调用逐渐提供给哈希器。回想一下我们的哈希器在4字节块上工作,字节字符串字面量中的前三个字符(即b"Hi,")不足以填充一个完整的要哈希的数据块。然而,我们也不希望将这些三个字符视为数据流的结尾,因为可能还有更多数据(事实上,在我们的例子中确实如此。借助Rust标准库提供的设施,由实现者负责跟踪这些各种边缘情况并确保哈希器适当地工作。

为了简化符合上述描述的哈希器的实现,分区哈希器在幕后处理必要的会计工作,使实现者只需关注哈希的固定大小接口。

实现分区哈希器

让我们看看核心的bufhash::partitioned::Hasher特质,以了解编写分区哈希器与编写std::hash::Hasher实现有何不同。

pub trait Hasher<const S: usize> {
   fn write(&mut self, bytes: &[u8; S]);
   fn finish(&self, bytes: &[u8]) -> u64;
}

您会发现有两个与std::hash::Hash提供的方法相同,但有几个细微(但重要!)的差异。

  • 该特质有一个泛型参数const S: usize,它定义了每个分区的字节数。在我们的示例中,我们将此设置为四个(4)字节。
  • write()方法接受一个固定大小的字节数组(&[u8; S])。参数bytes保证正好是泛型参数的大小,这使得实现者可以省去大小检查。
  • finish()方法也提供了一个作为字节切片的bytes参数。这些参数是需要处理才能完成哈希器的内部缓冲区中剩余的字节:保证其大小小于泛型参数。

作为一个例子,让我们实现一个分区哈希器,该哈希器(a)将字节流解释为需要相加的little-endian u64,然后在调用finish()时将结果左移缓冲区中剩余的字节数(不是一个特别好的哈希算法,但可以用于我们的演示目的)。

#[derive(Debug, Default)]
pub struct Simple(u64);

impl bufhash::partitioned::Hasher<8> for Simple {
    fn write(&mut self, bytes: &[u8; 8]) {
        let data = u64::from_le_bytes(*bytes);
        self.0 = self.0.wrapping_add(data);
    }

    fn finish(&self, bytes: &[u8]) -> u64 {
        self.0 << bytes.len()
    }
}

如您所见,这比自行处理会计工作要简单得多。

要使用此新实现与std::hash::Hasher接口,您可以使用PartitionedHasher适配器,如下所示

use std::hash::Hasher as _;
#

let mut hasher = bufhash::PartitionedHasher::new(Simple::default());
hasher.write(b"Hello, world!");

println!("Result: {:#X}", hasher.finish());

无运行时依赖