1 个不稳定版本
| 0.1.0 | 2024年1月3日 |
|---|
#1018 在 算法
20KB
198 行
包 url-hash
此包提供了三种类型,专门用于表示Url类型的哈希值。
对于一些以URL为中心的结构,如RDF图和XML文档,管理类似于哈希的操作来比较URL值或检测URL在缓存中的存在成为一个核心需求。虽然可以使用Rust内置的哈希实现,以及扩展的集合如HashMap和HashSet,但它们提供了一个封闭的实现,无法在不进行额外努力的情况下以语言可移植或持久的方式使用。
UrlHash类型的目的在于提供表示单个URL值的稳定值的稳定加密哈希,该值可以在不同的平台和编程环境中复制。
示例
use url::Url;
use url_hash::UrlHash;
let url = Url::parse("https://doc.rust-lang.net.cn/").unwrap();
let hash = UrlHash::from(url);
println!("{}", hash);
规范
本节尝试以语言和平台无关的方式描述实现,以便在其他地方复制。
计算
哈希的基础是SHA-256摘要算法,该算法在部分规范化的URL上计算。
- URL的
scheme组件被转换为小写。 - URL的
host组件被转换为小写。 host组件通过punycode替换进行Unicode标准化。- 如果
port组件对于给定的方案是默认的(对于http是80,对于https是443等),则将其删除。 - URL的
path组件中删除任何相对组件(使用"."和".."指定)。 - 空
path组件被替换为"/"。 path、query和fragment组件进行URL编码。
以下表格演示了上述规则的一些结果。
| # | 输入 | 输出 |
|---|---|---|
| 1 | hTTpS://example.com/ |
https://example.com/ |
| 2 | https://Example.COM/ |
https://example.com/ |
| 3 | https://exámple.com/ |
https://xn--exmple-xta.com/ |
| 3 | https://example§.com/ |
https://xn--example-eja.com/ |
| 4 | http://example.com:80/ |
http://example.com/ |
| 4 | https://example.com:443/ |
https://example.com/ |
| 5 | https://example.com/foo/../bar/./baz.jpg |
https://example.com/bar/baz.jpg |
| 6 | https://example.com |
https://example.com/ |
| 7 | https://example.com/hello world |
https://example.com/hello%20world |
| 7 | https://example.com/?q=hello world |
https://example.com/?q=hello%20world |
| 7 | https://example.com/?q=hello#to world |
https://example.com/?q=hello#to%20world |
表示
生成的SHA-256是一个256位,或32字节的值。这被存储为四个64位(8字节)的无符号整数值,这些值从以小端顺序表示的摘要字节转换而来。以下代码演示了如何从表示摘要的字节创建这些值。
以下代码演示了如何从摘要字节创建这四个值。
let bytes: [u8;32] = digest_bytes();
let value_1 = u64::from_le_bytes(bytes[0..8].try_into().unwrap());
let value_2 = u64::from_le_bytes(bytes[8..16].try_into().unwrap());
let value_3 = u64::from_le_bytes(bytes[16..24].try_into().unwrap());
let value_4 = u64::from_le_bytes(bytes[24..32].try_into().unwrap());
简写形式
在某些情况下,当在空间和哈希冲突之间进行权衡时,没有必要存储或传递整个32字节的UrlHash值。为了允许这些权衡,每个UrlHash实例都可以转换为16字节的UrlShortHash,它只包含完整哈希的前两个64位无符号值,或者8字节的UrlVeryShortHash,它只包含完整哈希的第一个64位无符号值。
以下代码演示了创建简短(截断)哈希以及前缀测试starts_with和starts_with_just。
let url = Url::parse("https://doc.rust-lang.net.cn/").unwrap();
let hash = UrlHash::from(url);
let short = hash.short();
assert!(hash.starts_with(&short));
let very_short = hash.very_short();
assert!(short.starts_with(&very_short));
assert!(hash.starts_with_just(&very_short));
assert_eq!(very_short, hash.very_short());
变更历史
版本 0.1.0
- 首次发布。
依赖项
~6–14MB
~277K SLoC