diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:44:51 +0000 |
commit | 9e3c08db40b8916968b9f30096c7be3f00ce9647 (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/rust/data-encoding | |
parent | Initial commit. (diff) | |
download | thunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.tar.xz thunderbird-9e3c08db40b8916968b9f30096c7be3f00ce9647.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/data-encoding')
-rw-r--r-- | third_party/rust/data-encoding/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/data-encoding/Cargo.toml | 43 | ||||
-rw-r--r-- | third_party/rust/data-encoding/LICENSE | 22 | ||||
-rw-r--r-- | third_party/rust/data-encoding/README.md | 34 | ||||
-rw-r--r-- | third_party/rust/data-encoding/src/lib.rs | 2394 |
5 files changed, 2494 insertions, 0 deletions
diff --git a/third_party/rust/data-encoding/.cargo-checksum.json b/third_party/rust/data-encoding/.cargo-checksum.json new file mode 100644 index 0000000000..6881e11450 --- /dev/null +++ b/third_party/rust/data-encoding/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"8e951c8c17231134e3d1a5450a8355509ae87046aff9a64721bb785cf245a72e","LICENSE":"b68ad1a3367b825447089e1f8d6829b97f47a89eb78d2f4ebaef4672f5606186","README.md":"ac92e91c7165d183c7578f78557608c7ffaa3033cbfcb04ab879d80454b0955a","src/lib.rs":"51a950c3b3ad7ad512743834a831a80bcc39091f5d3c0927e1a5f98daed213f6"},"package":"23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"}
\ No newline at end of file diff --git a/third_party/rust/data-encoding/Cargo.toml b/third_party/rust/data-encoding/Cargo.toml new file mode 100644 index 0000000000..36294764a9 --- /dev/null +++ b/third_party/rust/data-encoding/Cargo.toml @@ -0,0 +1,43 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +rust-version = "1.46" +name = "data-encoding" +version = "2.3.3" +authors = ["Julien Cretin <git@ia0.eu>"] +include = [ + "Cargo.toml", + "LICENSE", + "README.md", + "src/lib.rs", +] +description = "Efficient and customizable data-encoding functions like base64, base32, and hex" +documentation = "https://docs.rs/data-encoding" +readme = "README.md" +keywords = [ + "no_std", + "base64", + "base32", + "hex", +] +categories = [ + "encoding", + "no-std", +] +license = "MIT" +repository = "https://github.com/ia0/data-encoding" + +[features] +alloc = [] +default = ["std"] +std = ["alloc"] diff --git a/third_party/rust/data-encoding/LICENSE b/third_party/rust/data-encoding/LICENSE new file mode 100644 index 0000000000..9a750833a0 --- /dev/null +++ b/third_party/rust/data-encoding/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015-2020 Julien Cretin +Copyright (c) 2017-2020 Google Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/rust/data-encoding/README.md b/third_party/rust/data-encoding/README.md new file mode 100644 index 0000000000..64d2dec6d7 --- /dev/null +++ b/third_party/rust/data-encoding/README.md @@ -0,0 +1,34 @@ +[![CI Status][ci_badge]][ci] +[![Coverage Status][coveralls_badge]][coveralls] + +This library provides the following common encodings: + +| Name | Description | +| --- | --- | +| `HEXLOWER` | lowercase hexadecimal | +| `HEXLOWER_PERMISSIVE` | lowercase hexadecimal (case-insensitive decoding) | +| `HEXUPPER` | uppercase hexadecimal | +| `HEXUPPER_PERMISSIVE` | uppercase hexadecimal (case-insensitive decoding) | +| `BASE32` | RFC4648 base32 | +| `BASE32_NOPAD` | RFC4648 base32 (no padding) | +| `BASE32_DNSSEC` | RFC5155 base32 | +| `BASE32_DNSCURVE` | DNSCurve base32 | +| `BASE32HEX` | RFC4648 base32hex | +| `BASE32HEX_NOPAD` | RFC4648 base32hex (no padding) | +| `BASE64` | RFC4648 base64 | +| `BASE64_NOPAD` | RFC4648 base64 (no padding) | +| `BASE64_MIME` | RFC2045-like base64 | +| `BASE64URL` | RFC4648 base64url | +| `BASE64URL_NOPAD` | RFC4648 base64url (no padding) | + +It also provides the possibility to define custom little-endian ASCII +base-conversion encodings for bases of size 2, 4, 8, 16, 32, and 64 (for which +all above use-cases are particular instances). + +See the [documentation] for more details. + +[ci]: https://github.com/ia0/data-encoding/actions/workflows/ci.yml +[ci_badge]: https://github.com/ia0/data-encoding/actions/workflows/ci.yml/badge.svg +[coveralls]: https://coveralls.io/github/ia0/data-encoding?branch=master +[coveralls_badge]: https://coveralls.io/repos/github/ia0/data-encoding/badge.svg?branch=master +[documentation]: https://docs.rs/data-encoding diff --git a/third_party/rust/data-encoding/src/lib.rs b/third_party/rust/data-encoding/src/lib.rs new file mode 100644 index 0000000000..31df668d96 --- /dev/null +++ b/third_party/rust/data-encoding/src/lib.rs @@ -0,0 +1,2394 @@ +//! Efficient and customizable data-encoding functions like base64, base32, and hex +//! +//! This [crate] provides little-endian ASCII base-conversion encodings for +//! bases of size 2, 4, 8, 16, 32, and 64. It supports: +//! +//! - [padding] for streaming +//! - canonical encodings (e.g. [trailing bits] are checked) +//! - in-place [encoding] and [decoding] functions +//! - partial [decoding] functions (e.g. for error recovery) +//! - character [translation] (e.g. for case-insensitivity) +//! - most and least significant [bit-order] +//! - [ignoring] characters when decoding (e.g. for skipping newlines) +//! - [wrapping] the output when encoding +//! - no-std environments with `default-features = false, features = ["alloc"]` +//! - no-alloc environments with `default-features = false` +//! +//! You may use the [binary] or the [website] to play around. +//! +//! # Examples +//! +//! This crate provides predefined encodings as [constants]. These constants are of type +//! [`Encoding`]. This type provides encoding and decoding functions with in-place or allocating +//! variants. Here is an example using the allocating encoding function of [`BASE64`]: +//! +//! ```rust +//! use data_encoding::BASE64; +//! assert_eq!(BASE64.encode(b"Hello world"), "SGVsbG8gd29ybGQ="); +//! ``` +//! +//! Here is an example using the in-place decoding function of [`BASE32`]: +//! +//! ```rust +//! use data_encoding::BASE32; +//! let input = b"JBSWY3DPEB3W64TMMQ======"; +//! let mut output = vec![0; BASE32.decode_len(input.len()).unwrap()]; +//! let len = BASE32.decode_mut(input, &mut output).unwrap(); +//! assert_eq!(&output[0 .. len], b"Hello world"); +//! ``` +//! +//! You are not limited to the predefined encodings. You may define your own encodings (with the +//! same correctness and performance properties as the predefined ones) using the [`Specification`] +//! type: +//! +//! ```rust +//! use data_encoding::Specification; +//! let hex = { +//! let mut spec = Specification::new(); +//! spec.symbols.push_str("0123456789abcdef"); +//! spec.encoding().unwrap() +//! }; +//! assert_eq!(hex.encode(b"hello"), "68656c6c6f"); +//! ``` +//! +//! You may use the [macro] library to define a compile-time custom encoding: +//! +//! ```rust,ignore +//! use data_encoding::Encoding; +//! use data_encoding_macro::new_encoding; +//! const HEX: Encoding = new_encoding!{ +//! symbols: "0123456789abcdef", +//! translate_from: "ABCDEF", +//! translate_to: "abcdef", +//! }; +//! const BASE64: Encoding = new_encoding!{ +//! symbols: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", +//! padding: '=', +//! }; +//! ``` +//! +//! # Properties +//! +//! The [`HEXUPPER`], [`BASE32`], [`BASE32HEX`], [`BASE64`], and [`BASE64URL`] predefined encodings +//! are conform to [RFC4648]. +//! +//! In general, the encoding and decoding functions satisfy the following properties: +//! +//! - They are deterministic: their output only depends on their input +//! - They have no side-effects: they do not modify a hidden mutable state +//! - They are correct: encoding then decoding gives the initial data +//! - They are canonical (unless [`is_canonical`] returns false): decoding then encoding gives the +//! initial data +//! +//! This last property is usually not satisfied by base64 implementations. This is a matter of +//! choice and this crate has made the choice to let the user choose. Support for canonical encoding +//! as described by the [RFC][canonical] is provided. But it is also possible to disable checking +//! trailing bits, to add characters translation, to decode concatenated padded inputs, and to +//! ignore some characters. +//! +//! Since the RFC specifies the encoding function on all inputs and the decoding function on all +//! possible encoded outputs, the differences between implementations come from the decoding +//! function which may be more or less permissive. In this crate, the decoding function of canonical +//! encodings rejects all inputs that are not a possible output of the encoding function. Here are +//! some concrete examples of decoding differences between this crate, the `base64` crate, and the +//! `base64` GNU program: +//! +//! | Input | `data-encoding` | `base64` | GNU `base64` | +//! | ---------- | --------------- | --------- | ------------- | +//! | `AAB=` | `Trailing(2)` | `Last(2)` | `\x00\x00` | +//! | `AA\nB=` | `Length(4)` | `Length` | `\x00\x00` | +//! | `AAB` | `Length(0)` | `Last(2)` | Invalid input | +//! | `AAA` | `Length(0)` | `[0, 0]` | Invalid input | +//! | `A\rA\nB=` | `Length(4)` | `Byte(1)` | Invalid input | +//! | `-_\r\n` | `Symbol(0)` | `Byte(0)` | Invalid input | +//! | `AA==AA==` | `[0, 0]` | `Byte(2)` | `\x00\x00` | +//! +//! We can summarize these discrepancies as follows: +//! +//! | Discrepancy | `data-encoding` | `base64` | GNU `base64` | +//! | -------------------------- | --------------- | -------- | ------------ | +//! | Check trailing bits | Yes | Yes | No | +//! | Ignored characters | None | None | `\n` | +//! | Translated characters | None | None | None | +//! | Check padding | Yes | No | Yes | +//! | Support concatenated input | Yes | No | Yes | +//! +//! This crate permits to disable checking trailing bits. It permits to ignore some characters. It +//! permits to translate characters. It permits to use unpadded encodings. However, for padded +//! encodings, support for concatenated inputs cannot be disabled. This is simply because it doesn't +//! make sense to use padding if it is not to support concatenated inputs. +//! +//! [RFC4648]: https://tools.ietf.org/html/rfc4648 +//! [`BASE32HEX`]: constant.BASE32HEX.html +//! [`BASE32`]: constant.BASE32.html +//! [`BASE64URL`]: constant.BASE64URL.html +//! [`BASE64`]: constant.BASE64.html +//! [`Encoding`]: struct.Encoding.html +//! [`HEXUPPER`]: constant.HEXUPPER.html +//! [`Specification`]: struct.Specification.html +//! [`is_canonical`]: struct.Encoding.html#method.is_canonical +//! [binary]: https://crates.io/crates/data-encoding-bin +//! [bit-order]: struct.Specification.html#structfield.bit_order +//! [canonical]: https://tools.ietf.org/html/rfc4648#section-3.5 +//! [constants]: index.html#constants +//! [crate]: https://crates.io/crates/data-encoding +//! [decoding]: struct.Encoding.html#method.decode_mut +//! [encoding]: struct.Encoding.html#method.encode_mut +//! [ignoring]: struct.Specification.html#structfield.ignore +//! [macro]: https://crates.io/crates/data-encoding-macro +//! [padding]: struct.Specification.html#structfield.padding +//! [trailing bits]: struct.Specification.html#structfield.check_trailing_bits +//! [translation]: struct.Specification.html#structfield.translate +//! [website]: https://data-encoding.rs +//! [wrapping]: struct.Specification.html#structfield.wrap + +#![no_std] +#![warn(unused_results, missing_docs)] + +#[cfg(feature = "alloc")] +extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "alloc")] +use alloc::borrow::{Cow, ToOwned}; +#[cfg(feature = "alloc")] +use alloc::string::String; +#[cfg(feature = "alloc")] +use alloc::vec; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + +macro_rules! check { + ($e: expr, $c: expr) => { + if !$c { + return Err($e); + } + }; +} + +trait Static<T: Copy>: Copy { + fn val(self) -> T; +} + +macro_rules! define { + ($name: ident: $type: ty = $val: expr) => { + #[derive(Copy, Clone)] + struct $name; + impl Static<$type> for $name { + fn val(self) -> $type { + $val + } + } + }; +} + +define!(Bf: bool = false); +define!(Bt: bool = true); +define!(N1: usize = 1); +define!(N2: usize = 2); +define!(N3: usize = 3); +define!(N4: usize = 4); +define!(N5: usize = 5); +define!(N6: usize = 6); + +#[derive(Copy, Clone)] +struct On; + +impl<T: Copy> Static<Option<T>> for On { + fn val(self) -> Option<T> { + None + } +} + +#[derive(Copy, Clone)] +struct Os<T>(T); + +impl<T: Copy> Static<Option<T>> for Os<T> { + fn val(self) -> Option<T> { + Some(self.0) + } +} + +macro_rules! dispatch { + (let $var: ident: bool = $val: expr; $($body: tt)*) => { + if $val { + let $var = Bt; dispatch!($($body)*) + } else { + let $var = Bf; dispatch!($($body)*) + } + }; + (let $var: ident: usize = $val: expr; $($body: tt)*) => { + match $val { + 1 => { let $var = N1; dispatch!($($body)*) }, + 2 => { let $var = N2; dispatch!($($body)*) }, + 3 => { let $var = N3; dispatch!($($body)*) }, + 4 => { let $var = N4; dispatch!($($body)*) }, + 5 => { let $var = N5; dispatch!($($body)*) }, + 6 => { let $var = N6; dispatch!($($body)*) }, + _ => panic!(), + } + }; + (let $var: ident: Option<$type: ty> = $val: expr; $($body: tt)*) => { + match $val { + None => { let $var = On; dispatch!($($body)*) }, + Some(x) => { let $var = Os(x); dispatch!($($body)*) }, + } + }; + ($body: expr) => { $body }; +} + +unsafe fn chunk_unchecked(x: &[u8], n: usize, i: usize) -> &[u8] { + debug_assert!((i + 1) * n <= x.len()); + let ptr = x.as_ptr().add(n * i); + core::slice::from_raw_parts(ptr, n) +} + +unsafe fn chunk_mut_unchecked(x: &mut [u8], n: usize, i: usize) -> &mut [u8] { + debug_assert!((i + 1) * n <= x.len()); + let ptr = x.as_mut_ptr().add(n * i); + core::slice::from_raw_parts_mut(ptr, n) +} + +unsafe fn as_array(x: &[u8]) -> &[u8; 256] { + debug_assert_eq!(x.len(), 256); + &*(x.as_ptr() as *const [u8; 256]) +} + +fn div_ceil(x: usize, m: usize) -> usize { + (x + m - 1) / m +} + +fn floor(x: usize, m: usize) -> usize { + x / m * m +} + +fn vectorize<F: FnMut(usize)>(n: usize, bs: usize, mut f: F) { + for k in 0 .. n / bs { + for i in k * bs .. (k + 1) * bs { + f(i); + } + } + for i in floor(n, bs) .. n { + f(i); + } +} + +/// Decoding error kind +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum DecodeKind { + /// Invalid length + Length, + + /// Invalid symbol + Symbol, + + /// Non-zero trailing bits + Trailing, + + /// Invalid padding length + Padding, +} + +impl core::fmt::Display for DecodeKind { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + let description = match self { + DecodeKind::Length => "invalid length", + DecodeKind::Symbol => "invalid symbol", + DecodeKind::Trailing => "non-zero trailing bits", + DecodeKind::Padding => "invalid padding length", + }; + write!(f, "{}", description) + } +} + +/// Decoding error +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct DecodeError { + /// Error position + /// + /// This position is always a valid input position and represents the first encountered error. + pub position: usize, + + /// Error kind + pub kind: DecodeKind, +} + +#[cfg(feature = "std")] +impl std::error::Error for DecodeError {} + +impl core::fmt::Display for DecodeError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + write!(f, "{} at {}", self.kind, self.position) + } +} + +/// Decoding error with partial result +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct DecodePartial { + /// Number of bytes read from input + /// + /// This number does not exceed the error position: `read <= error.position`. + pub read: usize, + + /// Number of bytes written to output + /// + /// This number does not exceed the decoded length: `written <= decode_len(read)`. + pub written: usize, + + /// Decoding error + pub error: DecodeError, +} + +const INVALID: u8 = 128; +const IGNORE: u8 = 129; +const PADDING: u8 = 130; + +fn order(msb: bool, n: usize, i: usize) -> usize { + if msb { + n - 1 - i + } else { + i + } +} + +fn enc(bit: usize) -> usize { + match bit { + 1 | 2 | 4 => 1, + 3 | 6 => 3, + 5 => 5, + _ => unreachable!(), + } +} + +fn dec(bit: usize) -> usize { + enc(bit) * 8 / bit +} + +fn encode_len<B: Static<usize>>(bit: B, len: usize) -> usize { + div_ceil(8 * len, bit.val()) +} + +fn encode_block<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8], +) { + debug_assert!(input.len() <= enc(bit.val())); + debug_assert_eq!(output.len(), encode_len(bit, input.len())); + let bit = bit.val(); + let msb = msb.val(); + let mut x = 0u64; + for (i, input) in input.iter().enumerate() { + x |= u64::from(*input) << (8 * order(msb, enc(bit), i)); + } + for (i, output) in output.iter_mut().enumerate() { + let y = x >> (bit * order(msb, dec(bit), i)); + *output = symbols[y as usize % 256]; + } +} + +fn encode_mut<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8], +) { + debug_assert_eq!(output.len(), encode_len(bit, input.len())); + let enc = enc(bit.val()); + let dec = dec(bit.val()); + let n = input.len() / enc; + let bs = match bit.val() { + 5 => 2, + 6 => 4, + _ => 1, + }; + vectorize(n, bs, |i| { + let input = unsafe { chunk_unchecked(input, enc, i) }; + let output = unsafe { chunk_mut_unchecked(output, dec, i) }; + encode_block(bit, msb, symbols, input, output); + }); + encode_block(bit, msb, symbols, &input[enc * n ..], &mut output[dec * n ..]); +} + +// Fails if an input character does not translate to a symbol. The error is the +// lowest index of such character. The output is not written to. +fn decode_block<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, values: &[u8; 256], input: &[u8], output: &mut [u8], +) -> Result<(), usize> { + debug_assert!(output.len() <= enc(bit.val())); + debug_assert_eq!(input.len(), encode_len(bit, output.len())); + let bit = bit.val(); + let msb = msb.val(); + let mut x = 0u64; + for j in 0 .. input.len() { + let y = values[input[j] as usize]; + check!(j, y < 1 << bit); + x |= u64::from(y) << (bit * order(msb, dec(bit), j)); + } + for (j, output) in output.iter_mut().enumerate() { + *output = (x >> (8 * order(msb, enc(bit), j))) as u8; + } + Ok(()) +} + +// Fails if an input character does not translate to a symbol. The error `pos` +// is the lowest index of such character. The output is valid up to `pos / dec * +// enc` excluded. +fn decode_mut<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, values: &[u8; 256], input: &[u8], output: &mut [u8], +) -> Result<(), usize> { + debug_assert_eq!(input.len(), encode_len(bit, output.len())); + let enc = enc(bit.val()); + let dec = dec(bit.val()); + let n = input.len() / dec; + for i in 0 .. n { + let input = unsafe { chunk_unchecked(input, dec, i) }; + let output = unsafe { chunk_mut_unchecked(output, enc, i) }; + decode_block(bit, msb, values, input, output).map_err(|e| dec * i + e)?; + } + decode_block(bit, msb, values, &input[dec * n ..], &mut output[enc * n ..]) + .map_err(|e| dec * n + e) +} + +// Fails if there are non-zero trailing bits. +fn check_trail<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, ctb: bool, values: &[u8; 256], input: &[u8], +) -> Result<(), ()> { + if 8 % bit.val() == 0 || !ctb { + return Ok(()); + } + let trail = bit.val() * input.len() % 8; + if trail == 0 { + return Ok(()); + } + let mut mask = (1 << trail) - 1; + if !msb.val() { + mask <<= bit.val() - trail; + } + check!((), values[input[input.len() - 1] as usize] & mask == 0); + Ok(()) +} + +// Fails if the padding length is invalid. The error is the index of the first +// padding character. +fn check_pad<B: Static<usize>>(bit: B, values: &[u8; 256], input: &[u8]) -> Result<usize, usize> { + let bit = bit.val(); + debug_assert_eq!(input.len(), dec(bit)); + let is_pad = |x: &&u8| values[**x as usize] == PADDING; + let count = input.iter().rev().take_while(is_pad).count(); + let len = input.len() - count; + check!(len, len > 0 && bit * len % 8 < bit); + Ok(len) +} + +fn encode_base_len<B: Static<usize>>(bit: B, len: usize) -> usize { + encode_len(bit, len) +} + +fn encode_base<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8], +) { + debug_assert_eq!(output.len(), encode_base_len(bit, input.len())); + encode_mut(bit, msb, symbols, input, output); +} + +fn encode_pad_len<B: Static<usize>, P: Static<Option<u8>>>(bit: B, pad: P, len: usize) -> usize { + match pad.val() { + None => encode_base_len(bit, len), + Some(_) => div_ceil(len, enc(bit.val())) * dec(bit.val()), + } +} + +fn encode_pad<B: Static<usize>, M: Static<bool>, P: Static<Option<u8>>>( + bit: B, msb: M, symbols: &[u8; 256], spad: P, input: &[u8], output: &mut [u8], +) { + let pad = match spad.val() { + None => return encode_base(bit, msb, symbols, input, output), + Some(pad) => pad, + }; + debug_assert_eq!(output.len(), encode_pad_len(bit, spad, input.len())); + let olen = encode_base_len(bit, input.len()); + encode_base(bit, msb, symbols, input, &mut output[.. olen]); + for output in output.iter_mut().skip(olen) { + *output = pad; + } +} + +fn encode_wrap_len< + 'a, + B: Static<usize>, + P: Static<Option<u8>>, + W: Static<Option<(usize, &'a [u8])>>, +>( + bit: B, pad: P, wrap: W, ilen: usize, +) -> usize { + let olen = encode_pad_len(bit, pad, ilen); + match wrap.val() { + None => olen, + Some((col, end)) => olen + end.len() * div_ceil(olen, col), + } +} + +fn encode_wrap_mut< + 'a, + B: Static<usize>, + M: Static<bool>, + P: Static<Option<u8>>, + W: Static<Option<(usize, &'a [u8])>>, +>( + bit: B, msb: M, symbols: &[u8; 256], pad: P, wrap: W, input: &[u8], output: &mut [u8], +) { + let (col, end) = match wrap.val() { + None => return encode_pad(bit, msb, symbols, pad, input, output), + Some((col, end)) => (col, end), + }; + debug_assert_eq!(output.len(), encode_wrap_len(bit, pad, wrap, input.len())); + debug_assert_eq!(col % dec(bit.val()), 0); + let col = col / dec(bit.val()); + let enc = col * enc(bit.val()); + let dec = col * dec(bit.val()) + end.len(); + let olen = dec - end.len(); + let n = input.len() / enc; + for i in 0 .. n { + let input = unsafe { chunk_unchecked(input, enc, i) }; + let output = unsafe { chunk_mut_unchecked(output, dec, i) }; + encode_base(bit, msb, symbols, input, &mut output[.. olen]); + output[olen ..].copy_from_slice(end); + } + if input.len() > enc * n { + let olen = dec * n + encode_pad_len(bit, pad, input.len() - enc * n); + encode_pad(bit, msb, symbols, pad, &input[enc * n ..], &mut output[dec * n .. olen]); + output[olen ..].copy_from_slice(end); + } +} + +// Returns the longest valid input length and associated output length. +fn decode_wrap_len<B: Static<usize>, P: Static<bool>>( + bit: B, pad: P, len: usize, +) -> (usize, usize) { + let bit = bit.val(); + if pad.val() { + (floor(len, dec(bit)), len / dec(bit) * enc(bit)) + } else { + let trail = bit * len % 8; + (len - trail / bit, bit * len / 8) + } +} + +// Fails with Length if length is invalid. The error is the largest valid +// length. +fn decode_pad_len<B: Static<usize>, P: Static<bool>>( + bit: B, pad: P, len: usize, +) -> Result<usize, DecodeError> { + let (ilen, olen) = decode_wrap_len(bit, pad, len); + check!(DecodeError { position: ilen, kind: DecodeKind::Length }, ilen == len); + Ok(olen) +} + +// Fails with Length if length is invalid. The error is the largest valid +// length. +fn decode_base_len<B: Static<usize>>(bit: B, len: usize) -> Result<usize, DecodeError> { + decode_pad_len(bit, Bf, len) +} + +// Fails with Symbol if an input character does not translate to a symbol. The +// error is the lowest index of such character. +// Fails with Trailing if there are non-zero trailing bits. +fn decode_base_mut<B: Static<usize>, M: Static<bool>>( + bit: B, msb: M, ctb: bool, values: &[u8; 256], input: &[u8], output: &mut [u8], +) -> Result<usize, DecodePartial> { + debug_assert_eq!(Ok(output.len()), decode_base_len(bit, input.len())); + let fail = |pos, kind| DecodePartial { + read: pos / dec(bit.val()) * dec(bit.val()), + written: pos / dec(bit.val()) * enc(bit.val()), + error: DecodeError { position: pos, kind }, + }; + decode_mut(bit, msb, values, input, output).map_err(|pos| fail(pos, DecodeKind::Symbol))?; + check_trail(bit, msb, ctb, values, input) + .map_err(|()| fail(input.len() - 1, DecodeKind::Trailing))?; + Ok(output.len()) +} + +// Fails with Symbol if an input character does not translate to a symbol. The +// error is the lowest index of such character. +// Fails with Padding if some padding length is invalid. The error is the index +// of the first padding character of the invalid padding. +// Fails with Trailing if there are non-zero trailing bits. +fn decode_pad_mut<B: Static<usize>, M: Static<bool>, P: Static<bool>>( + bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, input: &[u8], output: &mut [u8], +) -> Result<usize, DecodePartial> { + if !pad.val() { + return decode_base_mut(bit, msb, ctb, values, input, output); + } + debug_assert_eq!(Ok(output.len()), decode_pad_len(bit, pad, input.len())); + let enc = enc(bit.val()); + let dec = dec(bit.val()); + let mut inpos = 0; + let mut outpos = 0; + let mut outend = output.len(); + while inpos < input.len() { + match decode_base_mut( + bit, + msb, + ctb, + values, + &input[inpos ..], + &mut output[outpos .. outend], + ) { + Ok(written) => { + if cfg!(debug_assertions) { + inpos = input.len(); + } + outpos += written; + break; + } + Err(partial) => { + inpos += partial.read; + outpos += partial.written; + } + } + let inlen = + check_pad(bit, values, &input[inpos .. inpos + dec]).map_err(|pos| DecodePartial { + read: inpos, + written: outpos, + error: DecodeError { position: inpos + pos, kind: DecodeKind::Padding }, + })?; + let outlen = decode_base_len(bit, inlen).unwrap(); + let written = decode_base_mut( + bit, + msb, + ctb, + values, + &input[inpos .. inpos + inlen], + &mut output[outpos .. outpos + outlen], + ) + .map_err(|partial| { + debug_assert_eq!(partial.read, 0); + debug_assert_eq!(partial.written, 0); + DecodePartial { + read: inpos, + written: outpos, + error: DecodeError { + position: inpos + partial.error.position, + kind: partial.error.kind, + }, + } + })?; + debug_assert_eq!(written, outlen); + inpos += dec; + outpos += outlen; + outend -= enc - outlen; + } + debug_assert_eq!(inpos, input.len()); + debug_assert_eq!(outpos, outend); + Ok(outend) +} + +fn skip_ignore(values: &[u8; 256], input: &[u8], mut inpos: usize) -> usize { + while inpos < input.len() && values[input[inpos] as usize] == IGNORE { + inpos += 1; + } + inpos +} + +// Returns next input and output position. +// Fails with Symbol if an input character does not translate to a symbol. The +// error is the lowest index of such character. +// Fails with Padding if some padding length is invalid. The error is the index +// of the first padding character of the invalid padding. +// Fails with Trailing if there are non-zero trailing bits. +fn decode_wrap_block<B: Static<usize>, M: Static<bool>, P: Static<bool>>( + bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, input: &[u8], output: &mut [u8], +) -> Result<(usize, usize), DecodeError> { + let dec = dec(bit.val()); + let mut buf = [0u8; 8]; + let mut shift = [0usize; 8]; + let mut bufpos = 0; + let mut inpos = 0; + while bufpos < dec { + inpos = skip_ignore(values, input, inpos); + if inpos == input.len() { + break; + } + shift[bufpos] = inpos; + buf[bufpos] = input[inpos]; + bufpos += 1; + inpos += 1; + } + let olen = decode_pad_len(bit, pad, bufpos).map_err(|mut e| { + e.position = shift[e.position]; + e + })?; + let written = decode_pad_mut(bit, msb, ctb, values, pad, &buf[.. bufpos], &mut output[.. olen]) + .map_err(|partial| { + debug_assert_eq!(partial.read, 0); + debug_assert_eq!(partial.written, 0); + DecodeError { position: shift[partial.error.position], kind: partial.error.kind } + })?; + Ok((inpos, written)) +} + +// Fails with Symbol if an input character does not translate to a symbol. The +// error is the lowest index of such character. +// Fails with Padding if some padding length is invalid. The error is the index +// of the first padding character of the invalid padding. +// Fails with Trailing if there are non-zero trailing bits. +// Fails with Length if input length (without ignored characters) is invalid. +#[allow(clippy::too_many_arguments)] +fn decode_wrap_mut<B: Static<usize>, M: Static<bool>, P: Static<bool>, I: Static<bool>>( + bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, has_ignore: I, input: &[u8], + output: &mut [u8], +) -> Result<usize, DecodePartial> { + if !has_ignore.val() { + return decode_pad_mut(bit, msb, ctb, values, pad, input, output); + } + debug_assert_eq!(output.len(), decode_wrap_len(bit, pad, input.len()).1); + let mut inpos = 0; + let mut outpos = 0; + while inpos < input.len() { + let (inlen, outlen) = decode_wrap_len(bit, pad, input.len() - inpos); + match decode_pad_mut( + bit, + msb, + ctb, + values, + pad, + &input[inpos .. inpos + inlen], + &mut output[outpos .. outpos + outlen], + ) { + Ok(written) => { + inpos += inlen; + outpos += written; + break; + } + Err(partial) => { + inpos += partial.read; + outpos += partial.written; + } + } + let (ipos, opos) = + decode_wrap_block(bit, msb, ctb, values, pad, &input[inpos ..], &mut output[outpos ..]) + .map_err(|mut error| { + error.position += inpos; + DecodePartial { read: inpos, written: outpos, error } + })?; + inpos += ipos; + outpos += opos; + } + let inpos = skip_ignore(values, input, inpos); + if inpos == input.len() { + Ok(outpos) + } else { + Err(DecodePartial { + read: inpos, + written: outpos, + error: DecodeError { position: inpos, kind: DecodeKind::Length }, + }) + } +} + +/// Order in which bits are read from a byte +/// +/// The base-conversion encoding is always little-endian. This means that the least significant +/// **byte** is always first. However, we can still choose whether, within a byte, this is the most +/// significant or the least significant **bit** that is first. If the terminology is confusing, +/// testing on an asymmetrical example should be enough to choose the correct value. +/// +/// # Examples +/// +/// In the following example, we can see that a base with the `MostSignificantFirst` bit-order has +/// the most significant bit first in the encoded output. In particular, the output is in the same +/// order as the bits in the byte. The opposite happens with the `LeastSignificantFirst` bit-order. +/// The least significant bit is first and the output is in the reverse order. +/// +/// ```rust +/// use data_encoding::{BitOrder, Specification}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("01"); +/// spec.bit_order = BitOrder::MostSignificantFirst; // default +/// let msb = spec.encoding().unwrap(); +/// spec.bit_order = BitOrder::LeastSignificantFirst; +/// let lsb = spec.encoding().unwrap(); +/// assert_eq!(msb.encode(&[0b01010011]), "01010011"); +/// assert_eq!(lsb.encode(&[0b01010011]), "11001010"); +/// ``` +/// +/// # Features +/// +/// Requires the `alloc` feature. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg(feature = "alloc")] +pub enum BitOrder { + /// Most significant bit first + /// + /// This is the most common and most intuitive bit-order. In particular, this is the bit-order + /// used by [RFC4648] and thus the usual hexadecimal, base64, base32, base64url, and base32hex + /// encodings. This is the default bit-order when [specifying](struct.Specification.html) a + /// base. + /// + /// [RFC4648]: https://tools.ietf.org/html/rfc4648 + MostSignificantFirst, + + /// Least significant bit first + /// + /// # Examples + /// + /// DNSCurve [base32] uses least significant bit first: + /// + /// ```rust + /// use data_encoding::BASE32_DNSCURVE; + /// assert_eq!(BASE32_DNSCURVE.encode(&[0x64, 0x88]), "4321"); + /// assert_eq!(BASE32_DNSCURVE.decode(b"4321").unwrap(), vec![0x64, 0x88]); + /// ``` + /// + /// [base32]: constant.BASE32_DNSCURVE.html + LeastSignificantFirst, +} +#[cfg(feature = "alloc")] +use crate::BitOrder::*; + +#[doc(hidden)] +#[cfg(feature = "alloc")] +pub type InternalEncoding = Cow<'static, [u8]>; + +#[doc(hidden)] +#[cfg(not(feature = "alloc"))] +pub type InternalEncoding = &'static [u8]; + +/// Base-conversion encoding +/// +/// See [Specification](struct.Specification.html) for technical details or how to define a new one. +// Required fields: +// 0 - 256 (256) symbols +// 256 - 512 (256) values +// 512 - 513 ( 1) padding +// 513 - 514 ( 1) reserved(3),ctb(1),msb(1),bit(3) +// Optional fields: +// 514 - 515 ( 1) width +// 515 - * ( N) separator +// Invariants: +// - symbols is 2^bit unique characters repeated 2^(8-bit) times +// - values[128 ..] are INVALID +// - values[0 .. 128] are either INVALID, IGNORE, PADDING, or < 2^bit +// - padding is either < 128 or INVALID +// - values[padding] is PADDING if padding < 128 +// - values and symbols are inverse +// - ctb is true if 8 % bit == 0 +// - width is present if there is x such that values[x] is IGNORE +// - width % dec(bit) == 0 +// - for all x in separator values[x] is IGNORE +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Encoding(pub InternalEncoding); + +/// How to translate characters when decoding +/// +/// The order matters. The first character of the `from` field is translated to the first character +/// of the `to` field. The second to the second. Etc. +/// +/// See [Specification](struct.Specification.html) for more information. +/// +/// # Features +/// +/// Requires the `alloc` feature. +#[derive(Debug, Clone)] +#[cfg(feature = "alloc")] +pub struct Translate { + /// Characters to translate from + pub from: String, + + /// Characters to translate to + pub to: String, +} + +/// How to wrap the output when encoding +/// +/// See [Specification](struct.Specification.html) for more information. +/// +/// # Features +/// +/// Requires the `alloc` feature. +#[derive(Debug, Clone)] +#[cfg(feature = "alloc")] +pub struct Wrap { + /// Wrapping width + /// + /// Must be a multiple of: + /// + /// - 8 for a bit-width of 1 (binary), 3 (octal), and 5 (base32) + /// - 4 for a bit-width of 2 (base4) and 6 (base64) + /// - 2 for a bit-width of 4 (hexadecimal) + /// + /// Wrapping is disabled if null. + pub width: usize, + + /// Wrapping characters + /// + /// Wrapping is disabled if empty. + pub separator: String, +} + +/// Base-conversion specification +/// +/// It is possible to define custom encodings given a specification. To do so, it is important to +/// understand the theory first. +/// +/// # Theory +/// +/// Each subsection has an equivalent subsection in the [Practice](#practice) section. +/// +/// ## Basics +/// +/// The main idea of a [base-conversion] encoding is to see `[u8]` as numbers written in +/// little-endian base256 and convert them in another little-endian base. For performance reasons, +/// this crate restricts this other base to be of size 2 (binary), 4 (base4), 8 (octal), 16 +/// (hexadecimal), 32 (base32), or 64 (base64). The converted number is written as `[u8]` although +/// it doesn't use all the 256 possible values of `u8`. This crate encodes to ASCII, so only values +/// smaller than 128 are allowed. +/// +/// More precisely, we need the following elements: +/// +/// - The bit-width N: 1 for binary, 2 for base4, 3 for octal, 4 for hexadecimal, 5 for base32, and +/// 6 for base64 +/// - The [bit-order](enum.BitOrder.html): most or least significant bit first +/// - The symbols function S from [0, 2<sup>N</sup>) (called values and written `uN`) to symbols +/// (represented as `u8` although only ASCII symbols are allowed, i.e. smaller than 128) +/// - The values partial function V from ASCII to [0, 2<sup>N</sup>), i.e. from `u8` to `uN` +/// - Whether trailing bits are checked: trailing bits are leading zeros in theory, but since +/// numbers are little-endian they come last +/// +/// For the encoding to be correct (i.e. encoding then decoding gives back the initial input), +/// V(S(i)) must be defined and equal to i for all i in [0, 2<sup>N</sup>). For the encoding to be +/// [canonical][canonical] (i.e. different inputs decode to different outputs, or equivalently, +/// decoding then encoding gives back the initial input), trailing bits must be checked and if V(i) +/// is defined then S(V(i)) is equal to i for all i. +/// +/// Encoding and decoding are given by the following pipeline: +/// +/// ```text +/// [u8] <--1--> [[bit; 8]] <--2--> [[bit; N]] <--3--> [uN] <--4--> [u8] +/// 1: Map bit-order between each u8 and [bit; 8] +/// 2: Base conversion between base 2^8 and base 2^N (check trailing bits) +/// 3: Map bit-order between each [bit; N] and uN +/// 4: Map symbols/values between each uN and u8 (values must be defined) +/// ``` +/// +/// ## Extensions +/// +/// All these extensions make the encoding not canonical. +/// +/// ### Padding +/// +/// Padding is useful if the following conditions are met: +/// +/// - the bit-width is 3 (octal), 5 (base32), or 6 (base64) +/// - the length of the data to encode is not known in advance +/// - the data must be sent without buffering +/// +/// Bases for which the bit-width N does not divide 8 may not concatenate encoded data. This comes +/// from the fact that it is not possible to make the difference between trailing bits and encoding +/// bits. Padding solves this issue by adding a new character to discriminate between trailing bits +/// and encoding bits. The idea is to work by blocks of lcm(8, N) bits, where lcm(8, N) is the least +/// common multiple of 8 and N. When such block is not complete, it is padded. +/// +/// To preserve correctness, the padding character must not be a symbol. +/// +/// ### Ignore characters when decoding +/// +/// Ignoring characters when decoding is useful if after encoding some characters are added for +/// convenience or any other reason (like wrapping). In that case we want to first ignore thoses +/// characters before decoding. +/// +/// To preserve correctness, ignored characters must not contain symbols or the padding character. +/// +/// ### Wrap output when encoding +/// +/// Wrapping output when encoding is useful if the output is meant to be printed in a document where +/// width is limited (typically 80-columns documents). In that case, the wrapping width and the +/// wrapping separator have to be defined. +/// +/// To preserve correctness, the wrapping separator characters must be ignored (see previous +/// subsection). As such, wrapping separator characters must also not contain symbols or the padding +/// character. +/// +/// ### Translate characters when decoding +/// +/// Translating characters when decoding is useful when encoded data may be copied by a humain +/// instead of a machine. Humans tend to confuse some characters for others. In that case we want to +/// translate those characters before decoding. +/// +/// To preserve correctness, the characters we translate _from_ must not contain symbols or the +/// padding character, and the characters we translate _to_ must only contain symbols or the padding +/// character. +/// +/// # Practice +/// +/// ## Basics +/// +/// ```rust +/// use data_encoding::{Encoding, Specification}; +/// fn make_encoding(symbols: &str) -> Encoding { +/// let mut spec = Specification::new(); +/// spec.symbols.push_str(symbols); +/// spec.encoding().unwrap() +/// } +/// let binary = make_encoding("01"); +/// let octal = make_encoding("01234567"); +/// let hexadecimal = make_encoding("0123456789abcdef"); +/// assert_eq!(binary.encode(b"Bit"), "010000100110100101110100"); +/// assert_eq!(octal.encode(b"Bit"), "20464564"); +/// assert_eq!(hexadecimal.encode(b"Bit"), "426974"); +/// ``` +/// +/// The `binary` base has 2 symbols `0` and `1` with value 0 and 1 respectively. The `octal` base +/// has 8 symbols `0` to `7` with value 0 to 7. The `hexadecimal` base has 16 symbols `0` to `9` and +/// `a` to `f` with value 0 to 15. The following diagram gives the idea of how encoding works in the +/// previous example (note that we can actually write such diagram only because the bit-order is +/// most significant first): +/// +/// ```text +/// [ octal] | 2 : 0 : 4 : 6 : 4 : 5 : 6 : 4 | +/// [ binary] |0 1 0 0 0 0 1 0|0 1 1 0 1 0 0 1|0 1 1 1 0 1 0 0| +/// [hexadecimal] | 4 : 2 | 6 : 9 | 7 : 4 | +/// ^-- LSB ^-- MSB +/// ``` +/// +/// Note that in theory, these little-endian numbers are read from right to left (the most +/// significant bit is at the right). Since leading zeros are meaningless (in our usual decimal +/// notation 0123 is the same as 123), it explains why trailing bits must be zero. Trailing bits may +/// occur when the bit-width of a base does not divide 8. Only binary, base4, and hexadecimal don't +/// have trailing bits issues. So let's consider octal and base64, which have trailing bits in +/// similar circumstances: +/// +/// ```rust +/// use data_encoding::{Specification, BASE64_NOPAD}; +/// let octal = { +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("01234567"); +/// spec.encoding().unwrap() +/// }; +/// assert_eq!(BASE64_NOPAD.encode(b"B"), "Qg"); +/// assert_eq!(octal.encode(b"B"), "204"); +/// ``` +/// +/// We have the following diagram, where the base64 values are written between parentheses: +/// +/// ```text +/// [base64] | Q(16) : g(32) : [has 4 zero trailing bits] +/// [ octal] | 2 : 0 : 4 : [has 1 zero trailing bit ] +/// |0 1 0 0 0 0 1 0|0 0 0 0 +/// [ ascii] | B | +/// ^-^-^-^-- leading zeros / trailing bits +/// ``` +/// +/// ## Extensions +/// +/// ### Padding +/// +/// For octal and base64, lcm(8, 3) == lcm(8, 6) == 24 bits or 3 bytes. For base32, lcm(8, 5) is 40 +/// bits or 5 bytes. Let's consider octal and base64: +/// +/// ```rust +/// use data_encoding::{Specification, BASE64}; +/// let octal = { +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("01234567"); +/// spec.padding = Some('='); +/// spec.encoding().unwrap() +/// }; +/// // We start encoding but we only have "B" for now. +/// assert_eq!(BASE64.encode(b"B"), "Qg=="); +/// assert_eq!(octal.encode(b"B"), "204====="); +/// // Now we have "it". +/// assert_eq!(BASE64.encode(b"it"), "aXQ="); +/// assert_eq!(octal.encode(b"it"), "322720=="); +/// // By concatenating everything, we may decode the original data. +/// assert_eq!(BASE64.decode(b"Qg==aXQ=").unwrap(), b"Bit"); +/// assert_eq!(octal.decode(b"204=====322720==").unwrap(), b"Bit"); +/// ``` +/// +/// We have the following diagrams: +/// +/// ```text +/// [base64] | Q(16) : g(32) : = : = | +/// [ octal] | 2 : 0 : 4 : = : = : = : = : = | +/// |0 1 0 0 0 0 1 0|. . . . . . . .|. . . . . . . .| +/// [ ascii] | B | end of block aligned --^ +/// ^-- beginning of block aligned +/// +/// [base64] | a(26) : X(23) : Q(16) : = | +/// [ octal] | 3 : 2 : 2 : 7 : 2 : 0 : = : = | +/// |0 1 1 0 1 0 0 1|0 1 1 1 0 1 0 0|. . . . . . . .| +/// [ ascii] | i | t | +/// ``` +/// +/// ### Ignore characters when decoding +/// +/// The typical use-case is to ignore newlines (`\r` and `\n`). But to keep the example small, we +/// will ignore spaces. +/// +/// ```rust +/// let mut spec = data_encoding::HEXLOWER.specification(); +/// spec.ignore.push_str(" \t"); +/// let base = spec.encoding().unwrap(); +/// assert_eq!(base.decode(b"42 69 74"), base.decode(b"426974")); +/// ``` +/// +/// ### Wrap output when encoding +/// +/// The typical use-case is to wrap after 64 or 76 characters with a newline (`\r\n` or `\n`). But +/// to keep the example small, we will wrap after 8 characters with a space. +/// +/// ```rust +/// let mut spec = data_encoding::BASE64.specification(); +/// spec.wrap.width = 8; +/// spec.wrap.separator.push_str(" "); +/// let base64 = spec.encoding().unwrap(); +/// assert_eq!(base64.encode(b"Hey you"), "SGV5IHlv dQ== "); +/// ``` +/// +/// Note that the output always ends with the separator. +/// +/// ### Translate characters when decoding +/// +/// The typical use-case is to translate lowercase to uppercase or reciprocally, but it is also used +/// for letters that look alike, like `O0` or `Il1`. Let's illustrate both examples. +/// +/// ```rust +/// let mut spec = data_encoding::HEXLOWER.specification(); +/// spec.translate.from.push_str("ABCDEFOIl"); +/// spec.translate.to.push_str("abcdef011"); +/// let base = spec.encoding().unwrap(); +/// assert_eq!(base.decode(b"BOIl"), base.decode(b"b011")); +/// ``` +/// +/// # Features +/// +/// Requires the `alloc` feature. +/// +/// [base-conversion]: https://en.wikipedia.org/wiki/Positional_notation#Base_conversion +/// [canonical]: https://tools.ietf.org/html/rfc4648#section-3.5 +#[derive(Debug, Clone)] +#[cfg(feature = "alloc")] +pub struct Specification { + /// Symbols + /// + /// The number of symbols must be 2, 4, 8, 16, 32, or 64. Symbols must be ASCII characters + /// (smaller than 128) and they must be unique. + pub symbols: String, + + /// Bit-order + /// + /// The default is to use most significant bit first since it is the most common. + pub bit_order: BitOrder, + + /// Check trailing bits + /// + /// The default is to check trailing bits. This field is ignored when unnecessary (i.e. for + /// base2, base4, and base16). + pub check_trailing_bits: bool, + + /// Padding + /// + /// The default is to not use padding. The padding character must be ASCII and must not be a + /// symbol. + pub padding: Option<char>, + + /// Characters to ignore when decoding + /// + /// The default is to not ignore characters when decoding. The characters to ignore must be + /// ASCII and must not be symbols or the padding character. + pub ignore: String, + + /// How to wrap the output when encoding + /// + /// The default is to not wrap the output when encoding. The wrapping characters must be ASCII + /// and must not be symbols or the padding character. + pub wrap: Wrap, + + /// How to translate characters when decoding + /// + /// The default is to not translate characters when decoding. The characters to translate from + /// must be ASCII and must not have already been assigned a semantics. The characters to + /// translate to must be ASCII and must have been assigned a semantics (symbol, padding + /// character, or ignored character). + pub translate: Translate, +} + +#[cfg(feature = "alloc")] +impl Default for Specification { + fn default() -> Self { + Self::new() + } +} + +impl Encoding { + fn sym(&self) -> &[u8; 256] { + unsafe { as_array(&self.0[0 .. 256]) } + } + + fn val(&self) -> &[u8; 256] { + unsafe { as_array(&self.0[256 .. 512]) } + } + + fn pad(&self) -> Option<u8> { + if self.0[512] < 128 { + Some(self.0[512]) + } else { + None + } + } + + fn ctb(&self) -> bool { + self.0[513] & 0x10 != 0 + } + + fn msb(&self) -> bool { + self.0[513] & 0x8 != 0 + } + + fn bit(&self) -> usize { + (self.0[513] & 0x7) as usize + } + + fn wrap(&self) -> Option<(usize, &[u8])> { + if self.0.len() <= 515 { + return None; + } + Some((self.0[514] as usize, &self.0[515 ..])) + } + + fn has_ignore(&self) -> bool { + self.0.len() >= 515 + } + + /// Returns the encoded length of an input of length `len` + /// + /// See [`encode_mut`] for when to use it. + /// + /// [`encode_mut`]: struct.Encoding.html#method.encode_mut + pub fn encode_len(&self, len: usize) -> usize { + dispatch! { + let bit: usize = self.bit(); + let pad: Option<u8> = self.pad(); + let wrap: Option<(usize, &[u8])> = self.wrap(); + encode_wrap_len(bit, pad, wrap, len) + } + } + + /// Encodes `input` in `output` + /// + /// # Panics + /// + /// Panics if the `output` length does not match the result of [`encode_len`] for the `input` + /// length. + /// + /// # Examples + /// + /// ```rust + /// use data_encoding::BASE64; + /// # let mut buffer = vec![0; 100]; + /// let input = b"Hello world"; + /// let output = &mut buffer[0 .. BASE64.encode_len(input.len())]; + /// BASE64.encode_mut(input, output); + /// assert_eq!(output, b"SGVsbG8gd29ybGQ="); + /// ``` + /// + /// [`encode_len`]: struct.Encoding.html#method.encode_len + #[allow(clippy::cognitive_complexity)] + pub fn encode_mut(&self, input: &[u8], output: &mut [u8]) { + assert_eq!(output.len(), self.encode_len(input.len())); + dispatch! { + let bit: usize = self.bit(); + let msb: bool = self.msb(); + let pad: Option<u8> = self.pad(); + let wrap: Option<(usize, &[u8])> = self.wrap(); + encode_wrap_mut(bit, msb, self.sym(), pad, wrap, input, output) + } + } + + /// Appends the encoding of `input` to `output` + /// + /// # Examples + /// + /// ```rust + /// use data_encoding::BASE64; + /// # let mut buffer = vec![0; 100]; + /// let input = b"Hello world"; + /// let mut output = "Result: ".to_string(); + /// BASE64.encode_append(input, &mut output); + /// assert_eq!(output, "Result: SGVsbG8gd29ybGQ="); + /// ``` + /// + /// # Features + /// + /// Requires the `alloc` feature. + #[cfg(feature = "alloc")] + pub fn encode_append(&self, input: &[u8], output: &mut String) { + let output = unsafe { output.as_mut_vec() }; + let output_len = output.len(); + output.resize(output_len + self.encode_len(input.len()), 0u8); + self.encode_mut(input, &mut output[output_len ..]); + } + + /// Returns encoded `input` + /// + /// # Examples + /// + /// ```rust + /// use data_encoding::BASE64; + /// assert_eq!(BASE64.encode(b"Hello world"), "SGVsbG8gd29ybGQ="); + /// ``` + /// + /// # Features + /// + /// Requires the `alloc` feature. + #[cfg(feature = "alloc")] + pub fn encode(&self, input: &[u8]) -> String { + let mut output = vec![0u8; self.encode_len(input.len())]; + self.encode_mut(input, &mut output); + unsafe { String::from_utf8_unchecked(output) } + } + + /// Returns the decoded length of an input of length `len` + /// + /// See [`decode_mut`] for when to use it. + /// + /// # Errors + /// + /// Returns an error if `len` is invalid. The error kind is [`Length`] and the [position] is the + /// greatest valid input length. + /// + /// [`decode_mut`]: struct.Encoding.html#method.decode_mut + /// [`Length`]: enum.DecodeKind.html#variant.Length + /// [position]: struct.DecodeError.html#structfield.position + pub fn decode_len(&self, len: usize) -> Result<usize, DecodeError> { + let (ilen, olen) = dispatch! { + let bit: usize = self.bit(); + let pad: bool = self.pad().is_some(); + decode_wrap_len(bit, pad, len) + }; + check!( + DecodeError { position: ilen, kind: DecodeKind::Length }, + self.has_ignore() || len == ilen + ); + Ok(olen) + } + + /// Decodes `input` in `output` + /// + /// Returns the length of the decoded output. This length may be smaller than the output length + /// if the input contained padding or ignored characters. The output bytes after the returned + /// length are not initialized and should not be read. + /// + /// # Panics + /// + /// Panics if the `output` length does not match the result of [`decode_len`] for the `input` + /// length. Also panics if `decode_len` fails for the `input` length. + /// + /// # Errors + /// + /// Returns an error if `input` is invalid. See [`decode`] for more details. The are two + /// differences though: + /// + /// - [`Length`] may be returned only if the encoding allows ignored characters, because + /// otherwise this is already checked by [`decode_len`]. + /// - The [`read`] first bytes of the input have been successfully decoded to the [`written`] + /// first bytes of the output. + /// + /// # Examples + /// + /// ```rust + /// use data_encoding::BASE64; + /// # let mut buffer = vec![0; 100]; + /// let input = b"SGVsbA==byB3b3JsZA=="; + /// let output = &mut buffer[0 .. BASE64.decode_len(input.len()).unwrap()]; + /// let len = BASE64.decode_mut(input, output).unwrap(); + /// assert_eq!(&output[0 .. len], b"Hello world"); + /// ``` + /// + /// [`decode_len`]: struct.Encoding.html#method.decode_len + /// [`decode`]: struct.Encoding.html#method.decode + /// [`Length`]: enum.DecodeKind.html#variant.Length + /// [`read`]: struct.DecodePartial.html#structfield.read + /// [`written`]: struct.DecodePartial.html#structfield.written + #[allow(clippy::cognitive_complexity)] + pub fn decode_mut(&self, input: &[u8], output: &mut [u8]) -> Result<usize, DecodePartial> { + assert_eq!(Ok(output.len()), self.decode_len(input.len())); + dispatch! { + let bit: usize = self.bit(); + let msb: bool = self.msb(); + let pad: bool = self.pad().is_some(); + let has_ignore: bool = self.has_ignore(); + decode_wrap_mut(bit, msb, self.ctb(), self.val(), pad, has_ignore, + input, output) + } + } + + /// Returns decoded `input` + /// + /// # Errors + /// + /// Returns an error if `input` is invalid. The error kind can be: + /// + /// - [`Length`] if the input length is invalid. The [position] is the greatest valid input + /// length. + /// - [`Symbol`] if the input contains an invalid character. The [position] is the first invalid + /// character. + /// - [`Trailing`] if the input has non-zero trailing bits. This is only possible if the + /// encoding checks trailing bits. The [position] is the first character containing non-zero + /// trailing bits. + /// - [`Padding`] if the input has an invalid padding length. This is only possible if the + /// encoding uses padding. The [position] is the first padding character of the first padding + /// of invalid length. + /// + /// # Examples + /// + /// ```rust + /// use data_encoding::BASE64; + /// assert_eq!(BASE64.decode(b"SGVsbA==byB3b3JsZA==").unwrap(), b"Hello world"); + /// ``` + /// + /// # Features + /// + /// Requires the `alloc` feature. + /// + /// [`Length`]: enum.DecodeKind.html#variant.Length + /// [`Symbol`]: enum.DecodeKind.html#variant.Symbol + /// [`Trailing`]: enum.DecodeKind.html#variant.Trailing + /// [`Padding`]: enum.DecodeKind.html#variant.Padding + /// [position]: struct.DecodeError.html#structfield.position + #[cfg(feature = "alloc")] + pub fn decode(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError> { + let mut output = vec![0u8; self.decode_len(input.len())?]; + let len = self.decode_mut(input, &mut output).map_err(|partial| partial.error)?; + output.truncate(len); + Ok(output) + } + + /// Returns the bit-width + pub fn bit_width(&self) -> usize { + self.bit() + } + + /// Returns whether the encoding is canonical + /// + /// An encoding is not canonical if one of the following conditions holds: + /// + /// - trailing bits are not checked + /// - padding is used + /// - characters are ignored + /// - characters are translated + pub fn is_canonical(&self) -> bool { + if !self.ctb() { + return false; + } + let bit = self.bit(); + let sym = self.sym(); + let val = self.val(); + for i in 0 .. 256 { + if val[i] == INVALID { + continue; + } + if val[i] >= 1 << bit { + return false; + } + if sym[val[i] as usize] != i as u8 { + return false; + } + } + true + } + + /// Returns the encoding specification + /// + /// # Features + /// + /// Requires the `alloc` feature. + #[cfg(feature = "alloc")] + pub fn specification(&self) -> Specification { + let mut specification = Specification::new(); + specification + .symbols + .push_str(core::str::from_utf8(&self.sym()[0 .. 1 << self.bit()]).unwrap()); + specification.bit_order = + if self.msb() { MostSignificantFirst } else { LeastSignificantFirst }; + specification.check_trailing_bits = self.ctb(); + if let Some(pad) = self.pad() { + specification.padding = Some(pad as char); + } + for i in 0 .. 128u8 { + if self.val()[i as usize] != IGNORE { + continue; + } + specification.ignore.push(i as char); + } + if let Some((col, end)) = self.wrap() { + specification.wrap.width = col; + specification.wrap.separator = core::str::from_utf8(end).unwrap().to_owned(); + } + for i in 0 .. 128u8 { + let canonical = if self.val()[i as usize] < 1 << self.bit() { + self.sym()[self.val()[i as usize] as usize] + } else if self.val()[i as usize] == PADDING { + self.pad().unwrap() + } else { + continue; + }; + if i == canonical { + continue; + } + specification.translate.from.push(i as char); + specification.translate.to.push(canonical as char); + } + specification + } + + #[doc(hidden)] + pub const fn internal_new(implementation: &'static [u8]) -> Encoding { + #[cfg(feature = "alloc")] + let encoding = Encoding(Cow::Borrowed(implementation)); + #[cfg(not(feature = "alloc"))] + let encoding = Encoding(implementation); + encoding + } + + #[doc(hidden)] + pub fn internal_implementation(&self) -> &[u8] { + &self.0 + } +} + +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "alloc")] +enum SpecificationErrorImpl { + BadSize, + NotAscii, + Duplicate(u8), + ExtraPadding, + WrapLength, + WrapWidth(u8), + FromTo, + Undefined(u8), +} +#[cfg(feature = "alloc")] +use crate::SpecificationErrorImpl::*; + +/// Specification error +/// +/// # Features +/// +/// Requires the `alloc` feature. +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "alloc")] +pub struct SpecificationError(SpecificationErrorImpl); + +#[cfg(feature = "alloc")] +impl core::fmt::Display for SpecificationError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + match self.0 { + BadSize => write!(f, "invalid number of symbols"), + NotAscii => write!(f, "non-ascii character"), + Duplicate(c) => write!(f, "{:?} has conflicting definitions", c as char), + ExtraPadding => write!(f, "unnecessary padding"), + WrapLength => write!(f, "invalid wrap width or separator length"), + WrapWidth(x) => write!(f, "wrap width not a multiple of {}", x), + FromTo => write!(f, "translate from/to length mismatch"), + Undefined(c) => write!(f, "{:?} is undefined", c as char), + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SpecificationError { + fn description(&self) -> &str { + match self.0 { + BadSize => "invalid number of symbols", + NotAscii => "non-ascii character", + Duplicate(_) => "conflicting definitions", + ExtraPadding => "unnecessary padding", + WrapLength => "invalid wrap width or separator length", + WrapWidth(_) => "wrap width not a multiple", + FromTo => "translate from/to length mismatch", + Undefined(_) => "undefined character", + } + } +} + +#[cfg(feature = "alloc")] +impl Specification { + /// Returns a default specification + pub fn new() -> Specification { + Specification { + symbols: String::new(), + bit_order: MostSignificantFirst, + check_trailing_bits: true, + padding: None, + ignore: String::new(), + wrap: Wrap { width: 0, separator: String::new() }, + translate: Translate { from: String::new(), to: String::new() }, + } + } + + /// Returns the specified encoding + /// + /// # Errors + /// + /// Returns an error if the specification is invalid. + pub fn encoding(&self) -> Result<Encoding, SpecificationError> { + let symbols = self.symbols.as_bytes(); + let bit: usize = match symbols.len() { + 2 => 1, + 4 => 2, + 8 => 3, + 16 => 4, + 32 => 5, + 64 => 6, + _ => return Err(SpecificationError(BadSize)), + }; + let mut values = [INVALID; 128]; + let set = |v: &mut [u8; 128], i: u8, x: u8| { + check!(SpecificationError(NotAscii), i < 128); + if v[i as usize] == x { + return Ok(()); + } + check!(SpecificationError(Duplicate(i)), v[i as usize] == INVALID); + v[i as usize] = x; + Ok(()) + }; + for (v, symbols) in symbols.iter().enumerate() { + set(&mut values, *symbols, v as u8)?; + } + let msb = self.bit_order == MostSignificantFirst; + let ctb = self.check_trailing_bits || 8 % bit == 0; + let pad = match self.padding { + None => None, + Some(pad) => { + check!(SpecificationError(ExtraPadding), 8 % bit != 0); + check!(SpecificationError(NotAscii), pad.len_utf8() == 1); + set(&mut values, pad as u8, PADDING)?; + Some(pad as u8) + } + }; + for i in self.ignore.bytes() { + set(&mut values, i, IGNORE)?; + } + let wrap = if self.wrap.separator.is_empty() || self.wrap.width == 0 { + None + } else { + Some((self.wrap.width, self.wrap.separator.as_bytes())) + }; + if let Some((col, end)) = wrap { + check!(SpecificationError(WrapLength), col < 256 && end.len() < 256); + check!(SpecificationError(WrapWidth(dec(bit) as u8)), col % dec(bit) == 0); + for i in end.iter() { + set(&mut values, *i, IGNORE)?; + } + } + let from = self.translate.from.as_bytes(); + let to = self.translate.to.as_bytes(); + check!(SpecificationError(FromTo), from.len() == to.len()); + for i in 0 .. from.len() { + check!(SpecificationError(NotAscii), to[i] < 128); + let v = values[to[i] as usize]; + check!(SpecificationError(Undefined(to[i])), v != INVALID); + set(&mut values, from[i], v)?; + } + let mut encoding = Vec::new(); + for _ in 0 .. 256 / symbols.len() { + encoding.extend_from_slice(symbols); + } + encoding.extend_from_slice(&values); + encoding.extend_from_slice(&[INVALID; 128]); + match pad { + None => encoding.push(INVALID), + Some(pad) => encoding.push(pad), + } + encoding.push(bit as u8); + if msb { + encoding[513] |= 0x08; + } + if ctb { + encoding[513] |= 0x10; + } + if let Some((col, end)) = wrap { + encoding.push(col as u8); + encoding.extend_from_slice(end); + } else if values.contains(&IGNORE) { + encoding.push(0); + } + Ok(Encoding(Cow::Owned(encoding))) + } +} + +/// Lowercase hexadecimal encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, HEXLOWER}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789abcdef"); +/// assert_eq!(HEXLOWER, spec.encoding().unwrap()); +/// ``` +/// +/// # Examples +/// +/// ```rust +/// use data_encoding::HEXLOWER; +/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; +/// assert_eq!(HEXLOWER.decode(b"deadbeef").unwrap(), deadbeef); +/// assert_eq!(HEXLOWER.encode(&deadbeef), "deadbeef"); +/// ``` +pub const HEXLOWER: Encoding = Encoding::internal_new(HEXLOWER_IMPL); +const HEXLOWER_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, + 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, + 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, + 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, + 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 97, 98, 99, 100, 101, 102, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, +]; + +/// Lowercase hexadecimal encoding with case-insensitive decoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, HEXLOWER_PERMISSIVE}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789abcdef"); +/// spec.translate.from.push_str("ABCDEF"); +/// spec.translate.to.push_str("abcdef"); +/// assert_eq!(HEXLOWER_PERMISSIVE, spec.encoding().unwrap()); +/// ``` +/// +/// # Examples +/// +/// ```rust +/// use data_encoding::HEXLOWER_PERMISSIVE; +/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; +/// assert_eq!(HEXLOWER_PERMISSIVE.decode(b"DeadBeef").unwrap(), deadbeef); +/// assert_eq!(HEXLOWER_PERMISSIVE.encode(&deadbeef), "deadbeef"); +/// ``` +/// +/// You can also define a shorter name: +/// +/// ```rust +/// use data_encoding::{Encoding, HEXLOWER_PERMISSIVE}; +/// const HEX: Encoding = HEXLOWER_PERMISSIVE; +/// ``` +pub const HEXLOWER_PERMISSIVE: Encoding = Encoding::internal_new(HEXLOWER_PERMISSIVE_IMPL); +const HEXLOWER_PERMISSIVE_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, + 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, + 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, + 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, + 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 97, 98, 99, 100, 101, 102, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, +]; + +/// Uppercase hexadecimal encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, HEXUPPER}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789ABCDEF"); +/// assert_eq!(HEXUPPER, spec.encoding().unwrap()); +/// ``` +/// +/// It is compliant with [RFC4648] and known as "base16" or "hex". +/// +/// # Examples +/// +/// ```rust +/// use data_encoding::HEXUPPER; +/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; +/// assert_eq!(HEXUPPER.decode(b"DEADBEEF").unwrap(), deadbeef); +/// assert_eq!(HEXUPPER.encode(&deadbeef), "DEADBEEF"); +/// ``` +/// +/// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-8 +pub const HEXUPPER: Encoding = Encoding::internal_new(HEXUPPER_IMPL); +const HEXUPPER_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, + 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, +]; + +/// Uppercase hexadecimal encoding with case-insensitive decoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, HEXUPPER_PERMISSIVE}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789ABCDEF"); +/// spec.translate.from.push_str("abcdef"); +/// spec.translate.to.push_str("ABCDEF"); +/// assert_eq!(HEXUPPER_PERMISSIVE, spec.encoding().unwrap()); +/// ``` +/// +/// # Examples +/// +/// ```rust +/// use data_encoding::HEXUPPER_PERMISSIVE; +/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; +/// assert_eq!(HEXUPPER_PERMISSIVE.decode(b"DeadBeef").unwrap(), deadbeef); +/// assert_eq!(HEXUPPER_PERMISSIVE.encode(&deadbeef), "DEADBEEF"); +/// ``` +pub const HEXUPPER_PERMISSIVE: Encoding = Encoding::internal_new(HEXUPPER_PERMISSIVE_IMPL); +const HEXUPPER_PERMISSIVE_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, + 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, +]; + +/// Padded base32 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE32}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); +/// spec.padding = Some('='); +/// assert_eq!(BASE32, spec.encoding().unwrap()); +/// ``` +/// +/// It is conform to [RFC4648]. +/// +/// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-6 +pub const BASE32: Encoding = Encoding::internal_new(BASE32_IMPL); +const BASE32_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 130, 128, 128, + 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 29, +]; + +/// Unpadded base32 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE32_NOPAD}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); +/// assert_eq!(BASE32_NOPAD, spec.encoding().unwrap()); +/// ``` +pub const BASE32_NOPAD: Encoding = Encoding::internal_new(BASE32_NOPAD_IMPL); +const BASE32_NOPAD_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 29, +]; + +/// Padded base32hex encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE32HEX}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789ABCDEFGHIJKLMNOPQRSTUV"); +/// spec.padding = Some('='); +/// assert_eq!(BASE32HEX, spec.encoding().unwrap()); +/// ``` +/// +/// It is conform to [RFC4648]. +/// +/// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-7 +pub const BASE32HEX: Encoding = Encoding::internal_new(BASE32HEX_IMPL); +const BASE32HEX_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 130, 128, 128, 128, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 29, +]; + +/// Unpadded base32hex encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE32HEX_NOPAD}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789ABCDEFGHIJKLMNOPQRSTUV"); +/// assert_eq!(BASE32HEX_NOPAD, spec.encoding().unwrap()); +/// ``` +pub const BASE32HEX_NOPAD: Encoding = Encoding::internal_new(BASE32HEX_NOPAD_IMPL); +const BASE32HEX_NOPAD_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 29, +]; + +/// DNSSEC base32 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE32_DNSSEC}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789abcdefghijklmnopqrstuv"); +/// spec.translate.from.push_str("ABCDEFGHIJKLMNOPQRSTUV"); +/// spec.translate.to.push_str("abcdefghijklmnopqrstuv"); +/// assert_eq!(BASE32_DNSSEC, spec.encoding().unwrap()); +/// ``` +/// +/// It is conform to [RFC5155]: +/// +/// - It uses a base32 extended hex alphabet. +/// - It is case-insensitive when decoding and uses lowercase when encoding. +/// - It does not use padding. +/// +/// [RFC5155]: https://tools.ietf.org/html/rfc5155 +pub const BASE32_DNSSEC: Encoding = Encoding::internal_new(BASE32_DNSSEC_IMPL); +const BASE32_DNSSEC_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 29, +]; + +/// DNSCurve base32 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{BitOrder, Specification, BASE32_DNSCURVE}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("0123456789bcdfghjklmnpqrstuvwxyz"); +/// spec.bit_order = BitOrder::LeastSignificantFirst; +/// spec.translate.from.push_str("BCDFGHJKLMNPQRSTUVWXYZ"); +/// spec.translate.to.push_str("bcdfghjklmnpqrstuvwxyz"); +/// assert_eq!(BASE32_DNSCURVE, spec.encoding().unwrap()); +/// ``` +/// +/// It is conform to [DNSCurve]. +/// +/// [DNSCurve]: https://dnscurve.org/in-implement.html +pub const BASE32_DNSCURVE: Encoding = Encoding::internal_new(BASE32_DNSCURVE_IMPL); +const BASE32_DNSCURVE_IMPL: &[u8] = &[ + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, + 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, + 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, + 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, + 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128, 10, 11, + 12, 128, 13, 14, 15, 128, 16, 17, 18, 19, 20, 128, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 128, 13, 14, 15, 128, 16, 17, 18, 19, 20, 128, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 21, +]; + +/// Padded base64 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE64}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); +/// spec.padding = Some('='); +/// assert_eq!(BASE64, spec.encoding().unwrap()); +/// ``` +/// +/// It is conform to [RFC4648]. +/// +/// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-4 +pub const BASE64: Encoding = Encoding::internal_new(BASE64_IMPL); +const BASE64_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 130, 128, + 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 30, +]; + +/// Unpadded base64 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE64_NOPAD}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); +/// assert_eq!(BASE64_NOPAD, spec.encoding().unwrap()); +/// ``` +pub const BASE64_NOPAD: Encoding = Encoding::internal_new(BASE64_NOPAD_IMPL); +const BASE64_NOPAD_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 128, 128, + 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 30, +]; + +/// MIME base64 encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, Wrap, BASE64_MIME}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); +/// spec.padding = Some('='); +/// spec.wrap.width = 76; +/// spec.wrap.separator.push_str("\r\n"); +/// assert_eq!(BASE64_MIME, spec.encoding().unwrap()); +/// ``` +/// +/// It is not exactly conform to [RFC2045] because it does not print the header +/// and does not ignore all characters. +/// +/// [RFC2045]: https://tools.ietf.org/html/rfc2045 +pub const BASE64_MIME: Encoding = Encoding::internal_new(BASE64_MIME_IMPL); +const BASE64_MIME_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 129, 128, 128, 129, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 130, 128, + 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 30, 76, 13, 10, +]; + +/// Padded base64url encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE64URL}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"); +/// spec.padding = Some('='); +/// assert_eq!(BASE64URL, spec.encoding().unwrap()); +/// ``` +/// +/// It is conform to [RFC4648]. +/// +/// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-5 +pub const BASE64URL: Encoding = Encoding::internal_new(BASE64URL_IMPL); +const BASE64URL_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 62, 128, 128, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 130, 128, + 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 128, 128, 128, 128, 63, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 30, +]; + +/// Unpadded base64url encoding +/// +/// This encoding is a static version of: +/// +/// ```rust +/// # use data_encoding::{Specification, BASE64URL_NOPAD}; +/// let mut spec = Specification::new(); +/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"); +/// assert_eq!(BASE64URL_NOPAD, spec.encoding().unwrap()); +/// ``` +pub const BASE64URL_NOPAD: Encoding = Encoding::internal_new(BASE64URL_NOPAD_IMPL); +const BASE64URL_NOPAD_IMPL: &[u8] = &[ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, + 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 62, 128, 128, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 128, 128, + 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 128, 128, 128, 128, 63, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 30, +]; |