1[base64](https://crates.io/crates/base64)
2===
3
4[![](https://img.shields.io/crates/v/base64.svg)](https://crates.io/crates/base64) [![Docs](https://docs.rs/base64/badge.svg)](https://docs.rs/base64) [![Build](https://travis-ci.org/alicemaz/rust-base64.svg?branch=master)](https://travis-ci.org/alicemaz/rust-base64) [![codecov](https://codecov.io/gh/alicemaz/rust-base64/branch/master/graph/badge.svg)](https://codecov.io/gh/alicemaz/rust-base64)
5
6<a href="https://www.jetbrains.com/?from=rust-base64"><img src="/icon_CLion.svg" height="40px"/></a>
7
8Made with CLion. Thanks to JetBrains for supporting open source!
9
10It's base64. What more could anyone want?
11
12Example
13---
14
15```rust
16extern crate base64;
17
18use base64::{encode, decode};
19
20fn main() {
21    let a = b"hello world";
22    let b = "aGVsbG8gd29ybGQ=";
23
24    assert_eq!(encode(a), b);
25    assert_eq!(a, &decode(b).unwrap()[..]);
26}
27```
28
29See the [docs](https://docs.rs/base64) for all the details.
30
31Rust version compatibility
32---
33
34The minimum required Rust version is 1.27.2.
35
36Developing
37---
38
39Benchmarks are in `benches/`. Running them requires nightly rust, but `rustup` makes it easy:
40
41```
42rustup run nightly cargo bench
43```
44
45Decoding is aided by some pre-calculated tables, which are generated by:
46
47```
48cargo run --example make_tables > src/tables.rs.tmp && mv src/tables.rs.tmp src/tables.rs
49```
50
51Profiling
52---
53
54On 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`.
55
56Run 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).
57
58```
59sudo perf record target/release/deps/benchmarks-* --bench decode_10mib_reuse
60```
61
62Then analyze the results, again with perf:
63
64```
65sudo perf annotate -l
66```
67
68You'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.
69
70```
71 lib.rs:322    0.70 :     10698:       mov    %rdi,%rax
72    2.82 :        1069b:       shr    $0x38,%rax
73         :                  if morsel == decode_tables::INVALID_VALUE {
74         :                      bad_byte_index = input_index;
75         :                      break;
76         :                  };
77         :                  accum = (morsel as u64) << 58;
78 lib.rs:327    4.02 :     1069f:       movzbl (%r9,%rax,1),%r15d
79         :              // fast loop of 8 bytes at a time
80         :              while input_index < length_of_full_chunks {
81         :                  let mut accum: u64;
82         :
83         :                  let input_chunk = BigEndian::read_u64(&input_bytes[input_index..(input_index + 8)]);
84         :                  morsel = decode_table[(input_chunk >> 56) as usize];
85 lib.rs:322    3.68 :     106a4:       cmp    $0xff,%r15
86         :                  if morsel == decode_tables::INVALID_VALUE {
87    0.00 :        106ab:       je     1090e <base64::decode_config_buf::hbf68a45fefa299c1+0x46e>
88```
89
90
91Fuzzing
92---
93
94This 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:
95
96```
97cargo +nightly fuzz run roundtrip
98cargo +nightly fuzz run roundtrip_no_pad
99cargo +nightly fuzz run roundtrip_random_config -- -max_len=10240
100```
101
102
103License
104---
105
106This project is dual-licensed under MIT and Apache 2.0.
107