43个版本
0.22.1 | 2024年4月30日 |
---|---|
0.22.0 | 2024年3月2日 |
0.21.7 | 2024年1月11日 |
0.21.5 | 2023年10月23日 |
0.1.1 | 2015年12月4日 |
在编码类别中排名第1
每月下载19,701,562次
在32,979个crate(直接使用4,793个)中使用
255KB
4.5K SLoC
base64
使用CLion制作。感谢JetBrains支持开源!
这就是base64。还有什么是人们想要的呢?
此库的目标是正确和快速。它经过彻底测试并广泛使用。它在多个抽象级别上公开功能,以便您可以选择您想要的便利性与性能之间的平衡,例如decode_engine_slice
将解码到现有的&mut [u8]
中,速度相当快(对于3 KiB输入为2.6GiB/s),而decode_engine
分配一个新的Vec<u8>
并将其返回,这在某些情况下可能更方便,但速度较慢(尽管仍然足够快,适用于几乎所有目的)为2.1 GiB/s。
请参阅文档以获取所有详细信息。
常见问题解答
我需要解码带有空格/空字节/其他随机内容的base64。我应该怎么做?
在解码之前从输入中删除非base64字符。
如果您有一个base64的Vec
,可以使用retain
来删除您需要删除的内容。
如果您有一个Read
(例如读取文件或网络套接字),有各种方法。
- 使用iter_read与
Read
的bytes()
一起使用,以过滤掉不需要的字节。 - 使用一个
Read
的read()
实现来委托到您的实际Read
,然后丢弃您不想要的任何字节。
我需要换行base64,例如用于MIME/PEM。
line-wrap 就是这样做的。
我想要规范化的 base64 编码/解码。
首先,不要这样做。你不应该期望 Base64 是规范的,就像你不应该期望压缩算法在所有实际应用中产生规范输出一样(提示:它们不会)。然而,人们就像飞蛾扑火一样被自己的毁灭所吸引,所以我们在这里。
存在两种非规范化编码的机会(因此,在解码时检测到相同的):最后一个编码令牌的最后几位,以及用于将后缀膨胀到完整四个令牌的 =
令牌。
尾随位问题是无法避免的:每个编码令牌有 6 位可用,1 个输入字节占用 2 个令牌,第二个令牌有一些位未被使用。两个输入字节也是一样:16 位,但 3 个令牌有 18 位。除非我们决定停止传输整个字节,否则我们就会被那些可能被偷偷设置或有错误的编码器设置为 1 而不是 0 的额外位所困扰。
另一方面,=
填充字节完全是 Base64 标准的自身问题。它们不会影响解码,除了提供机会说“那个填充是不正确的”。毫无疑问,有大量的存储和传输被无意义的 =
字节浪费了。不知何故,我们似乎都对,比如说,十六进制编码的数据完成时停止,而不是需要确认编码器的作者能数到四,感到非常舒服。无论如何,有两种方法可以使填充字节可预测:要求按 RFC 规范进行规范填充,使其成为下一个四的倍数字节,或者,如果你控制所有生产者和消费者,可以通过要求不进行填充来节省一些字节(特别适用于 url-safe 字母表)。
所有 Engine
实现至少必须支持将两种类型的非规范化填充都视为错误,并可选择允许其他行为。
Rust 版本兼容性
最低支持的 Rust 版本是 1.48.0。
贡献
贡献非常受欢迎。然而,因为这个库被广泛使用,并且在安全敏感的环境中,所有 PR 都将被仔细审查。除此之外,这种低级库简单地需要 100% 正确。没有人想要追逐任何类型的编码中的错误。
这意味着我花了很多时间来审查每个 PR,所以可能需要相当长的时间才能腾出时间来给每个 PR 应得的关注。我最终会到达每个人的!
开发
基准测试在 benches/
中。
cargo bench
no_std
这个crate支持no_std。默认情况下,crate通过std
功能针对std。您可以通过禁用default-features
来改为针对core
。在这种情况下,您将失去围绕std::io
、std::error::Error
和堆分配的所有功能。还有一个额外的alloc
功能,您可以激活它以恢复对堆分配的支持。
性能分析
在 Linux 上,您可以使用 perf 进行性能分析。然后使用 cargo bench --no-run
编译基准测试。
使用perf
(如此处所示,仅筛选特定的基准测试,以便更容易阅读结果)运行基准测试的二进制文件。perf
在大多数系统中仅对root用户可用,因为它会操作CPU中的事件计数器,因此请使用sudo
。我们需要运行实际的基准测试二进制文件,因此需要进入target
路径。您可以使用以下命令查看实际的全路径:cargo bench -v
;它将打印出它运行的命令。如果您使用bench
输出的确切路径,请确保您得到的是基准测试的路径,而不是测试的路径。您可能还需要使用cargo clean
以确保只有一个benchmarks-
二进制文件(它们往往会累积)。
sudo perf record target/release/deps/benchmarks-* --bench decode_10mib_reuse
然后使用perf分析结果
sudo perf annotate -l
您将看到一些交错着的Rust源代码和汇编代码,如下所示。带有lib.rs:327
的部分告诉我们,4.02%的样本看到movzbl
(即位移动)作为活动的指令。然而,由于称为skid的现象,这个百分比并不像看起来那么精确。基本上,现代CPU的复杂性的一个后果是,这种指令分析本质上是不准确的,尤其是在分支密集型的代码中。
lib.rs:322 0.70 : 10698: mov %rdi,%rax
2.82 : 1069b: shr $0x38,%rax
: if morsel == decode_tables::INVALID_VALUE {
: bad_byte_index = input_index;
: break;
: };
: accum = (morsel as u64) << 58;
lib.rs:327 4.02 : 1069f: movzbl (%r9,%rax,1),%r15d
: // fast loop of 8 bytes at a time
: while input_index < length_of_full_chunks {
: let mut accum: u64;
:
: let input_chunk = BigEndian::read_u64(&input_bytes[input_index..(input_index + 8)]);
: morsel = decode_table[(input_chunk >> 56) as usize];
lib.rs:322 3.68 : 106a4: cmp $0xff,%r15
: if morsel == decode_tables::INVALID_VALUE {
0.00 : 106ab: je 1090e <base64::decode_config_buf::hbf68a45fefa299c1+0x46e>
模糊测试
这使用了cargo-fuzz。有关可用的模糊测试脚本,请参阅fuzz/fuzzers
。要运行,请使用以下调用之一
cargo +nightly fuzz run roundtrip
cargo +nightly fuzz run roundtrip_no_pad
cargo +nightly fuzz run roundtrip_random_config -- -max_len=10240
cargo +nightly fuzz run decode_random
许可证
本项目根据MIT和Apache 2.0双重许可。