• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

benches/H03-May-2022-346276

examples/H03-May-2022-11789

src/H03-May-2022-3,8062,825

tests/H03-May-2022-709550

.cargo-checksum.jsonH A D03-May-202289 11

.gitignoreH A D19-Mar-2018112 1512

Cargo.tomlH A D01-Jan-19701.1 KiB3330

Cargo.toml.orig-cargoH A D14-Sep-2018642 2319

LICENSE-APACHEH A D11-Nov-201710.6 KiB202169

LICENSE-MITH A D11-Nov-20171.1 KiB2217

README.mdH A D14-Sep-20184.2 KiB10373

RELEASE-NOTES.mdH A D14-Sep-20181.1 KiB6337

README.md

1[base64](https://crates.io/crates/base64)
2===
3[![](https://img.shields.io/crates/v/base64.svg)](https://crates.io/crates/base64) [![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64)
4
5It's base64. What more could anyone want?
6
7Example
8---
9
10```rust
11extern crate base64;
12
13use base64::{encode, decode};
14
15fn main() {
16    let a = b"hello world";
17    let b = "aGVsbG8gd29ybGQ=";
18
19    assert_eq!(encode(a), b);
20    assert_eq!(a, &decode(b).unwrap()[..]);
21}
22```
23
24See the [docs](https://docs.rs/base64) for all the details.
25
26Purpose
27---
28
29I have a fondness for small dependency footprints, ecosystems where you can pick and choose what functionality you need, and no more. Unix philosophy sort of thing I guess, many tiny utilities interoperating across a common interface. One time making a Twitter bot, I ran into the need to correctly pluralize arbitrary words. I found on npm a module that did nothing but pluralize words. Nothing else, just a couple of functions. I'd like for this to be that "just a couple of functions."
30
31Developing
32---
33
34Benchmarks are in `benches/`. Running them requires nightly rust, but `rustup` makes it easy:
35
36```
37rustup run nightly cargo bench
38```
39
40Decoding is aided by some pre-calculated tables, which are generated by:
41
42```
43cargo run --example make_tables > src/tables.rs.tmp && mv src/tables.rs.tmp src/tables.rs
44```
45
46Profiling
47---
48
49On Linux, you can use [perf](https://perf.wiki.kernel.org/index.php/Main_Page) for profiling. Then compile the benchmarks with `rustup nightly run cargo bench --no-run`.
50
51Run the benchmark binary with `perf` (shown here filtering to one particular benchmark, which will make the results easier to read). `perf` is only available to the root user on most systems as it fiddles with event counters in your CPU, so use `sudo`. We need to run the actual benchmark binary, hence the path into `target`. You can see the actual full path with `rustup run nightly cargo bench -v`; it will print out the commands it runs. If you use the exact path that `bench` outputs, make sure you get the one that's for the benchmarks, not the tests. You may also want to `cargo clean` so you have only one `benchmarks-` binary (they tend to accumulate).
52
53```
54sudo perf record target/release/deps/benchmarks-* --bench decode_10mib_reuse
55```
56
57Then analyze the results, again with perf:
58
59```
60sudo perf annotate -l
61```
62
63You'll see a bunch of interleaved rust source and assembly like this. The section with `lib.rs:327` is telling us that 4.02% of samples saw the `movzbl` aka bit shift as the active instruction. However, this percentage is not as exact as it seems due to a phenomenon called *skid*. Basically, a consequence of how fancy modern CPUs are is that this sort of instruction profiling is inherently inaccurate, especially in branch-heavy code.
64
65```
66 lib.rs:322    0.70 :     10698:       mov    %rdi,%rax
67    2.82 :        1069b:       shr    $0x38,%rax
68         :                  if morsel == decode_tables::INVALID_VALUE {
69         :                      bad_byte_index = input_index;
70         :                      break;
71         :                  };
72         :                  accum = (morsel as u64) << 58;
73 lib.rs:327    4.02 :     1069f:       movzbl (%r9,%rax,1),%r15d
74         :              // fast loop of 8 bytes at a time
75         :              while input_index < length_of_full_chunks {
76         :                  let mut accum: u64;
77         :
78         :                  let input_chunk = BigEndian::read_u64(&input_bytes[input_index..(input_index + 8)]);
79         :                  morsel = decode_table[(input_chunk >> 56) as usize];
80 lib.rs:322    3.68 :     106a4:       cmp    $0xff,%r15
81         :                  if morsel == decode_tables::INVALID_VALUE {
82    0.00 :        106ab:       je     1090e <base64::decode_config_buf::hbf68a45fefa299c1+0x46e>
83```
84
85
86Fuzzing
87---
88
89This uses [cargo-fuzz](https://github.com/rust-fuzz/cargo-fuzz). See `fuzz/fuzzers` for the available fuzzing scripts. To run, use an invocation like these:
90
91```
92cargo +nightly fuzz run roundtrip
93cargo +nightly fuzz run roundtrip_no_pad
94cargo +nightly fuzz run roundtrip_mime -- -max_len=10240
95cargo +nightly fuzz run roundtrip_random_config -- -max_len=10240
96```
97
98
99License
100---
101
102This project is dual-licensed under MIT and Apache 2.0.
103