aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHyun Jae Moon <hyunjaemoon@google.com>2023-06-23 23:19:47 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-06-23 23:19:47 +0000
commitc97ee7e7af2a2dc9f3674af2ff876d3036f32aa0 (patch)
treea6443812f9b77f11bdbaeec3a44dce1837be121f
parentf57b419fd10cb0405be9183517e5fc6e7dce1538 (diff)
parent1d67f174fa398224060acb4c1a8401628730019b (diff)
downloaddata-encoding-c97ee7e7af2a2dc9f3674af2ff876d3036f32aa0.tar.gz
Import data-encoding crate am: a5641d4897 am: 83f6a96af9 am: 97972d1b39 am: 182696fb54 am: 1d67f174fa
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/data-encoding/+/2637330 Change-Id: Icffa39d97a01375c438d1482fbc5b0fa20db6b09 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--Android.bp25
-rw-r--r--Cargo.toml43
-rw-r--r--Cargo.toml.orig19
-rw-r--r--LICENSE22
-rw-r--r--METADATA19
-rw-r--r--MODULE_LICENSE_MIT0
-rw-r--r--OWNERS1
-rw-r--r--README.md34
-rw-r--r--src/lib.rs2391
9 files changed, 2554 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..970e754
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,25 @@
+// This file is generated by cargo2android.py --run --device --tests.
+// Do not modify this file as changes will be overridden on upgrade.
+
+
+
+rust_library {
+ name: "libdata_encoding",
+ host_supported: true,
+ crate_name: "data_encoding",
+ cargo_env_compat: true,
+ cargo_pkg_version: "2.4.0",
+ srcs: ["src/lib.rs"],
+ edition: "2018",
+ features: [
+ "alloc",
+ "default",
+ "std",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ product_available: true,
+ vendor_available: true,
+}
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..e4879f7
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,43 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.47"
+name = "data-encoding"
+version = "2.4.0"
+authors = ["Julien Cretin <git@ia0.eu>"]
+include = [
+ "Cargo.toml",
+ "LICENSE",
+ "README.md",
+ "src/lib.rs",
+]
+description = "Efficient and customizable data-encoding functions like base64, base32, and hex"
+documentation = "https://docs.rs/data-encoding"
+readme = "README.md"
+keywords = [
+ "no_std",
+ "base64",
+ "base32",
+ "hex",
+]
+categories = [
+ "encoding",
+ "no-std",
+]
+license = "MIT"
+repository = "https://github.com/ia0/data-encoding"
+
+[features]
+alloc = []
+default = ["std"]
+std = ["alloc"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
new file mode 100644
index 0000000..d60c6e3
--- /dev/null
+++ b/Cargo.toml.orig
@@ -0,0 +1,19 @@
+[package]
+name = "data-encoding"
+version = "2.4.0"
+authors = ["Julien Cretin <git@ia0.eu>"]
+license = "MIT"
+edition = "2018"
+rust-version = "1.47"
+keywords = ["no_std", "base64", "base32", "hex"]
+categories = ["encoding", "no-std"]
+readme = "README.md"
+repository = "https://github.com/ia0/data-encoding"
+documentation = "https://docs.rs/data-encoding"
+description = "Efficient and customizable data-encoding functions like base64, base32, and hex"
+include = ["Cargo.toml", "LICENSE", "README.md", "src/lib.rs"]
+
+[features]
+default = ["std"]
+alloc = []
+std = ["alloc"]
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..9a75083
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015-2020 Julien Cretin
+Copyright (c) 2017-2020 Google Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..c72af71
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,19 @@
+name: "data-encoding"
+description: "Efficient and customizable data-encoding functions like base64, base32, and hex"
+third_party {
+ url {
+ type: HOMEPAGE
+ value: "https://crates.io/crates/data-encoding"
+ }
+ url {
+ type: ARCHIVE
+ value: "https://static.crates.io/crates/data-encoding/data-encoding-2.4.0.crate"
+ }
+ version: "2.4.0"
+ license_type: NOTICE
+ last_upgrade_date {
+ year: 2023
+ month: 6
+ day: 7
+ }
+}
diff --git a/MODULE_LICENSE_MIT b/MODULE_LICENSE_MIT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_MIT
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..45dc4dd
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1 @@
+include platform/prebuilts/rust:master:/OWNERS
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..64d2dec
--- /dev/null
+++ b/README.md
@@ -0,0 +1,34 @@
+[![CI Status][ci_badge]][ci]
+[![Coverage Status][coveralls_badge]][coveralls]
+
+This library provides the following common encodings:
+
+| Name | Description |
+| --- | --- |
+| `HEXLOWER` | lowercase hexadecimal |
+| `HEXLOWER_PERMISSIVE` | lowercase hexadecimal (case-insensitive decoding) |
+| `HEXUPPER` | uppercase hexadecimal |
+| `HEXUPPER_PERMISSIVE` | uppercase hexadecimal (case-insensitive decoding) |
+| `BASE32` | RFC4648 base32 |
+| `BASE32_NOPAD` | RFC4648 base32 (no padding) |
+| `BASE32_DNSSEC` | RFC5155 base32 |
+| `BASE32_DNSCURVE` | DNSCurve base32 |
+| `BASE32HEX` | RFC4648 base32hex |
+| `BASE32HEX_NOPAD` | RFC4648 base32hex (no padding) |
+| `BASE64` | RFC4648 base64 |
+| `BASE64_NOPAD` | RFC4648 base64 (no padding) |
+| `BASE64_MIME` | RFC2045-like base64 |
+| `BASE64URL` | RFC4648 base64url |
+| `BASE64URL_NOPAD` | RFC4648 base64url (no padding) |
+
+It also provides the possibility to define custom little-endian ASCII
+base-conversion encodings for bases of size 2, 4, 8, 16, 32, and 64 (for which
+all above use-cases are particular instances).
+
+See the [documentation] for more details.
+
+[ci]: https://github.com/ia0/data-encoding/actions/workflows/ci.yml
+[ci_badge]: https://github.com/ia0/data-encoding/actions/workflows/ci.yml/badge.svg
+[coveralls]: https://coveralls.io/github/ia0/data-encoding?branch=master
+[coveralls_badge]: https://coveralls.io/repos/github/ia0/data-encoding/badge.svg?branch=master
+[documentation]: https://docs.rs/data-encoding
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..14438ed
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,2391 @@
+//! 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]
+#![warn(unused_results, missing_docs)]
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
+
+#[cfg(feature = "alloc")]
+use alloc::borrow::{Cow, ToOwned};
+#[cfg(feature = "alloc")]
+use alloc::string::String;
+#[cfg(feature = "alloc")]
+use alloc::vec;
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+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());
+ let ptr = x.as_ptr().add(n * i);
+ core::slice::from_raw_parts(ptr, n)
+}
+
+unsafe fn chunk_mut_unchecked(x: &mut [u8], n: usize, i: usize) -> &mut [u8] {
+ debug_assert!((i + 1) * n <= x.len());
+ let ptr = x.as_mut_ptr().add(n * i);
+ core::slice::from_raw_parts_mut(ptr, n)
+}
+
+fn div_ceil(x: usize, m: usize) -> usize {
+ (x + m - 1) / m
+}
+
+fn floor(x: usize, m: usize) -> usize {
+ x / m * m
+}
+
+fn vectorize<F: FnMut(usize)>(n: usize, bs: usize, mut f: F) {
+ for k in 0 .. n / bs {
+ for i in k * bs .. (k + 1) * bs {
+ f(i);
+ }
+ }
+ for i in floor(n, bs) .. n {
+ f(i);
+ }
+}
+
+/// Decoding error kind
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum DecodeKind {
+ /// Invalid length
+ Length,
+
+ /// Invalid symbol
+ Symbol,
+
+ /// Non-zero trailing bits
+ Trailing,
+
+ /// Invalid padding length
+ Padding,
+}
+
+impl core::fmt::Display for DecodeKind {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ let description = match self {
+ DecodeKind::Length => "invalid length",
+ DecodeKind::Symbol => "invalid symbol",
+ DecodeKind::Trailing => "non-zero trailing bits",
+ DecodeKind::Padding => "invalid padding length",
+ };
+ write!(f, "{}", description)
+ }
+}
+
+/// Decoding error
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct DecodeError {
+ /// Error position
+ ///
+ /// This position is always a valid input position and represents the first encountered error.
+ pub position: usize,
+
+ /// Error kind
+ pub kind: DecodeKind,
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for DecodeError {}
+
+impl core::fmt::Display for DecodeError {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ write!(f, "{} at {}", self.kind, self.position)
+ }
+}
+
+/// Decoding error with partial result
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct DecodePartial {
+ /// Number of bytes read from input
+ ///
+ /// This number does not exceed the error position: `read <= error.position`.
+ pub read: usize,
+
+ /// Number of bytes written to output
+ ///
+ /// This number does not exceed the decoded length: `written <= decode_len(read)`.
+ pub written: usize,
+
+ /// Decoding error
+ pub error: DecodeError,
+}
+
+const INVALID: u8 = 128;
+const IGNORE: u8 = 129;
+const PADDING: u8 = 130;
+
+fn order(msb: bool, n: usize, i: usize) -> usize {
+ if msb {
+ n - 1 - i
+ } else {
+ i
+ }
+}
+
+fn enc(bit: usize) -> usize {
+ match bit {
+ 1 | 2 | 4 => 1,
+ 3 | 6 => 3,
+ 5 => 5,
+ _ => unreachable!(),
+ }
+}
+
+fn dec(bit: usize) -> usize {
+ enc(bit) * 8 / bit
+}
+
+fn encode_len<B: Static<usize>>(bit: B, len: usize) -> usize {
+ div_ceil(8 * len, bit.val())
+}
+
+fn encode_block<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8],
+) {
+ debug_assert!(input.len() <= enc(bit.val()));
+ debug_assert_eq!(output.len(), encode_len(bit, input.len()));
+ let bit = bit.val();
+ let msb = msb.val();
+ let mut x = 0u64;
+ for (i, input) in input.iter().enumerate() {
+ x |= u64::from(*input) << (8 * order(msb, enc(bit), i));
+ }
+ for (i, output) in output.iter_mut().enumerate() {
+ let y = x >> (bit * order(msb, dec(bit), i));
+ *output = symbols[y as usize % 256];
+ }
+}
+
+fn encode_mut<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8],
+) {
+ debug_assert_eq!(output.len(), encode_len(bit, input.len()));
+ let enc = enc(bit.val());
+ let dec = dec(bit.val());
+ let n = input.len() / enc;
+ let bs = match bit.val() {
+ 5 => 2,
+ 6 => 4,
+ _ => 1,
+ };
+ vectorize(n, bs, |i| {
+ let input = unsafe { chunk_unchecked(input, enc, i) };
+ let output = unsafe { chunk_mut_unchecked(output, dec, i) };
+ encode_block(bit, msb, symbols, input, output);
+ });
+ encode_block(bit, msb, symbols, &input[enc * n ..], &mut output[dec * n ..]);
+}
+
+// Fails if an input character does not translate to a symbol. The error is the
+// lowest index of such character. The output is not written to.
+fn decode_block<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, values: &[u8; 256], input: &[u8], output: &mut [u8],
+) -> Result<(), usize> {
+ debug_assert!(output.len() <= enc(bit.val()));
+ debug_assert_eq!(input.len(), encode_len(bit, output.len()));
+ let bit = bit.val();
+ let msb = msb.val();
+ let mut x = 0u64;
+ for j in 0 .. input.len() {
+ let y = values[input[j] as usize];
+ check!(j, y < 1 << bit);
+ x |= u64::from(y) << (bit * order(msb, dec(bit), j));
+ }
+ for (j, output) in output.iter_mut().enumerate() {
+ *output = (x >> (8 * order(msb, enc(bit), j))) as u8;
+ }
+ Ok(())
+}
+
+// Fails if an input character does not translate to a symbol. The error `pos`
+// is the lowest index of such character. The output is valid up to `pos / dec *
+// enc` excluded.
+fn decode_mut<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, values: &[u8; 256], input: &[u8], output: &mut [u8],
+) -> Result<(), usize> {
+ debug_assert_eq!(input.len(), encode_len(bit, output.len()));
+ let enc = enc(bit.val());
+ let dec = dec(bit.val());
+ let n = input.len() / dec;
+ for i in 0 .. n {
+ let input = unsafe { chunk_unchecked(input, dec, i) };
+ let output = unsafe { chunk_mut_unchecked(output, enc, i) };
+ decode_block(bit, msb, values, input, output).map_err(|e| dec * i + e)?;
+ }
+ decode_block(bit, msb, values, &input[dec * n ..], &mut output[enc * n ..])
+ .map_err(|e| dec * n + e)
+}
+
+// Fails if there are non-zero trailing bits.
+fn check_trail<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, ctb: bool, values: &[u8; 256], input: &[u8],
+) -> Result<(), ()> {
+ if 8 % bit.val() == 0 || !ctb {
+ return Ok(());
+ }
+ let trail = bit.val() * input.len() % 8;
+ if trail == 0 {
+ return Ok(());
+ }
+ let mut mask = (1 << trail) - 1;
+ if !msb.val() {
+ mask <<= bit.val() - trail;
+ }
+ check!((), values[input[input.len() - 1] as usize] & mask == 0);
+ Ok(())
+}
+
+// Fails if the padding length is invalid. The error is the index of the first
+// padding character.
+fn check_pad<B: Static<usize>>(bit: B, values: &[u8; 256], input: &[u8]) -> Result<usize, usize> {
+ let bit = bit.val();
+ debug_assert_eq!(input.len(), dec(bit));
+ let is_pad = |x: &&u8| values[**x as usize] == PADDING;
+ let count = input.iter().rev().take_while(is_pad).count();
+ let len = input.len() - count;
+ check!(len, len > 0 && bit * len % 8 < bit);
+ Ok(len)
+}
+
+fn encode_base_len<B: Static<usize>>(bit: B, len: usize) -> usize {
+ encode_len(bit, len)
+}
+
+fn encode_base<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8],
+) {
+ debug_assert_eq!(output.len(), encode_base_len(bit, input.len()));
+ encode_mut(bit, msb, symbols, input, output);
+}
+
+fn encode_pad_len<B: Static<usize>, P: Static<Option<u8>>>(bit: B, pad: P, len: usize) -> usize {
+ match pad.val() {
+ None => encode_base_len(bit, len),
+ Some(_) => div_ceil(len, enc(bit.val())) * dec(bit.val()),
+ }
+}
+
+fn encode_pad<B: Static<usize>, M: Static<bool>, P: Static<Option<u8>>>(
+ bit: B, msb: M, symbols: &[u8; 256], spad: P, input: &[u8], output: &mut [u8],
+) {
+ let pad = match spad.val() {
+ None => return encode_base(bit, msb, symbols, input, output),
+ Some(pad) => pad,
+ };
+ debug_assert_eq!(output.len(), encode_pad_len(bit, spad, input.len()));
+ let olen = encode_base_len(bit, input.len());
+ encode_base(bit, msb, symbols, input, &mut output[.. olen]);
+ for output in output.iter_mut().skip(olen) {
+ *output = pad;
+ }
+}
+
+fn encode_wrap_len<
+ 'a,
+ B: Static<usize>,
+ P: Static<Option<u8>>,
+ W: Static<Option<(usize, &'a [u8])>>,
+>(
+ bit: B, pad: P, wrap: W, ilen: usize,
+) -> usize {
+ let olen = encode_pad_len(bit, pad, ilen);
+ match wrap.val() {
+ None => olen,
+ Some((col, end)) => olen + end.len() * div_ceil(olen, col),
+ }
+}
+
+fn encode_wrap_mut<
+ 'a,
+ B: Static<usize>,
+ M: Static<bool>,
+ P: Static<Option<u8>>,
+ W: Static<Option<(usize, &'a [u8])>>,
+>(
+ bit: B, msb: M, symbols: &[u8; 256], pad: P, wrap: W, input: &[u8], output: &mut [u8],
+) {
+ let (col, end) = match wrap.val() {
+ None => return encode_pad(bit, msb, symbols, pad, input, output),
+ Some((col, end)) => (col, end),
+ };
+ debug_assert_eq!(output.len(), encode_wrap_len(bit, pad, wrap, input.len()));
+ debug_assert_eq!(col % dec(bit.val()), 0);
+ let col = col / dec(bit.val());
+ let enc = col * enc(bit.val());
+ let dec = col * dec(bit.val()) + end.len();
+ let olen = dec - end.len();
+ let n = input.len() / enc;
+ for i in 0 .. n {
+ let input = unsafe { chunk_unchecked(input, enc, i) };
+ let output = unsafe { chunk_mut_unchecked(output, dec, i) };
+ encode_base(bit, msb, symbols, input, &mut output[.. olen]);
+ output[olen ..].copy_from_slice(end);
+ }
+ if input.len() > enc * n {
+ let olen = dec * n + encode_pad_len(bit, pad, input.len() - enc * n);
+ encode_pad(bit, msb, symbols, pad, &input[enc * n ..], &mut output[dec * n .. olen]);
+ output[olen ..].copy_from_slice(end);
+ }
+}
+
+// Returns the longest valid input length and associated output length.
+fn decode_wrap_len<B: Static<usize>, P: Static<bool>>(
+ bit: B, pad: P, len: usize,
+) -> (usize, usize) {
+ let bit = bit.val();
+ if pad.val() {
+ (floor(len, dec(bit)), len / dec(bit) * enc(bit))
+ } else {
+ let trail = bit * len % 8;
+ (len - trail / bit, bit * len / 8)
+ }
+}
+
+// Fails with Length if length is invalid. The error is the largest valid
+// length.
+fn decode_pad_len<B: Static<usize>, P: Static<bool>>(
+ bit: B, pad: P, len: usize,
+) -> Result<usize, DecodeError> {
+ let (ilen, olen) = decode_wrap_len(bit, pad, len);
+ check!(DecodeError { position: ilen, kind: DecodeKind::Length }, ilen == len);
+ Ok(olen)
+}
+
+// Fails with Length if length is invalid. The error is the largest valid
+// length.
+fn decode_base_len<B: Static<usize>>(bit: B, len: usize) -> Result<usize, DecodeError> {
+ decode_pad_len(bit, Bf, len)
+}
+
+// Fails with Symbol if an input character does not translate to a symbol. The
+// error is the lowest index of such character.
+// Fails with Trailing if there are non-zero trailing bits.
+fn decode_base_mut<B: Static<usize>, M: Static<bool>>(
+ bit: B, msb: M, ctb: bool, values: &[u8; 256], input: &[u8], output: &mut [u8],
+) -> Result<usize, DecodePartial> {
+ debug_assert_eq!(Ok(output.len()), decode_base_len(bit, input.len()));
+ let fail = |pos, kind| DecodePartial {
+ read: pos / dec(bit.val()) * dec(bit.val()),
+ written: pos / dec(bit.val()) * enc(bit.val()),
+ error: DecodeError { position: pos, kind },
+ };
+ decode_mut(bit, msb, values, input, output).map_err(|pos| fail(pos, DecodeKind::Symbol))?;
+ check_trail(bit, msb, ctb, values, input)
+ .map_err(|()| fail(input.len() - 1, DecodeKind::Trailing))?;
+ Ok(output.len())
+}
+
+// Fails with Symbol if an input character does not translate to a symbol. The
+// error is the lowest index of such character.
+// Fails with Padding if some padding length is invalid. The error is the index
+// of the first padding character of the invalid padding.
+// Fails with Trailing if there are non-zero trailing bits.
+fn decode_pad_mut<B: Static<usize>, M: Static<bool>, P: Static<bool>>(
+ bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, input: &[u8], output: &mut [u8],
+) -> Result<usize, DecodePartial> {
+ if !pad.val() {
+ return decode_base_mut(bit, msb, ctb, values, input, output);
+ }
+ debug_assert_eq!(Ok(output.len()), decode_pad_len(bit, pad, input.len()));
+ let enc = enc(bit.val());
+ let dec = dec(bit.val());
+ let mut inpos = 0;
+ let mut outpos = 0;
+ let mut outend = output.len();
+ while inpos < input.len() {
+ match decode_base_mut(
+ bit,
+ msb,
+ ctb,
+ values,
+ &input[inpos ..],
+ &mut output[outpos .. outend],
+ ) {
+ Ok(written) => {
+ if cfg!(debug_assertions) {
+ inpos = input.len();
+ }
+ outpos += written;
+ break;
+ }
+ Err(partial) => {
+ inpos += partial.read;
+ outpos += partial.written;
+ }
+ }
+ let inlen =
+ check_pad(bit, values, &input[inpos .. inpos + dec]).map_err(|pos| DecodePartial {
+ read: inpos,
+ written: outpos,
+ error: DecodeError { position: inpos + pos, kind: DecodeKind::Padding },
+ })?;
+ let outlen = decode_base_len(bit, inlen).unwrap();
+ let written = decode_base_mut(
+ bit,
+ msb,
+ ctb,
+ values,
+ &input[inpos .. inpos + inlen],
+ &mut output[outpos .. outpos + outlen],
+ )
+ .map_err(|partial| {
+ debug_assert_eq!(partial.read, 0);
+ debug_assert_eq!(partial.written, 0);
+ DecodePartial {
+ read: inpos,
+ written: outpos,
+ error: DecodeError {
+ position: inpos + partial.error.position,
+ kind: partial.error.kind,
+ },
+ }
+ })?;
+ debug_assert_eq!(written, outlen);
+ inpos += dec;
+ outpos += outlen;
+ outend -= enc - outlen;
+ }
+ debug_assert_eq!(inpos, input.len());
+ debug_assert_eq!(outpos, outend);
+ Ok(outend)
+}
+
+fn skip_ignore(values: &[u8; 256], input: &[u8], mut inpos: usize) -> usize {
+ while inpos < input.len() && values[input[inpos] as usize] == IGNORE {
+ inpos += 1;
+ }
+ inpos
+}
+
+// Returns next input and output position.
+// Fails with Symbol if an input character does not translate to a symbol. The
+// error is the lowest index of such character.
+// Fails with Padding if some padding length is invalid. The error is the index
+// of the first padding character of the invalid padding.
+// Fails with Trailing if there are non-zero trailing bits.
+fn decode_wrap_block<B: Static<usize>, M: Static<bool>, P: Static<bool>>(
+ bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, input: &[u8], output: &mut [u8],
+) -> Result<(usize, usize), DecodeError> {
+ let dec = dec(bit.val());
+ let mut buf = [0u8; 8];
+ let mut shift = [0usize; 8];
+ let mut bufpos = 0;
+ let mut inpos = 0;
+ while bufpos < dec {
+ inpos = skip_ignore(values, input, inpos);
+ if inpos == input.len() {
+ break;
+ }
+ shift[bufpos] = inpos;
+ buf[bufpos] = input[inpos];
+ bufpos += 1;
+ inpos += 1;
+ }
+ let olen = decode_pad_len(bit, pad, bufpos).map_err(|mut e| {
+ e.position = shift[e.position];
+ e
+ })?;
+ let written = decode_pad_mut(bit, msb, ctb, values, pad, &buf[.. bufpos], &mut output[.. olen])
+ .map_err(|partial| {
+ debug_assert_eq!(partial.read, 0);
+ debug_assert_eq!(partial.written, 0);
+ DecodeError { position: shift[partial.error.position], kind: partial.error.kind }
+ })?;
+ Ok((inpos, written))
+}
+
+// Fails with Symbol if an input character does not translate to a symbol. The
+// error is the lowest index of such character.
+// Fails with Padding if some padding length is invalid. The error is the index
+// of the first padding character of the invalid padding.
+// Fails with Trailing if there are non-zero trailing bits.
+// Fails with Length if input length (without ignored characters) is invalid.
+#[allow(clippy::too_many_arguments)]
+fn decode_wrap_mut<B: Static<usize>, M: Static<bool>, P: Static<bool>, I: Static<bool>>(
+ bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, has_ignore: I, input: &[u8],
+ output: &mut [u8],
+) -> Result<usize, DecodePartial> {
+ if !has_ignore.val() {
+ return decode_pad_mut(bit, msb, ctb, values, pad, input, output);
+ }
+ debug_assert_eq!(output.len(), decode_wrap_len(bit, pad, input.len()).1);
+ let mut inpos = 0;
+ let mut outpos = 0;
+ while inpos < input.len() {
+ let (inlen, outlen) = decode_wrap_len(bit, pad, input.len() - inpos);
+ match decode_pad_mut(
+ bit,
+ msb,
+ ctb,
+ values,
+ pad,
+ &input[inpos .. inpos + inlen],
+ &mut output[outpos .. outpos + outlen],
+ ) {
+ Ok(written) => {
+ inpos += inlen;
+ outpos += written;
+ break;
+ }
+ Err(partial) => {
+ inpos += partial.read;
+ outpos += partial.written;
+ }
+ }
+ let (ipos, opos) =
+ decode_wrap_block(bit, msb, ctb, values, pad, &input[inpos ..], &mut output[outpos ..])
+ .map_err(|mut error| {
+ error.position += inpos;
+ DecodePartial { read: inpos, written: outpos, error }
+ })?;
+ inpos += ipos;
+ outpos += opos;
+ }
+ let inpos = skip_ignore(values, input, inpos);
+ if inpos == input.len() {
+ Ok(outpos)
+ } else {
+ Err(DecodePartial {
+ read: inpos,
+ written: outpos,
+ error: DecodeError { position: inpos, kind: DecodeKind::Length },
+ })
+ }
+}
+
+/// Order in which bits are read from a byte
+///
+/// The base-conversion encoding is always little-endian. This means that the least significant
+/// **byte** is always first. However, we can still choose whether, within a byte, this is the most
+/// significant or the least significant **bit** that is first. If the terminology is confusing,
+/// testing on an asymmetrical example should be enough to choose the correct value.
+///
+/// # Examples
+///
+/// In the following example, we can see that a base with the `MostSignificantFirst` bit-order has
+/// the most significant bit first in the encoded output. In particular, the output is in the same
+/// order as the bits in the byte. The opposite happens with the `LeastSignificantFirst` bit-order.
+/// The least significant bit is first and the output is in the reverse order.
+///
+/// ```rust
+/// use data_encoding::{BitOrder, Specification};
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("01");
+/// spec.bit_order = BitOrder::MostSignificantFirst; // default
+/// let msb = spec.encoding().unwrap();
+/// spec.bit_order = BitOrder::LeastSignificantFirst;
+/// let lsb = spec.encoding().unwrap();
+/// assert_eq!(msb.encode(&[0b01010011]), "01010011");
+/// assert_eq!(lsb.encode(&[0b01010011]), "11001010");
+/// ```
+///
+/// # Features
+///
+/// Requires the `alloc` feature.
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[cfg(feature = "alloc")]
+pub enum BitOrder {
+ /// Most significant bit first
+ ///
+ /// This is the most common and most intuitive bit-order. In particular, this is the bit-order
+ /// used by [RFC4648] and thus the usual hexadecimal, base64, base32, base64url, and base32hex
+ /// encodings. This is the default bit-order when [specifying](struct.Specification.html) a
+ /// base.
+ ///
+ /// [RFC4648]: https://tools.ietf.org/html/rfc4648
+ MostSignificantFirst,
+
+ /// Least significant bit first
+ ///
+ /// # Examples
+ ///
+ /// DNSCurve [base32] uses least significant bit first:
+ ///
+ /// ```rust
+ /// use data_encoding::BASE32_DNSCURVE;
+ /// assert_eq!(BASE32_DNSCURVE.encode(&[0x64, 0x88]), "4321");
+ /// assert_eq!(BASE32_DNSCURVE.decode(b"4321").unwrap(), vec![0x64, 0x88]);
+ /// ```
+ ///
+ /// [base32]: constant.BASE32_DNSCURVE.html
+ LeastSignificantFirst,
+}
+#[cfg(feature = "alloc")]
+use crate::BitOrder::*;
+
+#[doc(hidden)]
+#[cfg(feature = "alloc")]
+pub type InternalEncoding = Cow<'static, [u8]>;
+
+#[doc(hidden)]
+#[cfg(not(feature = "alloc"))]
+pub type InternalEncoding = &'static [u8];
+
+/// Base-conversion encoding
+///
+/// See [Specification](struct.Specification.html) for technical details or how to define a new one.
+// Required fields:
+// 0 - 256 (256) symbols
+// 256 - 512 (256) values
+// 512 - 513 ( 1) padding
+// 513 - 514 ( 1) reserved(3),ctb(1),msb(1),bit(3)
+// Optional fields:
+// 514 - 515 ( 1) width
+// 515 - * ( N) separator
+// Invariants:
+// - symbols is 2^bit unique characters repeated 2^(8-bit) times
+// - values[128 ..] are INVALID
+// - values[0 .. 128] are either INVALID, IGNORE, PADDING, or < 2^bit
+// - padding is either < 128 or INVALID
+// - values[padding] is PADDING if padding < 128
+// - values and symbols are inverse
+// - ctb is true if 8 % bit == 0
+// - width is present if there is x such that values[x] is IGNORE
+// - width % dec(bit) == 0
+// - for all x in separator values[x] is IGNORE
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Encoding(pub InternalEncoding);
+
+/// How to translate characters when decoding
+///
+/// The order matters. The first character of the `from` field is translated to the first character
+/// of the `to` field. The second to the second. Etc.
+///
+/// See [Specification](struct.Specification.html) for more information.
+///
+/// # Features
+///
+/// Requires the `alloc` feature.
+#[derive(Debug, Clone)]
+#[cfg(feature = "alloc")]
+pub struct Translate {
+ /// Characters to translate from
+ pub from: String,
+
+ /// Characters to translate to
+ pub to: String,
+}
+
+/// How to wrap the output when encoding
+///
+/// See [Specification](struct.Specification.html) for more information.
+///
+/// # Features
+///
+/// Requires the `alloc` feature.
+#[derive(Debug, Clone)]
+#[cfg(feature = "alloc")]
+pub struct Wrap {
+ /// Wrapping width
+ ///
+ /// Must be a multiple of:
+ ///
+ /// - 8 for a bit-width of 1 (binary), 3 (octal), and 5 (base32)
+ /// - 4 for a bit-width of 2 (base4) and 6 (base64)
+ /// - 2 for a bit-width of 4 (hexadecimal)
+ ///
+ /// Wrapping is disabled if null.
+ pub width: usize,
+
+ /// Wrapping characters
+ ///
+ /// Wrapping is disabled if empty.
+ pub separator: String,
+}
+
+/// Base-conversion specification
+///
+/// It is possible to define custom encodings given a specification. To do so, it is important to
+/// understand the theory first.
+///
+/// # Theory
+///
+/// Each subsection has an equivalent subsection in the [Practice](#practice) section.
+///
+/// ## Basics
+///
+/// The main idea of a [base-conversion] encoding is to see `[u8]` as numbers written in
+/// little-endian base256 and convert them in another little-endian base. For performance reasons,
+/// this crate restricts this other base to be of size 2 (binary), 4 (base4), 8 (octal), 16
+/// (hexadecimal), 32 (base32), or 64 (base64). The converted number is written as `[u8]` although
+/// it doesn't use all the 256 possible values of `u8`. This crate encodes to ASCII, so only values
+/// smaller than 128 are allowed.
+///
+/// More precisely, we need the following elements:
+///
+/// - The bit-width N: 1 for binary, 2 for base4, 3 for octal, 4 for hexadecimal, 5 for base32, and
+/// 6 for base64
+/// - The [bit-order](enum.BitOrder.html): most or least significant bit first
+/// - The symbols function S from [0, 2<sup>N</sup>) (called values and written `uN`) to symbols
+/// (represented as `u8` although only ASCII symbols are allowed, i.e. smaller than 128)
+/// - The values partial function V from ASCII to [0, 2<sup>N</sup>), i.e. from `u8` to `uN`
+/// - Whether trailing bits are checked: trailing bits are leading zeros in theory, but since
+/// numbers are little-endian they come last
+///
+/// For the encoding to be correct (i.e. encoding then decoding gives back the initial input),
+/// V(S(i)) must be defined and equal to i for all i in [0, 2<sup>N</sup>). For the encoding to be
+/// [canonical][canonical] (i.e. different inputs decode to different outputs, or equivalently,
+/// decoding then encoding gives back the initial input), trailing bits must be checked and if V(i)
+/// is defined then S(V(i)) is equal to i for all i.
+///
+/// Encoding and decoding are given by the following pipeline:
+///
+/// ```text
+/// [u8] <--1--> [[bit; 8]] <--2--> [[bit; N]] <--3--> [uN] <--4--> [u8]
+/// 1: Map bit-order between each u8 and [bit; 8]
+/// 2: Base conversion between base 2^8 and base 2^N (check trailing bits)
+/// 3: Map bit-order between each [bit; N] and uN
+/// 4: Map symbols/values between each uN and u8 (values must be defined)
+/// ```
+///
+/// ## Extensions
+///
+/// All these extensions make the encoding not canonical.
+///
+/// ### Padding
+///
+/// Padding is useful if the following conditions are met:
+///
+/// - the bit-width is 3 (octal), 5 (base32), or 6 (base64)
+/// - the length of the data to encode is not known in advance
+/// - the data must be sent without buffering
+///
+/// Bases for which the bit-width N does not divide 8 may not concatenate encoded data. This comes
+/// from the fact that it is not possible to make the difference between trailing bits and encoding
+/// bits. Padding solves this issue by adding a new character to discriminate between trailing bits
+/// and encoding bits. The idea is to work by blocks of lcm(8, N) bits, where lcm(8, N) is the least
+/// common multiple of 8 and N. When such block is not complete, it is padded.
+///
+/// To preserve correctness, the padding character must not be a symbol.
+///
+/// ### Ignore characters when decoding
+///
+/// Ignoring characters when decoding is useful if after encoding some characters are added for
+/// convenience or any other reason (like wrapping). In that case we want to first ignore thoses
+/// characters before decoding.
+///
+/// To preserve correctness, ignored characters must not contain symbols or the padding character.
+///
+/// ### Wrap output when encoding
+///
+/// Wrapping output when encoding is useful if the output is meant to be printed in a document where
+/// width is limited (typically 80-columns documents). In that case, the wrapping width and the
+/// wrapping separator have to be defined.
+///
+/// To preserve correctness, the wrapping separator characters must be ignored (see previous
+/// subsection). As such, wrapping separator characters must also not contain symbols or the padding
+/// character.
+///
+/// ### Translate characters when decoding
+///
+/// Translating characters when decoding is useful when encoded data may be copied by a humain
+/// instead of a machine. Humans tend to confuse some characters for others. In that case we want to
+/// translate those characters before decoding.
+///
+/// To preserve correctness, the characters we translate _from_ must not contain symbols or the
+/// padding character, and the characters we translate _to_ must only contain symbols or the padding
+/// character.
+///
+/// # Practice
+///
+/// ## Basics
+///
+/// ```rust
+/// use data_encoding::{Encoding, Specification};
+/// fn make_encoding(symbols: &str) -> Encoding {
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str(symbols);
+/// spec.encoding().unwrap()
+/// }
+/// let binary = make_encoding("01");
+/// let octal = make_encoding("01234567");
+/// let hexadecimal = make_encoding("0123456789abcdef");
+/// assert_eq!(binary.encode(b"Bit"), "010000100110100101110100");
+/// assert_eq!(octal.encode(b"Bit"), "20464564");
+/// assert_eq!(hexadecimal.encode(b"Bit"), "426974");
+/// ```
+///
+/// The `binary` base has 2 symbols `0` and `1` with value 0 and 1 respectively. The `octal` base
+/// has 8 symbols `0` to `7` with value 0 to 7. The `hexadecimal` base has 16 symbols `0` to `9` and
+/// `a` to `f` with value 0 to 15. The following diagram gives the idea of how encoding works in the
+/// previous example (note that we can actually write such diagram only because the bit-order is
+/// most significant first):
+///
+/// ```text
+/// [ octal] | 2 : 0 : 4 : 6 : 4 : 5 : 6 : 4 |
+/// [ binary] |0 1 0 0 0 0 1 0|0 1 1 0 1 0 0 1|0 1 1 1 0 1 0 0|
+/// [hexadecimal] | 4 : 2 | 6 : 9 | 7 : 4 |
+/// ^-- LSB ^-- MSB
+/// ```
+///
+/// Note that in theory, these little-endian numbers are read from right to left (the most
+/// significant bit is at the right). Since leading zeros are meaningless (in our usual decimal
+/// notation 0123 is the same as 123), it explains why trailing bits must be zero. Trailing bits may
+/// occur when the bit-width of a base does not divide 8. Only binary, base4, and hexadecimal don't
+/// have trailing bits issues. So let's consider octal and base64, which have trailing bits in
+/// similar circumstances:
+///
+/// ```rust
+/// use data_encoding::{Specification, BASE64_NOPAD};
+/// let octal = {
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("01234567");
+/// spec.encoding().unwrap()
+/// };
+/// assert_eq!(BASE64_NOPAD.encode(b"B"), "Qg");
+/// assert_eq!(octal.encode(b"B"), "204");
+/// ```
+///
+/// We have the following diagram, where the base64 values are written between parentheses:
+///
+/// ```text
+/// [base64] | Q(16) : g(32) : [has 4 zero trailing bits]
+/// [ octal] | 2 : 0 : 4 : [has 1 zero trailing bit ]
+/// |0 1 0 0 0 0 1 0|0 0 0 0
+/// [ ascii] | B |
+/// ^-^-^-^-- leading zeros / trailing bits
+/// ```
+///
+/// ## Extensions
+///
+/// ### Padding
+///
+/// For octal and base64, lcm(8, 3) == lcm(8, 6) == 24 bits or 3 bytes. For base32, lcm(8, 5) is 40
+/// bits or 5 bytes. Let's consider octal and base64:
+///
+/// ```rust
+/// use data_encoding::{Specification, BASE64};
+/// let octal = {
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("01234567");
+/// spec.padding = Some('=');
+/// spec.encoding().unwrap()
+/// };
+/// // We start encoding but we only have "B" for now.
+/// assert_eq!(BASE64.encode(b"B"), "Qg==");
+/// assert_eq!(octal.encode(b"B"), "204=====");
+/// // Now we have "it".
+/// assert_eq!(BASE64.encode(b"it"), "aXQ=");
+/// assert_eq!(octal.encode(b"it"), "322720==");
+/// // By concatenating everything, we may decode the original data.
+/// assert_eq!(BASE64.decode(b"Qg==aXQ=").unwrap(), b"Bit");
+/// assert_eq!(octal.decode(b"204=====322720==").unwrap(), b"Bit");
+/// ```
+///
+/// We have the following diagrams:
+///
+/// ```text
+/// [base64] | Q(16) : g(32) : = : = |
+/// [ octal] | 2 : 0 : 4 : = : = : = : = : = |
+/// |0 1 0 0 0 0 1 0|. . . . . . . .|. . . . . . . .|
+/// [ ascii] | B | end of block aligned --^
+/// ^-- beginning of block aligned
+///
+/// [base64] | a(26) : X(23) : Q(16) : = |
+/// [ octal] | 3 : 2 : 2 : 7 : 2 : 0 : = : = |
+/// |0 1 1 0 1 0 0 1|0 1 1 1 0 1 0 0|. . . . . . . .|
+/// [ ascii] | i | t |
+/// ```
+///
+/// ### Ignore characters when decoding
+///
+/// The typical use-case is to ignore newlines (`\r` and `\n`). But to keep the example small, we
+/// will ignore spaces.
+///
+/// ```rust
+/// let mut spec = data_encoding::HEXLOWER.specification();
+/// spec.ignore.push_str(" \t");
+/// let base = spec.encoding().unwrap();
+/// assert_eq!(base.decode(b"42 69 74"), base.decode(b"426974"));
+/// ```
+///
+/// ### Wrap output when encoding
+///
+/// The typical use-case is to wrap after 64 or 76 characters with a newline (`\r\n` or `\n`). But
+/// to keep the example small, we will wrap after 8 characters with a space.
+///
+/// ```rust
+/// let mut spec = data_encoding::BASE64.specification();
+/// spec.wrap.width = 8;
+/// spec.wrap.separator.push_str(" ");
+/// let base64 = spec.encoding().unwrap();
+/// assert_eq!(base64.encode(b"Hey you"), "SGV5IHlv dQ== ");
+/// ```
+///
+/// Note that the output always ends with the separator.
+///
+/// ### Translate characters when decoding
+///
+/// The typical use-case is to translate lowercase to uppercase or reciprocally, but it is also used
+/// for letters that look alike, like `O0` or `Il1`. Let's illustrate both examples.
+///
+/// ```rust
+/// let mut spec = data_encoding::HEXLOWER.specification();
+/// spec.translate.from.push_str("ABCDEFOIl");
+/// spec.translate.to.push_str("abcdef011");
+/// let base = spec.encoding().unwrap();
+/// assert_eq!(base.decode(b"BOIl"), base.decode(b"b011"));
+/// ```
+///
+/// # Features
+///
+/// Requires the `alloc` feature.
+///
+/// [base-conversion]: https://en.wikipedia.org/wiki/Positional_notation#Base_conversion
+/// [canonical]: https://tools.ietf.org/html/rfc4648#section-3.5
+#[derive(Debug, Clone)]
+#[cfg(feature = "alloc")]
+pub struct Specification {
+ /// Symbols
+ ///
+ /// The number of symbols must be 2, 4, 8, 16, 32, or 64. Symbols must be ASCII characters
+ /// (smaller than 128) and they must be unique.
+ pub symbols: String,
+
+ /// Bit-order
+ ///
+ /// The default is to use most significant bit first since it is the most common.
+ pub bit_order: BitOrder,
+
+ /// Check trailing bits
+ ///
+ /// The default is to check trailing bits. This field is ignored when unnecessary (i.e. for
+ /// base2, base4, and base16).
+ pub check_trailing_bits: bool,
+
+ /// Padding
+ ///
+ /// The default is to not use padding. The padding character must be ASCII and must not be a
+ /// symbol.
+ pub padding: Option<char>,
+
+ /// Characters to ignore when decoding
+ ///
+ /// The default is to not ignore characters when decoding. The characters to ignore must be
+ /// ASCII and must not be symbols or the padding character.
+ pub ignore: String,
+
+ /// How to wrap the output when encoding
+ ///
+ /// The default is to not wrap the output when encoding. The wrapping characters must be ASCII
+ /// and must not be symbols or the padding character.
+ pub wrap: Wrap,
+
+ /// How to translate characters when decoding
+ ///
+ /// The default is to not translate characters when decoding. The characters to translate from
+ /// must be ASCII and must not have already been assigned a semantics. The characters to
+ /// translate to must be ASCII and must have been assigned a semantics (symbol, padding
+ /// character, or ignored character).
+ pub translate: Translate,
+}
+
+#[cfg(feature = "alloc")]
+impl Default for Specification {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Encoding {
+ fn sym(&self) -> &[u8; 256] {
+ 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
+ }
+
+ fn wrap(&self) -> Option<(usize, &[u8])> {
+ if self.0.len() <= 515 {
+ return None;
+ }
+ Some((self.0[514] as usize, &self.0[515 ..]))
+ }
+
+ fn has_ignore(&self) -> bool {
+ self.0.len() >= 515
+ }
+
+ /// Returns the encoded length of an input of length `len`
+ ///
+ /// See [`encode_mut`] for when to use it.
+ ///
+ /// [`encode_mut`]: struct.Encoding.html#method.encode_mut
+ pub fn encode_len(&self, len: usize) -> usize {
+ dispatch! {
+ let bit: usize = self.bit();
+ let pad: Option<u8> = self.pad();
+ let wrap: Option<(usize, &[u8])> = self.wrap();
+ encode_wrap_len(bit, pad, wrap, len)
+ }
+ }
+
+ /// Encodes `input` in `output`
+ ///
+ /// # Panics
+ ///
+ /// Panics if the `output` length does not match the result of [`encode_len`] for the `input`
+ /// length.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use data_encoding::BASE64;
+ /// # let mut buffer = vec![0; 100];
+ /// let input = b"Hello world";
+ /// let output = &mut buffer[0 .. BASE64.encode_len(input.len())];
+ /// BASE64.encode_mut(input, output);
+ /// assert_eq!(output, b"SGVsbG8gd29ybGQ=");
+ /// ```
+ ///
+ /// [`encode_len`]: struct.Encoding.html#method.encode_len
+ #[allow(clippy::cognitive_complexity)]
+ pub fn encode_mut(&self, input: &[u8], output: &mut [u8]) {
+ assert_eq!(output.len(), self.encode_len(input.len()));
+ dispatch! {
+ let bit: usize = self.bit();
+ let msb: bool = self.msb();
+ let pad: Option<u8> = self.pad();
+ let wrap: Option<(usize, &[u8])> = self.wrap();
+ encode_wrap_mut(bit, msb, self.sym(), pad, wrap, input, output)
+ }
+ }
+
+ /// Appends the encoding of `input` to `output`
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use data_encoding::BASE64;
+ /// # let mut buffer = vec![0; 100];
+ /// let input = b"Hello world";
+ /// let mut output = "Result: ".to_string();
+ /// BASE64.encode_append(input, &mut output);
+ /// assert_eq!(output, "Result: SGVsbG8gd29ybGQ=");
+ /// ```
+ ///
+ /// # Features
+ ///
+ /// Requires the `alloc` feature.
+ #[cfg(feature = "alloc")]
+ pub fn encode_append(&self, input: &[u8], output: &mut String) {
+ let output = unsafe { output.as_mut_vec() };
+ let output_len = output.len();
+ output.resize(output_len + self.encode_len(input.len()), 0u8);
+ self.encode_mut(input, &mut output[output_len ..]);
+ }
+
+ /// Returns encoded `input`
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use data_encoding::BASE64;
+ /// assert_eq!(BASE64.encode(b"Hello world"), "SGVsbG8gd29ybGQ=");
+ /// ```
+ ///
+ /// # Features
+ ///
+ /// Requires the `alloc` feature.
+ #[cfg(feature = "alloc")]
+ pub fn encode(&self, input: &[u8]) -> String {
+ let mut output = vec![0u8; self.encode_len(input.len())];
+ self.encode_mut(input, &mut output);
+ unsafe { String::from_utf8_unchecked(output) }
+ }
+
+ /// Returns the decoded length of an input of length `len`
+ ///
+ /// See [`decode_mut`] for when to use it.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if `len` is invalid. The error kind is [`Length`] and the [position] is the
+ /// greatest valid input length.
+ ///
+ /// [`decode_mut`]: struct.Encoding.html#method.decode_mut
+ /// [`Length`]: enum.DecodeKind.html#variant.Length
+ /// [position]: struct.DecodeError.html#structfield.position
+ pub fn decode_len(&self, len: usize) -> Result<usize, DecodeError> {
+ let (ilen, olen) = dispatch! {
+ let bit: usize = self.bit();
+ let pad: bool = self.pad().is_some();
+ decode_wrap_len(bit, pad, len)
+ };
+ check!(
+ DecodeError { position: ilen, kind: DecodeKind::Length },
+ self.has_ignore() || len == ilen
+ );
+ Ok(olen)
+ }
+
+ /// Decodes `input` in `output`
+ ///
+ /// Returns the length of the decoded output. This length may be smaller than the output length
+ /// if the input contained padding or ignored characters. The output bytes after the returned
+ /// length are not initialized and should not be read.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the `output` length does not match the result of [`decode_len`] for the `input`
+ /// length. Also panics if `decode_len` fails for the `input` length.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if `input` is invalid. See [`decode`] for more details. The are two
+ /// differences though:
+ ///
+ /// - [`Length`] may be returned only if the encoding allows ignored characters, because
+ /// otherwise this is already checked by [`decode_len`].
+ /// - The [`read`] first bytes of the input have been successfully decoded to the [`written`]
+ /// first bytes of the output.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use data_encoding::BASE64;
+ /// # let mut buffer = vec![0; 100];
+ /// let input = b"SGVsbA==byB3b3JsZA==";
+ /// let output = &mut buffer[0 .. BASE64.decode_len(input.len()).unwrap()];
+ /// let len = BASE64.decode_mut(input, output).unwrap();
+ /// assert_eq!(&output[0 .. len], b"Hello world");
+ /// ```
+ ///
+ /// [`decode_len`]: struct.Encoding.html#method.decode_len
+ /// [`decode`]: struct.Encoding.html#method.decode
+ /// [`Length`]: enum.DecodeKind.html#variant.Length
+ /// [`read`]: struct.DecodePartial.html#structfield.read
+ /// [`written`]: struct.DecodePartial.html#structfield.written
+ #[allow(clippy::cognitive_complexity)]
+ pub fn decode_mut(&self, input: &[u8], output: &mut [u8]) -> Result<usize, DecodePartial> {
+ assert_eq!(Ok(output.len()), self.decode_len(input.len()));
+ dispatch! {
+ let bit: usize = self.bit();
+ let msb: bool = self.msb();
+ let pad: bool = self.pad().is_some();
+ let has_ignore: bool = self.has_ignore();
+ decode_wrap_mut(bit, msb, self.ctb(), self.val(), pad, has_ignore,
+ input, output)
+ }
+ }
+
+ /// Returns decoded `input`
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if `input` is invalid. The error kind can be:
+ ///
+ /// - [`Length`] if the input length is invalid. The [position] is the greatest valid input
+ /// length.
+ /// - [`Symbol`] if the input contains an invalid character. The [position] is the first invalid
+ /// character.
+ /// - [`Trailing`] if the input has non-zero trailing bits. This is only possible if the
+ /// encoding checks trailing bits. The [position] is the first character containing non-zero
+ /// trailing bits.
+ /// - [`Padding`] if the input has an invalid padding length. This is only possible if the
+ /// encoding uses padding. The [position] is the first padding character of the first padding
+ /// of invalid length.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use data_encoding::BASE64;
+ /// assert_eq!(BASE64.decode(b"SGVsbA==byB3b3JsZA==").unwrap(), b"Hello world");
+ /// ```
+ ///
+ /// # Features
+ ///
+ /// Requires the `alloc` feature.
+ ///
+ /// [`Length`]: enum.DecodeKind.html#variant.Length
+ /// [`Symbol`]: enum.DecodeKind.html#variant.Symbol
+ /// [`Trailing`]: enum.DecodeKind.html#variant.Trailing
+ /// [`Padding`]: enum.DecodeKind.html#variant.Padding
+ /// [position]: struct.DecodeError.html#structfield.position
+ #[cfg(feature = "alloc")]
+ pub fn decode(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError> {
+ let mut output = vec![0u8; self.decode_len(input.len())?];
+ let len = self.decode_mut(input, &mut output).map_err(|partial| partial.error)?;
+ output.truncate(len);
+ Ok(output)
+ }
+
+ /// Returns the bit-width
+ pub fn bit_width(&self) -> usize {
+ self.bit()
+ }
+
+ /// Returns whether the encoding is canonical
+ ///
+ /// An encoding is not canonical if one of the following conditions holds:
+ ///
+ /// - trailing bits are not checked
+ /// - padding is used
+ /// - characters are ignored
+ /// - characters are translated
+ pub fn is_canonical(&self) -> bool {
+ if !self.ctb() {
+ return false;
+ }
+ let bit = self.bit();
+ let sym = self.sym();
+ let val = self.val();
+ for i in 0 .. 256 {
+ if val[i] == INVALID {
+ continue;
+ }
+ if val[i] >= 1 << bit {
+ return false;
+ }
+ if sym[val[i] as usize] != i as u8 {
+ return false;
+ }
+ }
+ true
+ }
+
+ /// Returns the encoding specification
+ ///
+ /// # Features
+ ///
+ /// Requires the `alloc` feature.
+ #[cfg(feature = "alloc")]
+ pub fn specification(&self) -> Specification {
+ let mut specification = Specification::new();
+ specification
+ .symbols
+ .push_str(core::str::from_utf8(&self.sym()[0 .. 1 << self.bit()]).unwrap());
+ specification.bit_order =
+ if self.msb() { MostSignificantFirst } else { LeastSignificantFirst };
+ specification.check_trailing_bits = self.ctb();
+ if let Some(pad) = self.pad() {
+ specification.padding = Some(pad as char);
+ }
+ for i in 0 .. 128u8 {
+ if self.val()[i as usize] != IGNORE {
+ continue;
+ }
+ specification.ignore.push(i as char);
+ }
+ if let Some((col, end)) = self.wrap() {
+ specification.wrap.width = col;
+ specification.wrap.separator = core::str::from_utf8(end).unwrap().to_owned();
+ }
+ for i in 0 .. 128u8 {
+ let canonical = if self.val()[i as usize] < 1 << self.bit() {
+ self.sym()[self.val()[i as usize] as usize]
+ } else if self.val()[i as usize] == PADDING {
+ self.pad().unwrap()
+ } else {
+ continue;
+ };
+ if i == canonical {
+ continue;
+ }
+ specification.translate.from.push(i as char);
+ specification.translate.to.push(canonical as char);
+ }
+ specification
+ }
+
+ #[doc(hidden)]
+ pub const fn internal_new(implementation: &'static [u8]) -> Encoding {
+ #[cfg(feature = "alloc")]
+ let encoding = Encoding(Cow::Borrowed(implementation));
+ #[cfg(not(feature = "alloc"))]
+ let encoding = Encoding(implementation);
+ encoding
+ }
+
+ #[doc(hidden)]
+ pub fn internal_implementation(&self) -> &[u8] {
+ &self.0
+ }
+}
+
+#[derive(Debug, Copy, Clone)]
+#[cfg(feature = "alloc")]
+enum SpecificationErrorImpl {
+ BadSize,
+ NotAscii,
+ Duplicate(u8),
+ ExtraPadding,
+ WrapLength,
+ WrapWidth(u8),
+ FromTo,
+ Undefined(u8),
+}
+#[cfg(feature = "alloc")]
+use crate::SpecificationErrorImpl::*;
+
+/// Specification error
+///
+/// # Features
+///
+/// Requires the `alloc` feature.
+#[derive(Debug, Copy, Clone)]
+#[cfg(feature = "alloc")]
+pub struct SpecificationError(SpecificationErrorImpl);
+
+#[cfg(feature = "alloc")]
+impl core::fmt::Display for SpecificationError {
+ fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ match self.0 {
+ BadSize => write!(f, "invalid number of symbols"),
+ NotAscii => write!(f, "non-ascii character"),
+ Duplicate(c) => write!(f, "{:?} has conflicting definitions", c as char),
+ ExtraPadding => write!(f, "unnecessary padding"),
+ WrapLength => write!(f, "invalid wrap width or separator length"),
+ WrapWidth(x) => write!(f, "wrap width not a multiple of {}", x),
+ FromTo => write!(f, "translate from/to length mismatch"),
+ Undefined(c) => write!(f, "{:?} is undefined", c as char),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for SpecificationError {
+ fn description(&self) -> &str {
+ match self.0 {
+ BadSize => "invalid number of symbols",
+ NotAscii => "non-ascii character",
+ Duplicate(_) => "conflicting definitions",
+ ExtraPadding => "unnecessary padding",
+ WrapLength => "invalid wrap width or separator length",
+ WrapWidth(_) => "wrap width not a multiple",
+ FromTo => "translate from/to length mismatch",
+ Undefined(_) => "undefined character",
+ }
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl Specification {
+ /// Returns a default specification
+ pub fn new() -> Specification {
+ Specification {
+ symbols: String::new(),
+ bit_order: MostSignificantFirst,
+ check_trailing_bits: true,
+ padding: None,
+ ignore: String::new(),
+ wrap: Wrap { width: 0, separator: String::new() },
+ translate: Translate { from: String::new(), to: String::new() },
+ }
+ }
+
+ /// Returns the specified encoding
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the specification is invalid.
+ pub fn encoding(&self) -> Result<Encoding, SpecificationError> {
+ let symbols = self.symbols.as_bytes();
+ let bit: usize = match symbols.len() {
+ 2 => 1,
+ 4 => 2,
+ 8 => 3,
+ 16 => 4,
+ 32 => 5,
+ 64 => 6,
+ _ => return Err(SpecificationError(BadSize)),
+ };
+ let mut values = [INVALID; 128];
+ let set = |v: &mut [u8; 128], i: u8, x: u8| {
+ check!(SpecificationError(NotAscii), i < 128);
+ if v[i as usize] == x {
+ return Ok(());
+ }
+ check!(SpecificationError(Duplicate(i)), v[i as usize] == INVALID);
+ v[i as usize] = x;
+ Ok(())
+ };
+ for (v, symbols) in symbols.iter().enumerate() {
+ set(&mut values, *symbols, v as u8)?;
+ }
+ let msb = self.bit_order == MostSignificantFirst;
+ let ctb = self.check_trailing_bits || 8 % bit == 0;
+ let pad = match self.padding {
+ None => None,
+ Some(pad) => {
+ check!(SpecificationError(ExtraPadding), 8 % bit != 0);
+ check!(SpecificationError(NotAscii), pad.len_utf8() == 1);
+ set(&mut values, pad as u8, PADDING)?;
+ Some(pad as u8)
+ }
+ };
+ for i in self.ignore.bytes() {
+ set(&mut values, i, IGNORE)?;
+ }
+ let wrap = if self.wrap.separator.is_empty() || self.wrap.width == 0 {
+ None
+ } else {
+ Some((self.wrap.width, self.wrap.separator.as_bytes()))
+ };
+ if let Some((col, end)) = wrap {
+ check!(SpecificationError(WrapLength), col < 256 && end.len() < 256);
+ check!(SpecificationError(WrapWidth(dec(bit) as u8)), col % dec(bit) == 0);
+ for i in end.iter() {
+ set(&mut values, *i, IGNORE)?;
+ }
+ }
+ let from = self.translate.from.as_bytes();
+ let to = self.translate.to.as_bytes();
+ check!(SpecificationError(FromTo), from.len() == to.len());
+ for i in 0 .. from.len() {
+ check!(SpecificationError(NotAscii), to[i] < 128);
+ let v = values[to[i] as usize];
+ check!(SpecificationError(Undefined(to[i])), v != INVALID);
+ set(&mut values, from[i], v)?;
+ }
+ let mut encoding = Vec::new();
+ for _ in 0 .. 256 / symbols.len() {
+ encoding.extend_from_slice(symbols);
+ }
+ encoding.extend_from_slice(&values);
+ encoding.extend_from_slice(&[INVALID; 128]);
+ match pad {
+ None => encoding.push(INVALID),
+ Some(pad) => encoding.push(pad),
+ }
+ encoding.push(bit as u8);
+ if msb {
+ encoding[513] |= 0x08;
+ }
+ if ctb {
+ encoding[513] |= 0x10;
+ }
+ if let Some((col, end)) = wrap {
+ encoding.push(col as u8);
+ encoding.extend_from_slice(end);
+ } else if values.contains(&IGNORE) {
+ encoding.push(0);
+ }
+ Ok(Encoding(Cow::Owned(encoding)))
+ }
+}
+
+/// Lowercase hexadecimal encoding
+///
+/// This encoding is a static version of:
+///
+/// ```rust
+/// # use data_encoding::{Specification, HEXLOWER};
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("0123456789abcdef");
+/// assert_eq!(HEXLOWER, spec.encoding().unwrap());
+/// ```
+///
+/// # Examples
+///
+/// ```rust
+/// use data_encoding::HEXLOWER;
+/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef];
+/// assert_eq!(HEXLOWER.decode(b"deadbeef").unwrap(), deadbeef);
+/// assert_eq!(HEXLOWER.encode(&deadbeef), "deadbeef");
+/// ```
+pub const HEXLOWER: Encoding = Encoding::internal_new(HEXLOWER_IMPL);
+const HEXLOWER_IMPL: &[u8] = &[
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100,
+ 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97,
+ 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100,
+ 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97,
+ 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 97, 98, 99, 100, 101, 102, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28,
+];
+
+/// Lowercase hexadecimal encoding with case-insensitive decoding
+///
+/// This encoding is a static version of:
+///
+/// ```rust
+/// # use data_encoding::{Specification, HEXLOWER_PERMISSIVE};
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("0123456789abcdef");
+/// spec.translate.from.push_str("ABCDEF");
+/// spec.translate.to.push_str("abcdef");
+/// assert_eq!(HEXLOWER_PERMISSIVE, spec.encoding().unwrap());
+/// ```
+///
+/// # Examples
+///
+/// ```rust
+/// use data_encoding::HEXLOWER_PERMISSIVE;
+/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef];
+/// assert_eq!(HEXLOWER_PERMISSIVE.decode(b"DeadBeef").unwrap(), deadbeef);
+/// assert_eq!(HEXLOWER_PERMISSIVE.encode(&deadbeef), "deadbeef");
+/// ```
+///
+/// You can also define a shorter name:
+///
+/// ```rust
+/// use data_encoding::{Encoding, HEXLOWER_PERMISSIVE};
+/// const HEX: Encoding = HEXLOWER_PERMISSIVE;
+/// ```
+pub const HEXLOWER_PERMISSIVE: Encoding = Encoding::internal_new(HEXLOWER_PERMISSIVE_IMPL);
+const HEXLOWER_PERMISSIVE_IMPL: &[u8] = &[
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100,
+ 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97,
+ 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100,
+ 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97,
+ 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48,
+ 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 97, 98, 99, 100, 101, 102, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28,
+];
+
+/// Uppercase hexadecimal encoding
+///
+/// This encoding is a static version of:
+///
+/// ```rust
+/// # use data_encoding::{Specification, HEXUPPER};
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("0123456789ABCDEF");
+/// assert_eq!(HEXUPPER, spec.encoding().unwrap());
+/// ```
+///
+/// It is compliant with [RFC4648] and known as "base16" or "hex".
+///
+/// # Examples
+///
+/// ```rust
+/// use data_encoding::HEXUPPER;
+/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef];
+/// assert_eq!(HEXUPPER.decode(b"DEADBEEF").unwrap(), deadbeef);
+/// assert_eq!(HEXUPPER.encode(&deadbeef), "DEADBEEF");
+/// ```
+///
+/// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-8
+pub const HEXUPPER: Encoding = Encoding::internal_new(HEXUPPER_IMPL);
+const HEXUPPER_IMPL: &[u8] = &[
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11,
+ 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28,
+];
+
+/// Uppercase hexadecimal encoding with case-insensitive decoding
+///
+/// This encoding is a static version of:
+///
+/// ```rust
+/// # use data_encoding::{Specification, HEXUPPER_PERMISSIVE};
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("0123456789ABCDEF");
+/// spec.translate.from.push_str("abcdef");
+/// spec.translate.to.push_str("ABCDEF");
+/// assert_eq!(HEXUPPER_PERMISSIVE, spec.encoding().unwrap());
+/// ```
+///
+/// # Examples
+///
+/// ```rust
+/// use data_encoding::HEXUPPER_PERMISSIVE;
+/// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef];
+/// assert_eq!(HEXUPPER_PERMISSIVE.decode(b"DeadBeef").unwrap(), deadbeef);
+/// assert_eq!(HEXUPPER_PERMISSIVE.encode(&deadbeef), "DEADBEEF");
+/// ```
+pub const HEXUPPER_PERMISSIVE: Encoding = Encoding::internal_new(HEXUPPER_PERMISSIVE_IMPL);
+const HEXUPPER_PERMISSIVE_IMPL: &[u8] = &[
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11,
+ 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28,
+];
+
+/// Padded base32 encoding
+///
+/// This encoding is a static version of:
+///
+/// ```rust
+/// # use data_encoding::{Specification, BASE32};
+/// let mut spec = Specification::new();
+/// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567");
+/// spec.padding = Some('=');
+/// assert_eq!(BASE32, spec.encoding().unwrap());
+/// ```
+///
+/// It 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,
+];
+
+/// 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,
+];