28 个稳定版本
3.2.2 | 2024 年 7 月 25 日 |
---|---|
3.1.4 | 2024 年 2 月 20 日 |
3.1.3 | 2023 年 10 月 20 日 |
2.2.3 | 2023 年 1 月 11 日 |
1.1.3 | 2020 年 3 月 31 日 |
#65 in 网页开发
34,155 每月下载量
用于 102 个 Crates(直接使用 62 个)
245KB
6.5K SLoC
国际化资源标识符和引用
这个 Crates 提供了符合 统一资源标识符 (URIs,也称 URLs) 和 国际化资源标识符 (IRIs) 的实现,遵循 RFC 3987 和 RFC 3986,由 互联网工程任务组 (IETF) 定义,用于在互联网上唯一标识对象。IRIs 是 URI 的超类,接受 Unicode 表中定义的国际字符。
URI/IRIs 被定义为具有可区分组件的字符序列:一个方案、一个权限、一个路径、一个查询和一个片段。
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
此 Crates 提供了表示借用和所有 URI 和 IRI 的类型(Uri
、Iri
、UriBuf
、IriBuf
),借用和所有 URI 和 IRI 引用(UriRef
、IriRef
、UriRefBuf
、IriRefBuf
)以及 URI/IRI 的每个部分的类似类型。这允许轻松访问和操作每个组件。它具有以下功能:
- 借用和所有 URI/IRIs 和 URI/IRI 引用;
- 可变 URI/IRI 缓冲区(原地);
- 路径规范化;
- 比较规范化模;
- URI/IRI 引用解析;
- 使用
static-iref
Crates 和其iri
宏进行静态 URI/IRI 解析;以及 - 支持
serde
(通过启用serde
功能)。
基本用法
您可以通过将一个Iri
实例包装在一个str
切片中,来解析IRI字符串。注意,使用Iri
不会发生内存分配,它仅借用输入数据。访问每个组件的时间是常数。
use iref::Iri;
let iri = Iri::new("https://rust-lang.net.cn/foo/bar?query#frag")?;
println!("scheme: {}", iri.scheme());
println!("authority: {}", iri.authority().unwrap());
println!("path: {}", iri.path());
println!("query: {}", iri.query().unwrap());
println!("fragment: {}", iri.fragment().unwrap());
可以使用IriBuf
类型创建和修改IRI。使用此类型,IRI保存在单个缓冲区中,原地修改以减少内存分配并优化内存访问。这还允许将IriBuf
转换为Iri
。
use iref::IriBuf;
let mut iri = IriBuf::new("https://rust-lang.net.cn".to_string())?;
iri.authority_mut().unwrap().set_port(Some("40".try_into()?));
iri.set_path("/foo".try_into()?);
iri.path_mut().push("bar".try_into()?);
iri.set_query(Some("query".try_into()?));
iri.set_fragment(Some("fragment".try_into()?));
assert_eq!(iri, "https://rust-lang.net.cn:40/foo/bar?query#fragment");
使用try_into
方法确保每个字符串在其对应组件方面是语法正确的(例如,无法将"query"
替换为"query?"
,因为?
不是有效的查询字符)。
详细用法
路径操作
通过path
或path_mut
方法访问IRI路径。可以使用由segments
方法返回的迭代器访问路径的各个部分。
for segment in iri.path().segments() {
println!("{}", segment);
}
可以使用normalized_segments
方法迭代路径的规范化版本,其中删除了点段(.
和..
)。此外,可以使用相应的方法向路径中推入或弹出段。
let mut iri = IriBuf::new("https://rust-lang.net.cn/a/c".to_string())?;
let mut path = iri.path_mut();
path.pop();
path.push("b".try_into()?);
path.push("c".try_into()?);
path.push("".try_into()?); // the empty segment is valid.
assert_eq!(iri.path(), "/a/b/c/");
IRI引用
此crate提供两种类型IriRef
和IriRefBuf
来表示IRI引用。IRI引用可以是IRI或相对IRI。与常规IRI不同,相对IRI引用可能没有方案。
let mut iri_ref = IriRefBuf::default(); // an IRI reference can be empty.
// An IRI reference with a scheme is a valid IRI.
iri_ref.set_scheme(Some("https".try_into()?));
let iri: &Iri = iri_ref.as_iri().unwrap();
// An IRI can be safely converted into an IRI reference.
let iri_ref: &IriRef = iri.into();
给定一个基本IRI,可以使用定义在RFC 3986中的引用解析算法将引用解析为常规IRI。此crate提供了该算法的严格实现。
let base_iri = Iri::new("http://a/b/c/d;p?q")?;
let mut iri_ref = IriRefBuf::new("g;x=1/../y".to_string())?;
// non mutating resolution.
assert_eq!(iri_ref.resolved(base_iri), "http://a/b/c/y");
// in-place resolution.
iri_ref.resolve(base_iri);
assert_eq!(iri_ref, "http://a/b/c/y");
此crate实现了关于相对路径中点段异常使用的Errata 4547。这意味着例如,路径a/b/../../../
被规范化为../
。
IRI比较
以下是此crate中实现的IRI比较方法的特性。
协议无关
此实现对现有协议一无所知。例如,即使HTTP协议将80
定义为默认端口,两个IRI http://example.org
和http://example.org:80
也不相等。
每个/
都算数
路径/foo/bar
不等于/foo/bar/
。
路径规范化
在比较过程中,通过删除点段(.
和 ..
)来规范化路径。这意味着例如,路径 a/b/c
和 a/../a/./b/../b/c
是等效的。但是请注意,此crate实现了关于相对路径中点段异常使用的勘误4547。这意味着例如,IRI http:a/b/../../../
等价于 http:../
,而不是 http:
。
百分编码字符
感谢 pct-str
crate,百分编码字符得到正确处理。两个IRI http://example.org
和 http://exa%6dple.org
是等效的。
依赖项
~2.6–4MB
~80K SLoC