base64 0.9.3

encodes and decodes base64 as bytes or utf8
Documentation
#![feature(test)]

extern crate base64;
extern crate rand;
extern crate test;

use base64::display;
use base64::{decode, decode_config_buf, decode_config_slice, encode, encode_config_buf,
             encode_config_slice, Config, MIME, STANDARD};

use rand::Rng;
use test::Bencher;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3, STANDARD)
}

#[bench]
fn encode_3b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3, STANDARD)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_display(b: &mut Bencher) {
    do_encode_bench_display(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50, STANDARD)
}

#[bench]
fn encode_50b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 50, STANDARD)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100, STANDARD)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, STANDARD)
}

#[bench]
fn encode_500b_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, MIME)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, MIME)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_3mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_3b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_50b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3kib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    b.bytes = encoded.len() as u64;
    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_buf(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_decode_bench_slice(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    buf.resize(size, 0);
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_slice(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_display(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = format!("{}", display::Base64Display::standard(&v));
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.bytes = v.len() as u64;
    b.iter(|| {
        encode_config_buf(&v, config, &mut buf);
        buf.clear();
    });
}

fn do_encode_bench_slice(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;
    // conservative estimate of encoded size
    buf.resize(size * 2, 0);
    b.iter(|| {
        encode_config_slice(&v, config, &mut buf);
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}