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