#decode-base64 #decode #encode-decode #encode #utf-8

无需std base64

以字节或UTF-8编码和解码base64

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

Download history 3731814/week @ 2024-05-02 3731823/week @ 2024-05-09 3967636/week @ 2024-05-16 3876729/week @ 2024-05-23 4379579/week @ 2024-05-30 4332827/week @ 2024-06-06 4414851/week @ 2024-06-13 4349638/week @ 2024-06-20 4407268/week @ 2024-06-27 4074513/week @ 2024-07-04 4450304/week @ 2024-07-11 4522646/week @ 2024-07-18 4613097/week @ 2024-07-25 4620676/week @ 2024-08-01 4957285/week @ 2024-08-08 4635222/week @ 2024-08-15

每月下载19,701,562
32,979个crate(直接使用4,793个)中使用

MIT/Apache

255KB
4.5K SLoC

base64

Docs CircleCI codecov unsafe forbidden

使用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_readReadbytes()一起使用,以过滤掉不需要的字节。
  • 使用一个Readread()实现来委托到您的实际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::iostd::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双重许可。

无运行时依赖