diff options
Diffstat (limited to 'third_party/rust/base64/src/lib.rs')
-rw-r--r-- | third_party/rust/base64/src/lib.rs | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/third_party/rust/base64/src/lib.rs b/third_party/rust/base64/src/lib.rs new file mode 100644 index 0000000000..6bded16066 --- /dev/null +++ b/third_party/rust/base64/src/lib.rs @@ -0,0 +1,245 @@ +//! # Configs +//! +//! There isn't just one type of Base64; that would be too simple. You need to choose a character +//! set (standard, URL-safe, etc) and padding suffix (yes/no). +//! The `Config` struct encapsulates this info. There are some common configs included: `STANDARD`, +//! `URL_SAFE`, 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 as per the config. +//! +//! # Decoding +//! +//! Just as for encoding, there are different decoding functions available. +//! +//! | 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. +//! +//! # `Read` and `Write` +//! +//! To map a `Read` of b64 bytes to the decoded bytes, wrap a reader (file, network socket, etc) +//! with `base64::read::DecoderReader`. To write raw bytes and have them b64 encoded on the fly, +//! wrap a writer with `base64::write::EncoderWriter`. There is some performance overhead (15% or +//! so) because of the necessary buffer shuffling -- still fast enough that almost nobody cares. +//! Also, these implementations do not heap allocate. +//! +//! # 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, + +#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))] +#![deny( + missing_docs, + trivial_casts, + trivial_numeric_casts, + unused_extern_crates, + unused_import_braces, + unused_results, + variant_size_differences, + warnings +)] +#![forbid(unsafe_code)] +#![cfg_attr(not(any(feature = "std", test)), no_std)] + +#[cfg(all(feature = "alloc", not(any(feature = "std", test))))] +extern crate alloc; +#[cfg(any(feature = "std", test))] +extern crate std as alloc; + +mod chunked_encoder; +pub mod display; +#[cfg(any(feature = "std", test))] +pub mod read; +mod tables; +#[cfg(any(feature = "std", test))] +pub mod write; + +mod encode; +pub use crate::encode::encode_config_slice; +#[cfg(any(feature = "alloc", feature = "std", test))] +pub use crate::encode::{encode, encode_config, encode_config_buf}; + +mod decode; +#[cfg(any(feature = "alloc", feature = "std", test))] +pub use crate::decode::{decode, decode_config, decode_config_buf}; +pub use crate::decode::{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 `/`). + /// + /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3). + Standard, + /// The URL safe character set (uses `-` and `_`). + /// + /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4). + UrlSafe, + /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`). + /// + /// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses. + Crypt, + /// The bcrypt character set (uses `./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`). + Bcrypt, + /// The character set used in IMAP-modified UTF-7 (uses `+` and `,`). + /// + /// See [RFC 3501](https://tools.ietf.org/html/rfc3501#section-5.1.3) + ImapMutf7, + /// The character set used in BinHex 4.0 files. + /// + /// See [BinHex 4.0 Definition](http://files.stairways.com/other/binhex-40-specs-info.txt) + BinHex, +} + +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, + CharacterSet::Bcrypt => tables::BCRYPT_ENCODE, + CharacterSet::ImapMutf7 => tables::IMAP_MUTF7_ENCODE, + CharacterSet::BinHex => tables::BINHEX_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, + CharacterSet::Bcrypt => tables::BCRYPT_DECODE, + CharacterSet::ImapMutf7 => tables::IMAP_MUTF7_DECODE, + CharacterSet::BinHex => tables::BINHEX_DECODE, + } + } +} + +/// 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, + /// True to ignore excess nonzero bits in the last few symbols, otherwise an error is returned. + decode_allow_trailing_bits: bool, +} + +impl Config { + /// Create a new `Config`. + pub const fn new(char_set: CharacterSet, pad: bool) -> Config { + Config { + char_set, + pad, + decode_allow_trailing_bits: false, + } + } + + /// Sets whether to pad output with `=` characters. + pub const fn pad(self, pad: bool) -> Config { + Config { pad, ..self } + } + + /// Sets whether to emit errors for nonzero trailing bits. + /// + /// This is useful when implementing + /// [forgiving-base64 decode](https://infra.spec.whatwg.org/#forgiving-base64-decode). + pub const fn decode_allow_trailing_bits(self, allow: bool) -> Config { + Config { + decode_allow_trailing_bits: allow, + ..self + } + } +} + +/// Standard character set with padding. +pub const STANDARD: Config = Config { + char_set: CharacterSet::Standard, + pad: true, + decode_allow_trailing_bits: false, +}; + +/// Standard character set without padding. +pub const STANDARD_NO_PAD: Config = Config { + char_set: CharacterSet::Standard, + pad: false, + decode_allow_trailing_bits: false, +}; + +/// URL-safe character set with padding +pub const URL_SAFE: Config = Config { + char_set: CharacterSet::UrlSafe, + pad: true, + decode_allow_trailing_bits: false, +}; + +/// URL-safe character set without padding +pub const URL_SAFE_NO_PAD: Config = Config { + char_set: CharacterSet::UrlSafe, + pad: false, + decode_allow_trailing_bits: false, +}; + +/// As per `crypt(3)` requirements +pub const CRYPT: Config = Config { + char_set: CharacterSet::Crypt, + pad: false, + decode_allow_trailing_bits: false, +}; + +/// Bcrypt character set +pub const BCRYPT: Config = Config { + char_set: CharacterSet::Bcrypt, + pad: false, + decode_allow_trailing_bits: false, +}; + +/// IMAP modified UTF-7 requirements +pub const IMAP_MUTF7: Config = Config { + char_set: CharacterSet::ImapMutf7, + pad: false, + decode_allow_trailing_bits: false, +}; + +/// BinHex character set +pub const BINHEX: Config = Config { + char_set: CharacterSet::BinHex, + pad: false, + decode_allow_trailing_bits: false, +}; + +const PAD_BYTE: u8 = b'='; |