base64 0.9.2

encodes and decodes base64 as bytes or utf8
Documentation
//! # Configs
//!
//! There isn't just one type of Base64; that would be too simple. You need to choose a character
//! set (standard or URL-safe), padding suffix (yes/no), and line wrap (line length, line ending).
//! The `Config` struct encapsulates this info. There are some common configs included: `STANDARD`,
//! `MIME`, etc. You can also make your own `Config` if needed.
//!
//! The functions that don't have `config` in the name (e.g. `encode()` and `decode()`) use the
//! `STANDARD` config .
//!
//! The functions that write to a slice (the ones that end in `_slice`) are generally the fastest
//! because they don't need to resize anything. If it fits in your workflow and you care about
//! performance, keep using the same buffer (growing as need be) and use the `_slice` methods for
//! the best performance.
//!
//! # Encoding
//!
//! Several different encoding functions are available to you depending on your desire for
//! convenience vs performance.
//!
//! | Function                | Output                       | Allocates                      |
//! | ----------------------- | ---------------------------- | ------------------------------ |
//! | `encode`                | Returns a new `String`       | Always                         |
//! | `encode_config`         | Returns a new `String`       | Always                         |
//! | `encode_config_buf`     | Appends to provided `String` | Only if `String` needs to grow |
//! | `encode_config_slice`   | Writes to provided `&[u8]`   | Never                          |
//!
//! All of the encoding functions that take a `Config` will pad, line wrap, etc, as per the config.
//!
//! # Decoding
//!
//! Just as for encoding, there are different decoding functions available.
//!
//! Note that all decode functions that take a config will allocate a copy of the input if you
//! specify a config that requires whitespace to be stripped. If you care about speed, don't use
//! formats that line wrap and then require whitespace stripping.
//!
//! | Function                | Output                        | Allocates                      |
//! | ----------------------- | ----------------------------- | ------------------------------ |
//! | `decode`                | Returns a new `Vec<u8>`       | Always                         |
//! | `decode_config`         | Returns a new `Vec<u8>`       | Always                         |
//! | `decode_config_buf`     | Appends to provided `Vec<u8>` | Only if `Vec` needs to grow    |
//! | `decode_config_slice`   | Writes to provided `&[u8]`    | Never                          |
//!
//! Unlike encoding, where all possible input is valid, decoding can fail (see `DecodeError`).
//!
//! Input can be invalid because it has invalid characters or invalid padding. (No padding at all is
//! valid, but excess padding is not.)
//!
//! Whitespace in the input is invalid unless `strip_whitespace` is enabled in the `Config` used.
//!
//! # Panics
//!
//! If length calculations result in overflowing `usize`, a panic will result.
//!
//! The `_slice` flavors of encode or decode will panic if the provided output slice is too small,

#![deny(
    missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
    unused_results, variant_size_differences, warnings
)]

extern crate byteorder;

mod chunked_encoder;
pub mod display;
mod line_wrap;
mod tables;

use line_wrap::{line_wrap, line_wrap_parameters};

mod encode;
pub use encode::{encode, encode_config, encode_config_buf, encode_config_slice};

mod decode;
pub use decode::{decode, decode_config, decode_config_buf, decode_config_slice, DecodeError};

#[cfg(test)]
mod tests;

/// Available encoding character sets
#[derive(Clone, Copy, Debug)]
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe,
    /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`)
    Crypt,
}

impl CharacterSet {
    fn encode_table(&self) -> &'static [u8; 64] {
        match *self {
            CharacterSet::Standard => tables::STANDARD_ENCODE,
            CharacterSet::UrlSafe => tables::URL_SAFE_ENCODE,
            CharacterSet::Crypt => tables::CRYPT_ENCODE,
        }
    }

    fn decode_table(&self) -> &'static [u8; 256] {
        match *self {
            CharacterSet::Standard => tables::STANDARD_DECODE,
            CharacterSet::UrlSafe => tables::URL_SAFE_DECODE,
            CharacterSet::Crypt => tables::CRYPT_DECODE,
        }
    }
}

/// Line ending used in optional line wrapping.
#[derive(Clone, Copy, Debug)]
pub enum LineEnding {
    /// Unix-style \n
    LF,
    /// Windows-style \r\n
    CRLF,
}

impl LineEnding {
    fn len(&self) -> usize {
        match *self {
            LineEnding::LF => 1,
            LineEnding::CRLF => 2,
        }
    }
}

/// Line wrap configuration.
#[derive(Clone, Copy, Debug)]
pub enum LineWrap {
    /// Don't wrap.
    NoWrap,
    /// Wrap lines with the specified length and line ending. The length must be > 0.
    Wrap(usize, LineEnding),
}

/// Contains configuration parameters for base64 encoding
#[derive(Clone, Copy, Debug)]
pub struct Config {
    /// Character set to use
    char_set: CharacterSet,
    /// True to pad output with `=` characters
    pad: bool,
    /// Remove whitespace before decoding, at the cost of an allocation. Whitespace is defined
    /// according to POSIX-locale `isspace`, meaning \n \r \f \t \v and space.
    strip_whitespace: bool,
    /// ADT signifying whether to linewrap output, and if so by how many characters and with what
    /// ending
    line_wrap: LineWrap,
}

impl Config {
    /// Create a new `Config`.
    pub fn new(
        char_set: CharacterSet,
        pad: bool,
        strip_whitespace: bool,
        input_line_wrap: LineWrap,
    ) -> Config {
        let line_wrap = match input_line_wrap {
            LineWrap::Wrap(0, _) => LineWrap::NoWrap,
            _ => input_line_wrap,
        };

        Config {
            char_set,
            pad,
            strip_whitespace,
            line_wrap,
        }
    }
}

/// Standard character set with padding.
pub const STANDARD: Config = Config {
    char_set: CharacterSet::Standard,
    pad: true,
    strip_whitespace: false,
    line_wrap: LineWrap::NoWrap,
};

/// Standard character set without padding.
pub const STANDARD_NO_PAD: Config = Config {
    char_set: CharacterSet::Standard,
    pad: false,
    strip_whitespace: false,
    line_wrap: LineWrap::NoWrap,
};

/// As per standards for MIME encoded messages
pub const MIME: Config = Config {
    char_set: CharacterSet::Standard,
    pad: true,
    strip_whitespace: true,
    line_wrap: LineWrap::Wrap(76, LineEnding::CRLF),
};

/// URL-safe character set with padding
pub const URL_SAFE: Config = Config {
    char_set: CharacterSet::UrlSafe,
    pad: true,
    strip_whitespace: false,
    line_wrap: LineWrap::NoWrap,
};

/// URL-safe character set without padding
pub const URL_SAFE_NO_PAD: Config = Config {
    char_set: CharacterSet::UrlSafe,
    pad: false,
    strip_whitespace: false,
    line_wrap: LineWrap::NoWrap,
};

/// As per `crypt(3)` requirements
pub const CRYPT: Config = Config {
    char_set: CharacterSet::Crypt,
    pad: false,
    strip_whitespace: false,
    line_wrap: LineWrap::NoWrap,
};