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