//! 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
//! 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 any hidden mutable state
//! - They are correct: encoding followed by decoding gives the initial data
//! - They are canonical (unless [`is_canonical`] returns false): decoding followed by 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. Note that non-canonical encodings may be an attack vector as described
//! in [Base64 Malleability in Practice](https://eprint.iacr.org/2022/361.pdf).
//!
//! 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)`     | `Padding` | Invalid input |
//! | `AAA`      | `Length(0)`     | `Padding` | 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]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
// TODO: This list up to warn(clippy::pedantic) should ideally use a lint group.
#![warn(elided_lifetimes_in_paths)]
// TODO(msrv): #![warn(let_underscore_drop)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(unreachable_pub)]
// TODO(msrv): #![warn(unsafe_op_in_unsafe_fn)]
#![warn(unused_results)]
#![allow(unused_unsafe)] // TODO(msrv)
#![warn(clippy::pedantic)]
#![allow(clippy::enum_glob_use)]
#![allow(clippy::similar_names)]
#![allow(clippy::uninlined_format_args)] // TODO(msrv)

#[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;
use core::convert::TryInto;

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());
    unsafe { core::slice::from_raw_parts(x.as_ptr().add(n * i), n) }
}

unsafe fn chunk_mut_unchecked(x: &mut [u8], n: usize, i: usize) -> &mut [u8] {
    debug_assert!((i + 1) * n <= x.len());
    unsafe { core::slice::from_raw_parts_mut(x.as_mut_ptr().add(n * i), n) }
}

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 & 0xff) as usize];
    }
}

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)) & 0xff) 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");
/// ```
#[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(#[doc(hidden)] 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.
#[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.
#[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"));
/// ```
///
/// [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] {
        self.0[0 .. 256].try_into().unwrap()
    }

    fn val(&self) -> &[u8; 256] {
        self.0[256 .. 512].try_into().unwrap()
    }

    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
    }

    /// Minimum number of input and output blocks when encoding
    fn block_len(&self) -> (usize, usize) {
        let bit = self.bit();
        match self.wrap() {
            Some((col, end)) => (col / dec(bit) * enc(bit), col + end.len()),
            None => (enc(bit), dec(bit)),
        }
    }

    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
    #[must_use]
    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=");
    /// ```
    #[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 an object to encode a fragmented input and append it to `output`
    ///
    /// See the documentation of [`Encoder`] for more details and examples.
    #[cfg(feature = "alloc")]
    pub fn new_encoder<'a>(&'a self, output: &'a mut String) -> Encoder<'a> {
        Encoder::new(self, output)
    }

    /// Writes the encoding of `input` to `output`
    ///
    /// This allocates a buffer of 1024 bytes on the stack. If you want to control the buffer size
    /// and location, use [`Encoding::encode_write_buffer()`] instead.
    ///
    /// # Errors
    ///
    /// Returns an error when writing to the output fails.
    pub fn encode_write(
        &self, input: &[u8], output: &mut impl core::fmt::Write,
    ) -> core::fmt::Result {
        self.encode_write_buffer(input, output, &mut [0; 1024])
    }

    /// Writes the encoding of `input` to `output` using a temporary `buffer`
    ///
    /// # Panics
    ///
    /// Panics if the buffer is shorter than 510 bytes.
    ///
    /// # Errors
    ///
    /// Returns an error when writing to the output fails.
    pub fn encode_write_buffer(
        &self, input: &[u8], output: &mut impl core::fmt::Write, buffer: &mut [u8],
    ) -> core::fmt::Result {
        assert!(510 <= buffer.len());
        let (enc, dec) = self.block_len();
        for input in input.chunks(buffer.len() / dec * enc) {
            let buffer = &mut buffer[.. self.encode_len(input.len())];
            self.encode_mut(input, buffer);
            output.write_str(unsafe { core::str::from_utf8_unchecked(buffer) })?;
        }
        Ok(())
    }

    /// Returns encoded `input`
    ///
    /// # Examples
    ///
    /// ```rust
    /// use data_encoding::BASE64;
    /// assert_eq!(BASE64.encode(b"Hello world"), "SGVsbG8gd29ybGQ=");
    /// ```
    #[cfg(feature = "alloc")]
    #[must_use]
    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");
    /// ```
    ///
    /// [`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
    #[must_use]
    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
    #[must_use]
    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] as usize != i {
                return false;
            }
        }
        true
    }

    /// Returns the encoding specification
    #[allow(clippy::missing_panics_doc)] // no panic
    #[cfg(feature = "alloc")]
    #[must_use]
    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)]
    #[must_use]
    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)]
    #[must_use]
    pub fn internal_implementation(&self) -> &[u8] {
        &self.0
    }
}

/// Encodes fragmented input to an output
///
/// It is equivalent to use an [`Encoder`] with multiple calls to [`Encoder::append()`] than to
/// first concatenate all the input and then use [`Encoding::encode_append()`]. In particular, this
/// function will not introduce padding or wrapping between inputs.
///
/// # Examples
///
/// ```rust
/// // This is a bit inconvenient but we can't take a long-term reference to data_encoding::BASE64
/// // because it's a constant. We need to use a static which has an address instead. This will be
/// // fixed in version 3 of the library.
/// static BASE64: data_encoding::Encoding = data_encoding::BASE64;
/// let mut output = String::new();
/// let mut encoder = BASE64.new_encoder(&mut output);
/// encoder.append(b"hello");
/// encoder.append(b"world");
/// encoder.finalize();
/// assert_eq!(output, BASE64.encode(b"helloworld"));
/// ```
#[derive(Debug)]
#[cfg(feature = "alloc")]
pub struct Encoder<'a> {
    encoding: &'a Encoding,
    output: &'a mut String,
    buffer: [u8; 255],
    length: u8,
}

#[cfg(feature = "alloc")]
impl<'a> Drop for Encoder<'a> {
    fn drop(&mut self) {
        self.encoding.encode_append(&self.buffer[.. self.length as usize], self.output);
    }
}

#[cfg(feature = "alloc")]
impl<'a> Encoder<'a> {
    fn new(encoding: &'a Encoding, output: &'a mut String) -> Self {
        Encoder { encoding, output, buffer: [0; 255], length: 0 }
    }

    /// Encodes the provided input fragment and appends the result to the output
    pub fn append(&mut self, mut input: &[u8]) {
        #[allow(clippy::cast_possible_truncation)] // no truncation
        let max = self.encoding.block_len().0 as u8;
        if self.length != 0 {
            let len = self.length;
            #[allow(clippy::cast_possible_truncation)] // no truncation
            let add = core::cmp::min((max - len) as usize, input.len()) as u8;
            self.buffer[len as usize ..][.. add as usize].copy_from_slice(&input[.. add as usize]);
            self.length += add;
            input = &input[add as usize ..];
            if self.length != max {
                debug_assert!(self.length < max);
                debug_assert!(input.is_empty());
                return;
            }
            self.encoding.encode_append(&self.buffer[.. max as usize], self.output);
            self.length = 0;
        }
        let len = floor(input.len(), max as usize);
        self.encoding.encode_append(&input[.. len], self.output);
        input = &input[len ..];
        #[allow(clippy::cast_possible_truncation)] // no truncation
        let len = input.len() as u8;
        self.buffer[.. len as usize].copy_from_slice(input);
        self.length = len;
    }

    /// Makes sure all inputs have been encoded and appended to the output
    ///
    /// This is equivalent to dropping the encoder and required for correctness, otherwise some
    /// encoded data may be missing at the end.
    pub fn finalize(self) {}
}

#[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
#[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
    #[must_use]
    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: u8 = 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() {
            #[allow(clippy::cast_possible_truncation)] // no truncation
            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 {
            let col = self.wrap.width;
            let end = self.wrap.separator.as_bytes();
            check!(SpecificationError(WrapLength), col < 256 && end.len() < 256);
            #[allow(clippy::cast_possible_truncation)] // no truncation
            let col = col as u8;
            #[allow(clippy::cast_possible_truncation)] // no truncation
            let dec = dec(bit as usize) as u8;
            check!(SpecificationError(WrapWidth(dec)), col % dec == 0);
            for &i in end {
                set(&mut values, i, IGNORE)?;
            }
            Some((col, end))
        };
        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);
        if msb {
            encoding[513] |= 0x08;
        }
        if ctb {
            encoding[513] |= 0x10;
        }
        if let Some((col, end)) = wrap {
            encoding.push(col);
            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 conforms 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 conforms 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 conforms 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,
];

#[allow(clippy::doc_markdown)]
/// 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 conforms 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 conforms 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 does 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 conforms 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,
];
