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 网页开发

Download history 7314/week @ 2024-04-28 7822/week @ 2024-05-05 9022/week @ 2024-05-12 7768/week @ 2024-05-19 6900/week @ 2024-05-26 6731/week @ 2024-06-02 6564/week @ 2024-06-09 7673/week @ 2024-06-16 6493/week @ 2024-06-23 6549/week @ 2024-06-30 7104/week @ 2024-07-07 7031/week @ 2024-07-14 8085/week @ 2024-07-21 8112/week @ 2024-07-28 9699/week @ 2024-08-04 7865/week @ 2024-08-11

34,155 每月下载量
用于 102 个 Crates(直接使用 62 个)

MIT/Apache

245KB
6.5K SLoC

国际化资源标识符和引用

CI Crate informations License Documentation

这个 Crates 提供了符合 统一资源标识符 (URIs,也称 URLs)国际化资源标识符 (IRIs) 的实现,遵循 RFC 3987RFC 3986,由 互联网工程任务组 (IETF) 定义,用于在互联网上唯一标识对象。IRIs 是 URI 的超类,接受 Unicode 表中定义的国际字符。

URI/IRIs 被定义为具有可区分组件的字符序列:一个方案、一个权限、一个路径、一个查询和一个片段。

    foo://example.com:8042/over/there?name=ferret#nose
    \_/   \______________/\_________/ \_________/ \__/
     |           |            |            |        |
  scheme     authority       path        query   fragment

此 Crates 提供了表示借用和所有 URI 和 IRI 的类型(UriIriUriBufIriBuf),借用和所有 URI 和 IRI 引用(UriRefIriRefUriRefBufIriRefBuf)以及 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?",因为?不是有效的查询字符)。

详细用法

路径操作

通过pathpath_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提供两种类型IriRefIriRefBuf来表示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.orghttp://example.org:80也不相等。

每个/都算数

路径/foo/bar不等于/foo/bar/

路径规范化

在比较过程中,通过删除点段(...)来规范化路径。这意味着例如,路径 a/b/ca/../a/./b/../b/c 是等效的。但是请注意,此crate实现了关于相对路径中点段异常使用的勘误4547。这意味着例如,IRI http:a/b/../../../ 等价于 http:../,而不是 http:

百分编码字符

感谢 pct-str crate,百分编码字符得到正确处理。两个IRI http://example.orghttp://exa%6dple.org 是等效的

依赖项

~2.6–4MB
~80K SLoC