| //! 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)` | `Byte(2)` | `\x00\x00` | |
| //! | `AAB` | `Length(0)` | `Padding` | Invalid input | |
| //! | `AAA` | `Length(0)` | `Padding` | Invalid input | |
| //! | `A\rA\nB=` | `Length(4)` | `Byte(1)` | Invalid input | |
| //! | `-_\r\n` | `Symbol(0)` | `Byte(0)` | Invalid input | |
| //! | `AA==AA==` | `[0, 0]` | `Byte(2)` | `\x00\x00` | |
| //! |
| //! We can summarize these discrepancies as follows: |
| //! |
| //! | Discrepancy | `data-encoding` | `base64` | GNU `base64` | |
| //! | -------------------------- | --------------- | -------- | ------------ | |
| //! | Check trailing bits | Yes | Yes | No | |
| //! | Ignored characters | None | None | `\n` | |
| //! | Translated characters | None | None | None | |
| //! | Check padding | Yes | No | Yes | |
| //! | Support concatenated input | Yes | No | Yes | |
| //! |
| //! This crate permits to disable checking trailing bits. It permits to ignore some characters. It |
| //! permits to translate characters. It permits to use unpadded encodings. However, for padded |
| //! encodings, support for concatenated inputs cannot be disabled. This is simply because it doesn't |
| //! make sense to use padding if it is not to support concatenated inputs. |
| //! |
| //! [RFC4648]: https://tools.ietf.org/html/rfc4648 |
| //! [`BASE32HEX`]: constant.BASE32HEX.html |
| //! [`BASE32`]: constant.BASE32.html |
| //! [`BASE64URL`]: constant.BASE64URL.html |
| //! [`BASE64`]: constant.BASE64.html |
| //! [`Encoding`]: struct.Encoding.html |
| //! [`HEXUPPER`]: constant.HEXUPPER.html |
| //! [`Specification`]: struct.Specification.html |
| //! [`is_canonical`]: struct.Encoding.html#method.is_canonical |
| //! [binary]: https://crates.io/crates/data-encoding-bin |
| //! [bit-order]: struct.Specification.html#structfield.bit_order |
| //! [canonical]: https://tools.ietf.org/html/rfc4648#section-3.5 |
| //! [constants]: index.html#constants |
| //! [crate]: https://crates.io/crates/data-encoding |
| //! [decoding]: struct.Encoding.html#method.decode_mut |
| //! [encoding]: struct.Encoding.html#method.encode_mut |
| //! [ignoring]: struct.Specification.html#structfield.ignore |
| //! [macro]: https://crates.io/crates/data-encoding-macro |
| //! [padding]: struct.Specification.html#structfield.padding |
| //! [trailing bits]: struct.Specification.html#structfield.check_trailing_bits |
| //! [translation]: struct.Specification.html#structfield.translate |
| //! [website]: https://data-encoding.rs |
| //! [wrapping]: struct.Specification.html#structfield.wrap |
| |
| #![no_std] |
| #![cfg_attr(docsrs, feature(doc_auto_cfg))] |
| // TODO: This list up to warn(clippy::pedantic) should ideally use a lint group. |
| #![warn(elided_lifetimes_in_paths)] |
| // TODO(msrv): #![warn(let_underscore_drop)] |
| #![warn(missing_debug_implementations)] |
| #![warn(missing_docs)] |
| #![warn(unreachable_pub)] |
| // TODO(msrv): #![warn(unsafe_op_in_unsafe_fn)] |
| #![warn(unused_results)] |
| #![allow(unused_unsafe)] // TODO(msrv) |
| #![warn(clippy::pedantic)] |
| #![allow(clippy::assigning_clones)] // TODO(msrv) |
| #![allow(clippy::doc_markdown)] |
| #![allow(clippy::enum_glob_use)] |
| #![allow(clippy::similar_names)] |
| #![allow(clippy::uninlined_format_args)] // TODO(msrv) |
| |
| #[cfg(feature = "alloc")] |
| extern crate alloc; |
| #[cfg(feature = "std")] |
| extern crate std; |
| |
| #[cfg(feature = "alloc")] |
| use alloc::borrow::{Cow, ToOwned}; |
| #[cfg(feature = "alloc")] |
| use alloc::string::String; |
| #[cfg(feature = "alloc")] |
| use alloc::vec; |
| #[cfg(feature = "alloc")] |
| use alloc::vec::Vec; |
| use core::convert::TryInto; |
| |
| macro_rules! check { |
| ($e: expr, $c: expr) => { |
| if !$c { |
| return Err($e); |
| } |
| }; |
| } |
| |
| trait Static<T: Copy>: Copy { |
| fn val(self) -> T; |
| } |
| |
| macro_rules! define { |
| ($name: ident: $type: ty = $val: expr) => { |
| #[derive(Copy, Clone)] |
| struct $name; |
| impl Static<$type> for $name { |
| fn val(self) -> $type { |
| $val |
| } |
| } |
| }; |
| } |
| |
| define!(Bf: bool = false); |
| define!(Bt: bool = true); |
| define!(N1: usize = 1); |
| define!(N2: usize = 2); |
| define!(N3: usize = 3); |
| define!(N4: usize = 4); |
| define!(N5: usize = 5); |
| define!(N6: usize = 6); |
| |
| #[derive(Copy, Clone)] |
| struct On; |
| |
| impl<T: Copy> Static<Option<T>> for On { |
| fn val(self) -> Option<T> { |
| None |
| } |
| } |
| |
| #[derive(Copy, Clone)] |
| struct Os<T>(T); |
| |
| impl<T: Copy> Static<Option<T>> for Os<T> { |
| fn val(self) -> Option<T> { |
| Some(self.0) |
| } |
| } |
| |
| macro_rules! dispatch { |
| (let $var: ident: bool = $val: expr; $($body: tt)*) => { |
| if $val { |
| let $var = Bt; dispatch!($($body)*) |
| } else { |
| let $var = Bf; dispatch!($($body)*) |
| } |
| }; |
| (let $var: ident: usize = $val: expr; $($body: tt)*) => { |
| match $val { |
| 1 => { let $var = N1; dispatch!($($body)*) }, |
| 2 => { let $var = N2; dispatch!($($body)*) }, |
| 3 => { let $var = N3; dispatch!($($body)*) }, |
| 4 => { let $var = N4; dispatch!($($body)*) }, |
| 5 => { let $var = N5; dispatch!($($body)*) }, |
| 6 => { let $var = N6; dispatch!($($body)*) }, |
| _ => panic!(), |
| } |
| }; |
| (let $var: ident: Option<$type: ty> = $val: expr; $($body: tt)*) => { |
| match $val { |
| None => { let $var = On; dispatch!($($body)*) }, |
| Some(x) => { let $var = Os(x); dispatch!($($body)*) }, |
| } |
| }; |
| ($body: expr) => { $body }; |
| } |
| |
| unsafe fn chunk_unchecked(x: &[u8], n: usize, i: usize) -> &[u8] { |
| debug_assert!((i + 1) * n <= x.len()); |
| unsafe { core::slice::from_raw_parts(x.as_ptr().add(n * i), n) } |
| } |
| |
| unsafe fn chunk_mut_unchecked(x: &mut [u8], n: usize, i: usize) -> &mut [u8] { |
| debug_assert!((i + 1) * n <= x.len()); |
| unsafe { core::slice::from_raw_parts_mut(x.as_mut_ptr().add(n * i), n) } |
| } |
| |
| fn div_ceil(x: usize, m: usize) -> usize { |
| (x + m - 1) / m |
| } |
| |
| fn floor(x: usize, m: usize) -> usize { |
| x / m * m |
| } |
| |
| fn vectorize<F: FnMut(usize)>(n: usize, bs: usize, mut f: F) { |
| for k in 0 .. n / bs { |
| for i in k * bs .. (k + 1) * bs { |
| f(i); |
| } |
| } |
| for i in floor(n, bs) .. n { |
| f(i); |
| } |
| } |
| |
| /// Decoding error kind |
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| pub enum DecodeKind { |
| /// Invalid length |
| Length, |
| |
| /// Invalid symbol |
| Symbol, |
| |
| /// Non-zero trailing bits |
| Trailing, |
| |
| /// Invalid padding length |
| Padding, |
| } |
| |
| impl core::fmt::Display for DecodeKind { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| let description = match self { |
| DecodeKind::Length => "invalid length", |
| DecodeKind::Symbol => "invalid symbol", |
| DecodeKind::Trailing => "non-zero trailing bits", |
| DecodeKind::Padding => "invalid padding length", |
| }; |
| write!(f, "{}", description) |
| } |
| } |
| |
| /// Decoding error |
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| pub struct DecodeError { |
| /// Error position |
| /// |
| /// This position is always a valid input position and represents the first encountered error. |
| pub position: usize, |
| |
| /// Error kind |
| pub kind: DecodeKind, |
| } |
| |
| #[cfg(feature = "std")] |
| impl std::error::Error for DecodeError {} |
| |
| impl core::fmt::Display for DecodeError { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| write!(f, "{} at {}", self.kind, self.position) |
| } |
| } |
| |
| /// Decoding error with partial result |
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| pub struct DecodePartial { |
| /// Number of bytes read from input |
| /// |
| /// This number does not exceed the error position: `read <= error.position`. |
| pub read: usize, |
| |
| /// Number of bytes written to output |
| /// |
| /// This number does not exceed the decoded length: `written <= decode_len(read)`. |
| pub written: usize, |
| |
| /// Decoding error |
| pub error: DecodeError, |
| } |
| |
| const INVALID: u8 = 128; |
| const IGNORE: u8 = 129; |
| const PADDING: u8 = 130; |
| |
| fn order(msb: bool, n: usize, i: usize) -> usize { |
| if msb { |
| n - 1 - i |
| } else { |
| i |
| } |
| } |
| |
| fn enc(bit: usize) -> usize { |
| match bit { |
| 1 | 2 | 4 => 1, |
| 3 | 6 => 3, |
| 5 => 5, |
| _ => unreachable!(), |
| } |
| } |
| |
| fn dec(bit: usize) -> usize { |
| enc(bit) * 8 / bit |
| } |
| |
| fn encode_len<B: Static<usize>>(bit: B, len: usize) -> usize { |
| div_ceil(8 * len, bit.val()) |
| } |
| |
| fn encode_block<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8], |
| ) { |
| debug_assert!(input.len() <= enc(bit.val())); |
| debug_assert_eq!(output.len(), encode_len(bit, input.len())); |
| let bit = bit.val(); |
| let msb = msb.val(); |
| let mut x = 0u64; |
| for (i, input) in input.iter().enumerate() { |
| x |= u64::from(*input) << (8 * order(msb, enc(bit), i)); |
| } |
| for (i, output) in output.iter_mut().enumerate() { |
| let y = x >> (bit * order(msb, dec(bit), i)); |
| *output = symbols[(y & 0xff) as usize]; |
| } |
| } |
| |
| fn encode_mut<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8], |
| ) { |
| debug_assert_eq!(output.len(), encode_len(bit, input.len())); |
| let enc = enc(bit.val()); |
| let dec = dec(bit.val()); |
| let n = input.len() / enc; |
| let bs = match bit.val() { |
| 5 => 2, |
| 6 => 4, |
| _ => 1, |
| }; |
| vectorize(n, bs, |i| { |
| let input = unsafe { chunk_unchecked(input, enc, i) }; |
| let output = unsafe { chunk_mut_unchecked(output, dec, i) }; |
| encode_block(bit, msb, symbols, input, output); |
| }); |
| encode_block(bit, msb, symbols, &input[enc * n ..], &mut output[dec * n ..]); |
| } |
| |
| // Fails if an input character does not translate to a symbol. The error is the |
| // lowest index of such character. The output is not written to. |
| fn decode_block<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, values: &[u8; 256], input: &[u8], output: &mut [u8], |
| ) -> Result<(), usize> { |
| debug_assert!(output.len() <= enc(bit.val())); |
| debug_assert_eq!(input.len(), encode_len(bit, output.len())); |
| let bit = bit.val(); |
| let msb = msb.val(); |
| let mut x = 0u64; |
| for j in 0 .. input.len() { |
| let y = values[input[j] as usize]; |
| check!(j, y < 1 << bit); |
| x |= u64::from(y) << (bit * order(msb, dec(bit), j)); |
| } |
| for (j, output) in output.iter_mut().enumerate() { |
| *output = (x >> (8 * order(msb, enc(bit), j)) & 0xff) as u8; |
| } |
| Ok(()) |
| } |
| |
| // Fails if an input character does not translate to a symbol. The error `pos` |
| // is the lowest index of such character. The output is valid up to `pos / dec * |
| // enc` excluded. |
| fn decode_mut<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, values: &[u8; 256], input: &[u8], output: &mut [u8], |
| ) -> Result<(), usize> { |
| debug_assert_eq!(input.len(), encode_len(bit, output.len())); |
| let enc = enc(bit.val()); |
| let dec = dec(bit.val()); |
| let n = input.len() / dec; |
| for i in 0 .. n { |
| let input = unsafe { chunk_unchecked(input, dec, i) }; |
| let output = unsafe { chunk_mut_unchecked(output, enc, i) }; |
| decode_block(bit, msb, values, input, output).map_err(|e| dec * i + e)?; |
| } |
| decode_block(bit, msb, values, &input[dec * n ..], &mut output[enc * n ..]) |
| .map_err(|e| dec * n + e) |
| } |
| |
| // Fails if there are non-zero trailing bits. |
| fn check_trail<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, ctb: bool, values: &[u8; 256], input: &[u8], |
| ) -> Result<(), ()> { |
| if 8 % bit.val() == 0 || !ctb { |
| return Ok(()); |
| } |
| let trail = bit.val() * input.len() % 8; |
| if trail == 0 { |
| return Ok(()); |
| } |
| let mut mask = (1 << trail) - 1; |
| if !msb.val() { |
| mask <<= bit.val() - trail; |
| } |
| check!((), values[input[input.len() - 1] as usize] & mask == 0); |
| Ok(()) |
| } |
| |
| // Fails if the padding length is invalid. The error is the index of the first |
| // padding character. |
| fn check_pad<B: Static<usize>>(bit: B, values: &[u8; 256], input: &[u8]) -> Result<usize, usize> { |
| let bit = bit.val(); |
| debug_assert_eq!(input.len(), dec(bit)); |
| let is_pad = |x: &&u8| values[**x as usize] == PADDING; |
| let count = input.iter().rev().take_while(is_pad).count(); |
| let len = input.len() - count; |
| check!(len, len > 0 && bit * len % 8 < bit); |
| Ok(len) |
| } |
| |
| fn encode_base_len<B: Static<usize>>(bit: B, len: usize) -> usize { |
| encode_len(bit, len) |
| } |
| |
| fn encode_base<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, symbols: &[u8; 256], input: &[u8], output: &mut [u8], |
| ) { |
| debug_assert_eq!(output.len(), encode_base_len(bit, input.len())); |
| encode_mut(bit, msb, symbols, input, output); |
| } |
| |
| fn encode_pad_len<B: Static<usize>, P: Static<Option<u8>>>(bit: B, pad: P, len: usize) -> usize { |
| match pad.val() { |
| None => encode_base_len(bit, len), |
| Some(_) => div_ceil(len, enc(bit.val())) * dec(bit.val()), |
| } |
| } |
| |
| fn encode_pad<B: Static<usize>, M: Static<bool>, P: Static<Option<u8>>>( |
| bit: B, msb: M, symbols: &[u8; 256], spad: P, input: &[u8], output: &mut [u8], |
| ) { |
| let pad = match spad.val() { |
| None => return encode_base(bit, msb, symbols, input, output), |
| Some(pad) => pad, |
| }; |
| debug_assert_eq!(output.len(), encode_pad_len(bit, spad, input.len())); |
| let olen = encode_base_len(bit, input.len()); |
| encode_base(bit, msb, symbols, input, &mut output[.. olen]); |
| for output in output.iter_mut().skip(olen) { |
| *output = pad; |
| } |
| } |
| |
| fn encode_wrap_len< |
| 'a, |
| B: Static<usize>, |
| P: Static<Option<u8>>, |
| W: Static<Option<(usize, &'a [u8])>>, |
| >( |
| bit: B, pad: P, wrap: W, ilen: usize, |
| ) -> usize { |
| let olen = encode_pad_len(bit, pad, ilen); |
| match wrap.val() { |
| None => olen, |
| Some((col, end)) => olen + end.len() * div_ceil(olen, col), |
| } |
| } |
| |
| fn encode_wrap_mut< |
| 'a, |
| B: Static<usize>, |
| M: Static<bool>, |
| P: Static<Option<u8>>, |
| W: Static<Option<(usize, &'a [u8])>>, |
| >( |
| bit: B, msb: M, symbols: &[u8; 256], pad: P, wrap: W, input: &[u8], output: &mut [u8], |
| ) { |
| let (col, end) = match wrap.val() { |
| None => return encode_pad(bit, msb, symbols, pad, input, output), |
| Some((col, end)) => (col, end), |
| }; |
| debug_assert_eq!(output.len(), encode_wrap_len(bit, pad, wrap, input.len())); |
| debug_assert_eq!(col % dec(bit.val()), 0); |
| let col = col / dec(bit.val()); |
| let enc = col * enc(bit.val()); |
| let dec = col * dec(bit.val()) + end.len(); |
| let olen = dec - end.len(); |
| let n = input.len() / enc; |
| for i in 0 .. n { |
| let input = unsafe { chunk_unchecked(input, enc, i) }; |
| let output = unsafe { chunk_mut_unchecked(output, dec, i) }; |
| encode_base(bit, msb, symbols, input, &mut output[.. olen]); |
| output[olen ..].copy_from_slice(end); |
| } |
| if input.len() > enc * n { |
| let olen = dec * n + encode_pad_len(bit, pad, input.len() - enc * n); |
| encode_pad(bit, msb, symbols, pad, &input[enc * n ..], &mut output[dec * n .. olen]); |
| output[olen ..].copy_from_slice(end); |
| } |
| } |
| |
| // Returns the longest valid input length and associated output length. |
| fn decode_wrap_len<B: Static<usize>, P: Static<bool>>( |
| bit: B, pad: P, len: usize, |
| ) -> (usize, usize) { |
| let bit = bit.val(); |
| if pad.val() { |
| (floor(len, dec(bit)), len / dec(bit) * enc(bit)) |
| } else { |
| let trail = bit * len % 8; |
| (len - trail / bit, bit * len / 8) |
| } |
| } |
| |
| // Fails with Length if length is invalid. The error is the largest valid |
| // length. |
| fn decode_pad_len<B: Static<usize>, P: Static<bool>>( |
| bit: B, pad: P, len: usize, |
| ) -> Result<usize, DecodeError> { |
| let (ilen, olen) = decode_wrap_len(bit, pad, len); |
| check!(DecodeError { position: ilen, kind: DecodeKind::Length }, ilen == len); |
| Ok(olen) |
| } |
| |
| // Fails with Length if length is invalid. The error is the largest valid |
| // length. |
| fn decode_base_len<B: Static<usize>>(bit: B, len: usize) -> Result<usize, DecodeError> { |
| decode_pad_len(bit, Bf, len) |
| } |
| |
| // Fails with Symbol if an input character does not translate to a symbol. The |
| // error is the lowest index of such character. |
| // Fails with Trailing if there are non-zero trailing bits. |
| fn decode_base_mut<B: Static<usize>, M: Static<bool>>( |
| bit: B, msb: M, ctb: bool, values: &[u8; 256], input: &[u8], output: &mut [u8], |
| ) -> Result<usize, DecodePartial> { |
| debug_assert_eq!(Ok(output.len()), decode_base_len(bit, input.len())); |
| let fail = |pos, kind| DecodePartial { |
| read: pos / dec(bit.val()) * dec(bit.val()), |
| written: pos / dec(bit.val()) * enc(bit.val()), |
| error: DecodeError { position: pos, kind }, |
| }; |
| decode_mut(bit, msb, values, input, output).map_err(|pos| fail(pos, DecodeKind::Symbol))?; |
| check_trail(bit, msb, ctb, values, input) |
| .map_err(|()| fail(input.len() - 1, DecodeKind::Trailing))?; |
| Ok(output.len()) |
| } |
| |
| // Fails with Symbol if an input character does not translate to a symbol. The |
| // error is the lowest index of such character. |
| // Fails with Padding if some padding length is invalid. The error is the index |
| // of the first padding character of the invalid padding. |
| // Fails with Trailing if there are non-zero trailing bits. |
| fn decode_pad_mut<B: Static<usize>, M: Static<bool>, P: Static<bool>>( |
| bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, input: &[u8], output: &mut [u8], |
| ) -> Result<usize, DecodePartial> { |
| if !pad.val() { |
| return decode_base_mut(bit, msb, ctb, values, input, output); |
| } |
| debug_assert_eq!(Ok(output.len()), decode_pad_len(bit, pad, input.len())); |
| let enc = enc(bit.val()); |
| let dec = dec(bit.val()); |
| let mut inpos = 0; |
| let mut outpos = 0; |
| let mut outend = output.len(); |
| while inpos < input.len() { |
| match decode_base_mut( |
| bit, |
| msb, |
| ctb, |
| values, |
| &input[inpos ..], |
| &mut output[outpos .. outend], |
| ) { |
| Ok(written) => { |
| if cfg!(debug_assertions) { |
| inpos = input.len(); |
| } |
| outpos += written; |
| break; |
| } |
| Err(partial) => { |
| inpos += partial.read; |
| outpos += partial.written; |
| } |
| } |
| let inlen = |
| check_pad(bit, values, &input[inpos .. inpos + dec]).map_err(|pos| DecodePartial { |
| read: inpos, |
| written: outpos, |
| error: DecodeError { position: inpos + pos, kind: DecodeKind::Padding }, |
| })?; |
| let outlen = decode_base_len(bit, inlen).unwrap(); |
| let written = decode_base_mut( |
| bit, |
| msb, |
| ctb, |
| values, |
| &input[inpos .. inpos + inlen], |
| &mut output[outpos .. outpos + outlen], |
| ) |
| .map_err(|partial| { |
| debug_assert_eq!(partial.read, 0); |
| debug_assert_eq!(partial.written, 0); |
| DecodePartial { |
| read: inpos, |
| written: outpos, |
| error: DecodeError { |
| position: inpos + partial.error.position, |
| kind: partial.error.kind, |
| }, |
| } |
| })?; |
| debug_assert_eq!(written, outlen); |
| inpos += dec; |
| outpos += outlen; |
| outend -= enc - outlen; |
| } |
| debug_assert_eq!(inpos, input.len()); |
| debug_assert_eq!(outpos, outend); |
| Ok(outend) |
| } |
| |
| fn skip_ignore(values: &[u8; 256], input: &[u8], mut inpos: usize) -> usize { |
| while inpos < input.len() && values[input[inpos] as usize] == IGNORE { |
| inpos += 1; |
| } |
| inpos |
| } |
| |
| // Returns next input and output position. |
| // Fails with Symbol if an input character does not translate to a symbol. The |
| // error is the lowest index of such character. |
| // Fails with Padding if some padding length is invalid. The error is the index |
| // of the first padding character of the invalid padding. |
| // Fails with Trailing if there are non-zero trailing bits. |
| fn decode_wrap_block<B: Static<usize>, M: Static<bool>, P: Static<bool>>( |
| bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, input: &[u8], output: &mut [u8], |
| ) -> Result<(usize, usize), DecodeError> { |
| let dec = dec(bit.val()); |
| let mut buf = [0u8; 8]; |
| let mut shift = [0usize; 8]; |
| let mut bufpos = 0; |
| let mut inpos = 0; |
| while bufpos < dec { |
| inpos = skip_ignore(values, input, inpos); |
| if inpos == input.len() { |
| break; |
| } |
| shift[bufpos] = inpos; |
| buf[bufpos] = input[inpos]; |
| bufpos += 1; |
| inpos += 1; |
| } |
| let olen = decode_pad_len(bit, pad, bufpos).map_err(|mut e| { |
| e.position = shift[e.position]; |
| e |
| })?; |
| let written = decode_pad_mut(bit, msb, ctb, values, pad, &buf[.. bufpos], &mut output[.. olen]) |
| .map_err(|partial| { |
| debug_assert_eq!(partial.read, 0); |
| debug_assert_eq!(partial.written, 0); |
| DecodeError { position: shift[partial.error.position], kind: partial.error.kind } |
| })?; |
| Ok((inpos, written)) |
| } |
| |
| // Fails with Symbol if an input character does not translate to a symbol. The |
| // error is the lowest index of such character. |
| // Fails with Padding if some padding length is invalid. The error is the index |
| // of the first padding character of the invalid padding. |
| // Fails with Trailing if there are non-zero trailing bits. |
| // Fails with Length if input length (without ignored characters) is invalid. |
| #[allow(clippy::too_many_arguments)] |
| fn decode_wrap_mut<B: Static<usize>, M: Static<bool>, P: Static<bool>, I: Static<bool>>( |
| bit: B, msb: M, ctb: bool, values: &[u8; 256], pad: P, has_ignore: I, input: &[u8], |
| output: &mut [u8], |
| ) -> Result<usize, DecodePartial> { |
| if !has_ignore.val() { |
| return decode_pad_mut(bit, msb, ctb, values, pad, input, output); |
| } |
| debug_assert_eq!(output.len(), decode_wrap_len(bit, pad, input.len()).1); |
| let mut inpos = 0; |
| let mut outpos = 0; |
| while inpos < input.len() { |
| let (inlen, outlen) = decode_wrap_len(bit, pad, input.len() - inpos); |
| match decode_pad_mut( |
| bit, |
| msb, |
| ctb, |
| values, |
| pad, |
| &input[inpos .. inpos + inlen], |
| &mut output[outpos .. outpos + outlen], |
| ) { |
| Ok(written) => { |
| inpos += inlen; |
| outpos += written; |
| break; |
| } |
| Err(partial) => { |
| inpos += partial.read; |
| outpos += partial.written; |
| } |
| } |
| let (ipos, opos) = |
| decode_wrap_block(bit, msb, ctb, values, pad, &input[inpos ..], &mut output[outpos ..]) |
| .map_err(|mut error| { |
| error.position += inpos; |
| DecodePartial { read: inpos, written: outpos, error } |
| })?; |
| inpos += ipos; |
| outpos += opos; |
| } |
| let inpos = skip_ignore(values, input, inpos); |
| if inpos == input.len() { |
| Ok(outpos) |
| } else { |
| Err(DecodePartial { |
| read: inpos, |
| written: outpos, |
| error: DecodeError { position: inpos, kind: DecodeKind::Length }, |
| }) |
| } |
| } |
| |
| /// Order in which bits are read from a byte |
| /// |
| /// The base-conversion encoding is always little-endian. This means that the least significant |
| /// **byte** is always first. However, we can still choose whether, within a byte, this is the most |
| /// significant or the least significant **bit** that is first. If the terminology is confusing, |
| /// testing on an asymmetrical example should be enough to choose the correct value. |
| /// |
| /// # Examples |
| /// |
| /// In the following example, we can see that a base with the `MostSignificantFirst` bit-order has |
| /// the most significant bit first in the encoded output. In particular, the output is in the same |
| /// order as the bits in the byte. The opposite happens with the `LeastSignificantFirst` bit-order. |
| /// The least significant bit is first and the output is in the reverse order. |
| /// |
| /// ```rust |
| /// use data_encoding::{BitOrder, Specification}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("01"); |
| /// spec.bit_order = BitOrder::MostSignificantFirst; // default |
| /// let msb = spec.encoding().unwrap(); |
| /// spec.bit_order = BitOrder::LeastSignificantFirst; |
| /// let lsb = spec.encoding().unwrap(); |
| /// assert_eq!(msb.encode(&[0b01010011]), "01010011"); |
| /// assert_eq!(lsb.encode(&[0b01010011]), "11001010"); |
| /// ``` |
| #[derive(Debug, Copy, Clone, PartialEq, Eq)] |
| #[cfg(feature = "alloc")] |
| pub enum BitOrder { |
| /// Most significant bit first |
| /// |
| /// This is the most common and most intuitive bit-order. In particular, this is the bit-order |
| /// used by [RFC4648] and thus the usual hexadecimal, base64, base32, base64url, and base32hex |
| /// encodings. This is the default bit-order when [specifying](struct.Specification.html) a |
| /// base. |
| /// |
| /// [RFC4648]: https://tools.ietf.org/html/rfc4648 |
| MostSignificantFirst, |
| |
| /// Least significant bit first |
| /// |
| /// # Examples |
| /// |
| /// DNSCurve [base32] uses least significant bit first: |
| /// |
| /// ```rust |
| /// use data_encoding::BASE32_DNSCURVE; |
| /// assert_eq!(BASE32_DNSCURVE.encode(&[0x64, 0x88]), "4321"); |
| /// assert_eq!(BASE32_DNSCURVE.decode(b"4321").unwrap(), vec![0x64, 0x88]); |
| /// ``` |
| /// |
| /// [base32]: constant.BASE32_DNSCURVE.html |
| LeastSignificantFirst, |
| } |
| #[cfg(feature = "alloc")] |
| use crate::BitOrder::*; |
| |
| #[doc(hidden)] |
| #[cfg(feature = "alloc")] |
| pub type InternalEncoding = Cow<'static, [u8]>; |
| |
| #[doc(hidden)] |
| #[cfg(not(feature = "alloc"))] |
| pub type InternalEncoding = &'static [u8]; |
| |
| /// Base-conversion encoding |
| /// |
| /// See [Specification](struct.Specification.html) for technical details or how to define a new one. |
| // Required fields: |
| // 0 - 256 (256) symbols |
| // 256 - 512 (256) values |
| // 512 - 513 ( 1) padding |
| // 513 - 514 ( 1) reserved(3),ctb(1),msb(1),bit(3) |
| // Optional fields: |
| // 514 - 515 ( 1) width |
| // 515 - * ( N) separator |
| // Invariants: |
| // - symbols is 2^bit unique characters repeated 2^(8-bit) times |
| // - values[128 ..] are INVALID |
| // - values[0 .. 128] are either INVALID, IGNORE, PADDING, or < 2^bit |
| // - padding is either < 128 or INVALID |
| // - values[padding] is PADDING if padding < 128 |
| // - values and symbols are inverse |
| // - ctb is true if 8 % bit == 0 |
| // - width is present if there is x such that values[x] is IGNORE |
| // - width % dec(bit) == 0 |
| // - for all x in separator values[x] is IGNORE |
| #[derive(Debug, Clone, PartialEq, Eq)] |
| pub struct Encoding(#[doc(hidden)] pub InternalEncoding); |
| |
| /// How to translate characters when decoding |
| /// |
| /// The order matters. The first character of the `from` field is translated to the first character |
| /// of the `to` field. The second to the second. Etc. |
| /// |
| /// See [Specification](struct.Specification.html) for more information. |
| #[derive(Debug, Clone)] |
| #[cfg(feature = "alloc")] |
| pub struct Translate { |
| /// Characters to translate from |
| pub from: String, |
| |
| /// Characters to translate to |
| pub to: String, |
| } |
| |
| /// How to wrap the output when encoding |
| /// |
| /// See [Specification](struct.Specification.html) for more information. |
| #[derive(Debug, Clone)] |
| #[cfg(feature = "alloc")] |
| pub struct Wrap { |
| /// Wrapping width |
| /// |
| /// Must be a multiple of: |
| /// |
| /// - 8 for a bit-width of 1 (binary), 3 (octal), and 5 (base32) |
| /// - 4 for a bit-width of 2 (base4) and 6 (base64) |
| /// - 2 for a bit-width of 4 (hexadecimal) |
| /// |
| /// Wrapping is disabled if null. |
| pub width: usize, |
| |
| /// Wrapping characters |
| /// |
| /// Wrapping is disabled if empty. |
| pub separator: String, |
| } |
| |
| /// Base-conversion specification |
| /// |
| /// It is possible to define custom encodings given a specification. To do so, it is important to |
| /// understand the theory first. |
| /// |
| /// # Theory |
| /// |
| /// Each subsection has an equivalent subsection in the [Practice](#practice) section. |
| /// |
| /// ## Basics |
| /// |
| /// The main idea of a [base-conversion] encoding is to see `[u8]` as numbers written in |
| /// little-endian base256 and convert them in another little-endian base. For performance reasons, |
| /// this crate restricts this other base to be of size 2 (binary), 4 (base4), 8 (octal), 16 |
| /// (hexadecimal), 32 (base32), or 64 (base64). The converted number is written as `[u8]` although |
| /// it doesn't use all the 256 possible values of `u8`. This crate encodes to ASCII, so only values |
| /// smaller than 128 are allowed. |
| /// |
| /// More precisely, we need the following elements: |
| /// |
| /// - The bit-width N: 1 for binary, 2 for base4, 3 for octal, 4 for hexadecimal, 5 for base32, and |
| /// 6 for base64 |
| /// - The [bit-order](enum.BitOrder.html): most or least significant bit first |
| /// - The symbols function S from [0, 2<sup>N</sup>) (called values and written `uN`) to symbols |
| /// (represented as `u8` although only ASCII symbols are allowed, i.e. smaller than 128) |
| /// - The values partial function V from ASCII to [0, 2<sup>N</sup>), i.e. from `u8` to `uN` |
| /// - Whether trailing bits are checked: trailing bits are leading zeros in theory, but since |
| /// numbers are little-endian they come last |
| /// |
| /// For the encoding to be correct (i.e. encoding then decoding gives back the initial input), |
| /// V(S(i)) must be defined and equal to i for all i in [0, 2<sup>N</sup>). For the encoding to be |
| /// [canonical][canonical] (i.e. different inputs decode to different outputs, or equivalently, |
| /// decoding then encoding gives back the initial input), trailing bits must be checked and if V(i) |
| /// is defined then S(V(i)) is equal to i for all i. |
| /// |
| /// Encoding and decoding are given by the following pipeline: |
| /// |
| /// ```text |
| /// [u8] <--1--> [[bit; 8]] <--2--> [[bit; N]] <--3--> [uN] <--4--> [u8] |
| /// 1: Map bit-order between each u8 and [bit; 8] |
| /// 2: Base conversion between base 2^8 and base 2^N (check trailing bits) |
| /// 3: Map bit-order between each [bit; N] and uN |
| /// 4: Map symbols/values between each uN and u8 (values must be defined) |
| /// ``` |
| /// |
| /// ## Extensions |
| /// |
| /// All these extensions make the encoding not canonical. |
| /// |
| /// ### Padding |
| /// |
| /// Padding is useful if the following conditions are met: |
| /// |
| /// - the bit-width is 3 (octal), 5 (base32), or 6 (base64) |
| /// - the length of the data to encode is not known in advance |
| /// - the data must be sent without buffering |
| /// |
| /// Bases for which the bit-width N does not divide 8 may not concatenate encoded data. This comes |
| /// from the fact that it is not possible to make the difference between trailing bits and encoding |
| /// bits. Padding solves this issue by adding a new character to discriminate between trailing bits |
| /// and encoding bits. The idea is to work by blocks of lcm(8, N) bits, where lcm(8, N) is the least |
| /// common multiple of 8 and N. When such block is not complete, it is padded. |
| /// |
| /// To preserve correctness, the padding character must not be a symbol. |
| /// |
| /// ### Ignore characters when decoding |
| /// |
| /// Ignoring characters when decoding is useful if after encoding some characters are added for |
| /// convenience or any other reason (like wrapping). In that case we want to first ignore those |
| /// characters before decoding. |
| /// |
| /// To preserve correctness, ignored characters must not contain symbols or the padding character. |
| /// |
| /// ### Wrap output when encoding |
| /// |
| /// Wrapping output when encoding is useful if the output is meant to be printed in a document where |
| /// width is limited (typically 80-columns documents). In that case, the wrapping width and the |
| /// wrapping separator have to be defined. |
| /// |
| /// To preserve correctness, the wrapping separator characters must be ignored (see previous |
| /// subsection). As such, wrapping separator characters must also not contain symbols or the padding |
| /// character. |
| /// |
| /// ### Translate characters when decoding |
| /// |
| /// Translating characters when decoding is useful when encoded data may be copied by a humain |
| /// instead of a machine. Humans tend to confuse some characters for others. In that case we want to |
| /// translate those characters before decoding. |
| /// |
| /// To preserve correctness, the characters we translate _from_ must not contain symbols or the |
| /// padding character, and the characters we translate _to_ must only contain symbols or the padding |
| /// character. |
| /// |
| /// # Practice |
| /// |
| /// ## Basics |
| /// |
| /// ```rust |
| /// use data_encoding::{Encoding, Specification}; |
| /// fn make_encoding(symbols: &str) -> Encoding { |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str(symbols); |
| /// spec.encoding().unwrap() |
| /// } |
| /// let binary = make_encoding("01"); |
| /// let octal = make_encoding("01234567"); |
| /// let hexadecimal = make_encoding("0123456789abcdef"); |
| /// assert_eq!(binary.encode(b"Bit"), "010000100110100101110100"); |
| /// assert_eq!(octal.encode(b"Bit"), "20464564"); |
| /// assert_eq!(hexadecimal.encode(b"Bit"), "426974"); |
| /// ``` |
| /// |
| /// The `binary` base has 2 symbols `0` and `1` with value 0 and 1 respectively. The `octal` base |
| /// has 8 symbols `0` to `7` with value 0 to 7. The `hexadecimal` base has 16 symbols `0` to `9` and |
| /// `a` to `f` with value 0 to 15. The following diagram gives the idea of how encoding works in the |
| /// previous example (note that we can actually write such diagram only because the bit-order is |
| /// most significant first): |
| /// |
| /// ```text |
| /// [ octal] | 2 : 0 : 4 : 6 : 4 : 5 : 6 : 4 | |
| /// [ binary] |0 1 0 0 0 0 1 0|0 1 1 0 1 0 0 1|0 1 1 1 0 1 0 0| |
| /// [hexadecimal] | 4 : 2 | 6 : 9 | 7 : 4 | |
| /// ^-- LSB ^-- MSB |
| /// ``` |
| /// |
| /// Note that in theory, these little-endian numbers are read from right to left (the most |
| /// significant bit is at the right). Since leading zeros are meaningless (in our usual decimal |
| /// notation 0123 is the same as 123), it explains why trailing bits must be zero. Trailing bits may |
| /// occur when the bit-width of a base does not divide 8. Only binary, base4, and hexadecimal don't |
| /// have trailing bits issues. So let's consider octal and base64, which have trailing bits in |
| /// similar circumstances: |
| /// |
| /// ```rust |
| /// use data_encoding::{Specification, BASE64_NOPAD}; |
| /// let octal = { |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("01234567"); |
| /// spec.encoding().unwrap() |
| /// }; |
| /// assert_eq!(BASE64_NOPAD.encode(b"B"), "Qg"); |
| /// assert_eq!(octal.encode(b"B"), "204"); |
| /// ``` |
| /// |
| /// We have the following diagram, where the base64 values are written between parentheses: |
| /// |
| /// ```text |
| /// [base64] | Q(16) : g(32) : [has 4 zero trailing bits] |
| /// [ octal] | 2 : 0 : 4 : [has 1 zero trailing bit ] |
| /// |0 1 0 0 0 0 1 0|0 0 0 0 |
| /// [ ascii] | B | |
| /// ^-^-^-^-- leading zeros / trailing bits |
| /// ``` |
| /// |
| /// ## Extensions |
| /// |
| /// ### Padding |
| /// |
| /// For octal and base64, lcm(8, 3) == lcm(8, 6) == 24 bits or 3 bytes. For base32, lcm(8, 5) is 40 |
| /// bits or 5 bytes. Let's consider octal and base64: |
| /// |
| /// ```rust |
| /// use data_encoding::{Specification, BASE64}; |
| /// let octal = { |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("01234567"); |
| /// spec.padding = Some('='); |
| /// spec.encoding().unwrap() |
| /// }; |
| /// // We start encoding but we only have "B" for now. |
| /// assert_eq!(BASE64.encode(b"B"), "Qg=="); |
| /// assert_eq!(octal.encode(b"B"), "204====="); |
| /// // Now we have "it". |
| /// assert_eq!(BASE64.encode(b"it"), "aXQ="); |
| /// assert_eq!(octal.encode(b"it"), "322720=="); |
| /// // By concatenating everything, we may decode the original data. |
| /// assert_eq!(BASE64.decode(b"Qg==aXQ=").unwrap(), b"Bit"); |
| /// assert_eq!(octal.decode(b"204=====322720==").unwrap(), b"Bit"); |
| /// ``` |
| /// |
| /// We have the following diagrams: |
| /// |
| /// ```text |
| /// [base64] | Q(16) : g(32) : = : = | |
| /// [ octal] | 2 : 0 : 4 : = : = : = : = : = | |
| /// |0 1 0 0 0 0 1 0|. . . . . . . .|. . . . . . . .| |
| /// [ ascii] | B | end of block aligned --^ |
| /// ^-- beginning of block aligned |
| /// |
| /// [base64] | a(26) : X(23) : Q(16) : = | |
| /// [ octal] | 3 : 2 : 2 : 7 : 2 : 0 : = : = | |
| /// |0 1 1 0 1 0 0 1|0 1 1 1 0 1 0 0|. . . . . . . .| |
| /// [ ascii] | i | t | |
| /// ``` |
| /// |
| /// ### Ignore characters when decoding |
| /// |
| /// The typical use-case is to ignore newlines (`\r` and `\n`). But to keep the example small, we |
| /// will ignore spaces. |
| /// |
| /// ```rust |
| /// let mut spec = data_encoding::HEXLOWER.specification(); |
| /// spec.ignore.push_str(" \t"); |
| /// let base = spec.encoding().unwrap(); |
| /// assert_eq!(base.decode(b"42 69 74"), base.decode(b"426974")); |
| /// ``` |
| /// |
| /// ### Wrap output when encoding |
| /// |
| /// The typical use-case is to wrap after 64 or 76 characters with a newline (`\r\n` or `\n`). But |
| /// to keep the example small, we will wrap after 8 characters with a space. |
| /// |
| /// ```rust |
| /// let mut spec = data_encoding::BASE64.specification(); |
| /// spec.wrap.width = 8; |
| /// spec.wrap.separator.push_str(" "); |
| /// let base64 = spec.encoding().unwrap(); |
| /// assert_eq!(base64.encode(b"Hey you"), "SGV5IHlv dQ== "); |
| /// ``` |
| /// |
| /// Note that the output always ends with the separator. |
| /// |
| /// ### Translate characters when decoding |
| /// |
| /// The typical use-case is to translate lowercase to uppercase or reciprocally, but it is also used |
| /// for letters that look alike, like `O0` or `Il1`. Let's illustrate both examples. |
| /// |
| /// ```rust |
| /// let mut spec = data_encoding::HEXLOWER.specification(); |
| /// spec.translate.from.push_str("ABCDEFOIl"); |
| /// spec.translate.to.push_str("abcdef011"); |
| /// let base = spec.encoding().unwrap(); |
| /// assert_eq!(base.decode(b"BOIl"), base.decode(b"b011")); |
| /// ``` |
| /// |
| /// [base-conversion]: https://en.wikipedia.org/wiki/Positional_notation#Base_conversion |
| /// [canonical]: https://tools.ietf.org/html/rfc4648#section-3.5 |
| #[derive(Debug, Clone)] |
| #[cfg(feature = "alloc")] |
| pub struct Specification { |
| /// Symbols |
| /// |
| /// The number of symbols must be 2, 4, 8, 16, 32, or 64. Symbols must be ASCII characters |
| /// (smaller than 128) and they must be unique. |
| pub symbols: String, |
| |
| /// Bit-order |
| /// |
| /// The default is to use most significant bit first since it is the most common. |
| pub bit_order: BitOrder, |
| |
| /// Check trailing bits |
| /// |
| /// The default is to check trailing bits. This field is ignored when unnecessary (i.e. for |
| /// base2, base4, and base16). |
| pub check_trailing_bits: bool, |
| |
| /// Padding |
| /// |
| /// The default is to not use padding. The padding character must be ASCII and must not be a |
| /// symbol. |
| pub padding: Option<char>, |
| |
| /// Characters to ignore when decoding |
| /// |
| /// The default is to not ignore characters when decoding. The characters to ignore must be |
| /// ASCII and must not be symbols or the padding character. |
| pub ignore: String, |
| |
| /// How to wrap the output when encoding |
| /// |
| /// The default is to not wrap the output when encoding. The wrapping characters must be ASCII |
| /// and must not be symbols or the padding character. |
| pub wrap: Wrap, |
| |
| /// How to translate characters when decoding |
| /// |
| /// The default is to not translate characters when decoding. The characters to translate from |
| /// must be ASCII and must not have already been assigned a semantics. The characters to |
| /// translate to must be ASCII and must have been assigned a semantics (symbol, padding |
| /// character, or ignored character). |
| pub translate: Translate, |
| } |
| |
| #[cfg(feature = "alloc")] |
| impl Default for Specification { |
| fn default() -> Self { |
| Self::new() |
| } |
| } |
| |
| impl Encoding { |
| fn sym(&self) -> &[u8; 256] { |
| self.0[0 .. 256].try_into().unwrap() |
| } |
| |
| fn val(&self) -> &[u8; 256] { |
| self.0[256 .. 512].try_into().unwrap() |
| } |
| |
| fn pad(&self) -> Option<u8> { |
| if self.0[512] < 128 { |
| Some(self.0[512]) |
| } else { |
| None |
| } |
| } |
| |
| fn ctb(&self) -> bool { |
| self.0[513] & 0x10 != 0 |
| } |
| |
| fn msb(&self) -> bool { |
| self.0[513] & 0x8 != 0 |
| } |
| |
| fn bit(&self) -> usize { |
| (self.0[513] & 0x7) as usize |
| } |
| |
| /// Minimum number of input and output blocks when encoding |
| fn block_len(&self) -> (usize, usize) { |
| let bit = self.bit(); |
| match self.wrap() { |
| Some((col, end)) => (col / dec(bit) * enc(bit), col + end.len()), |
| None => (enc(bit), dec(bit)), |
| } |
| } |
| |
| fn wrap(&self) -> Option<(usize, &[u8])> { |
| if self.0.len() <= 515 { |
| return None; |
| } |
| Some((self.0[514] as usize, &self.0[515 ..])) |
| } |
| |
| fn has_ignore(&self) -> bool { |
| self.0.len() >= 515 |
| } |
| |
| /// Returns the encoded length of an input of length `len` |
| /// |
| /// See [`encode_mut`] for when to use it. |
| /// |
| /// [`encode_mut`]: struct.Encoding.html#method.encode_mut |
| #[must_use] |
| pub fn encode_len(&self, len: usize) -> usize { |
| dispatch! { |
| let bit: usize = self.bit(); |
| let pad: Option<u8> = self.pad(); |
| let wrap: Option<(usize, &[u8])> = self.wrap(); |
| encode_wrap_len(bit, pad, wrap, len) |
| } |
| } |
| |
| /// Encodes `input` in `output` |
| /// |
| /// # Panics |
| /// |
| /// Panics if the `output` length does not match the result of [`encode_len`] for the `input` |
| /// length. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::BASE64; |
| /// # let mut buffer = vec![0; 100]; |
| /// let input = b"Hello world"; |
| /// let output = &mut buffer[0 .. BASE64.encode_len(input.len())]; |
| /// BASE64.encode_mut(input, output); |
| /// assert_eq!(output, b"SGVsbG8gd29ybGQ="); |
| /// ``` |
| /// |
| /// [`encode_len`]: struct.Encoding.html#method.encode_len |
| #[allow(clippy::cognitive_complexity)] |
| pub fn encode_mut(&self, input: &[u8], output: &mut [u8]) { |
| assert_eq!(output.len(), self.encode_len(input.len())); |
| dispatch! { |
| let bit: usize = self.bit(); |
| let msb: bool = self.msb(); |
| let pad: Option<u8> = self.pad(); |
| let wrap: Option<(usize, &[u8])> = self.wrap(); |
| encode_wrap_mut(bit, msb, self.sym(), pad, wrap, input, output) |
| } |
| } |
| |
| /// Appends the encoding of `input` to `output` |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::BASE64; |
| /// # let mut buffer = vec![0; 100]; |
| /// let input = b"Hello world"; |
| /// let mut output = "Result: ".to_string(); |
| /// BASE64.encode_append(input, &mut output); |
| /// assert_eq!(output, "Result: SGVsbG8gd29ybGQ="); |
| /// ``` |
| #[cfg(feature = "alloc")] |
| pub fn encode_append(&self, input: &[u8], output: &mut String) { |
| let output = unsafe { output.as_mut_vec() }; |
| let output_len = output.len(); |
| output.resize(output_len + self.encode_len(input.len()), 0u8); |
| self.encode_mut(input, &mut output[output_len ..]); |
| } |
| |
| /// Returns an object to encode a fragmented input and append it to `output` |
| /// |
| /// See the documentation of [`Encoder`] for more details and examples. |
| #[cfg(feature = "alloc")] |
| pub fn new_encoder<'a>(&'a self, output: &'a mut String) -> Encoder<'a> { |
| Encoder::new(self, output) |
| } |
| |
| /// Writes the encoding of `input` to `output` |
| /// |
| /// This allocates a buffer of 1024 bytes on the stack. If you want to control the buffer size |
| /// and location, use [`Encoding::encode_write_buffer()`] instead. |
| /// |
| /// # Errors |
| /// |
| /// Returns an error when writing to the output fails. |
| pub fn encode_write( |
| &self, input: &[u8], output: &mut impl core::fmt::Write, |
| ) -> core::fmt::Result { |
| self.encode_write_buffer(input, output, &mut [0; 1024]) |
| } |
| |
| /// Writes the encoding of `input` to `output` using a temporary `buffer` |
| /// |
| /// # Panics |
| /// |
| /// Panics if the buffer is shorter than 510 bytes. |
| /// |
| /// # Errors |
| /// |
| /// Returns an error when writing to the output fails. |
| pub fn encode_write_buffer( |
| &self, input: &[u8], output: &mut impl core::fmt::Write, buffer: &mut [u8], |
| ) -> core::fmt::Result { |
| assert!(510 <= buffer.len()); |
| let (enc, dec) = self.block_len(); |
| for input in input.chunks(buffer.len() / dec * enc) { |
| let buffer = &mut buffer[.. self.encode_len(input.len())]; |
| self.encode_mut(input, buffer); |
| output.write_str(unsafe { core::str::from_utf8_unchecked(buffer) })?; |
| } |
| Ok(()) |
| } |
| |
| /// Returns encoded `input` |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::BASE64; |
| /// assert_eq!(BASE64.encode(b"Hello world"), "SGVsbG8gd29ybGQ="); |
| /// ``` |
| #[cfg(feature = "alloc")] |
| #[must_use] |
| pub fn encode(&self, input: &[u8]) -> String { |
| let mut output = vec![0u8; self.encode_len(input.len())]; |
| self.encode_mut(input, &mut output); |
| unsafe { String::from_utf8_unchecked(output) } |
| } |
| |
| /// Returns the decoded length of an input of length `len` |
| /// |
| /// See [`decode_mut`] for when to use it. |
| /// |
| /// # Errors |
| /// |
| /// Returns an error if `len` is invalid. The error kind is [`Length`] and the [position] is the |
| /// greatest valid input length. |
| /// |
| /// [`decode_mut`]: struct.Encoding.html#method.decode_mut |
| /// [`Length`]: enum.DecodeKind.html#variant.Length |
| /// [position]: struct.DecodeError.html#structfield.position |
| pub fn decode_len(&self, len: usize) -> Result<usize, DecodeError> { |
| let (ilen, olen) = dispatch! { |
| let bit: usize = self.bit(); |
| let pad: bool = self.pad().is_some(); |
| decode_wrap_len(bit, pad, len) |
| }; |
| check!( |
| DecodeError { position: ilen, kind: DecodeKind::Length }, |
| self.has_ignore() || len == ilen |
| ); |
| Ok(olen) |
| } |
| |
| /// Decodes `input` in `output` |
| /// |
| /// Returns the length of the decoded output. This length may be smaller than the output length |
| /// if the input contained padding or ignored characters. The output bytes after the returned |
| /// length are not initialized and should not be read. |
| /// |
| /// # Panics |
| /// |
| /// Panics if the `output` length does not match the result of [`decode_len`] for the `input` |
| /// length. Also panics if `decode_len` fails for the `input` length. |
| /// |
| /// # Errors |
| /// |
| /// Returns an error if `input` is invalid. See [`decode`] for more details. The are two |
| /// differences though: |
| /// |
| /// - [`Length`] may be returned only if the encoding allows ignored characters, because |
| /// otherwise this is already checked by [`decode_len`]. |
| /// - The [`read`] first bytes of the input have been successfully decoded to the [`written`] |
| /// first bytes of the output. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::BASE64; |
| /// # let mut buffer = vec![0; 100]; |
| /// let input = b"SGVsbA==byB3b3JsZA=="; |
| /// let output = &mut buffer[0 .. BASE64.decode_len(input.len()).unwrap()]; |
| /// let len = BASE64.decode_mut(input, output).unwrap(); |
| /// assert_eq!(&output[0 .. len], b"Hello world"); |
| /// ``` |
| /// |
| /// [`decode_len`]: struct.Encoding.html#method.decode_len |
| /// [`decode`]: struct.Encoding.html#method.decode |
| /// [`Length`]: enum.DecodeKind.html#variant.Length |
| /// [`read`]: struct.DecodePartial.html#structfield.read |
| /// [`written`]: struct.DecodePartial.html#structfield.written |
| #[allow(clippy::cognitive_complexity)] |
| pub fn decode_mut(&self, input: &[u8], output: &mut [u8]) -> Result<usize, DecodePartial> { |
| assert_eq!(Ok(output.len()), self.decode_len(input.len())); |
| dispatch! { |
| let bit: usize = self.bit(); |
| let msb: bool = self.msb(); |
| let pad: bool = self.pad().is_some(); |
| let has_ignore: bool = self.has_ignore(); |
| decode_wrap_mut(bit, msb, self.ctb(), self.val(), pad, has_ignore, |
| input, output) |
| } |
| } |
| |
| /// Returns decoded `input` |
| /// |
| /// # Errors |
| /// |
| /// Returns an error if `input` is invalid. The error kind can be: |
| /// |
| /// - [`Length`] if the input length is invalid. The [position] is the greatest valid input |
| /// length. |
| /// - [`Symbol`] if the input contains an invalid character. The [position] is the first invalid |
| /// character. |
| /// - [`Trailing`] if the input has non-zero trailing bits. This is only possible if the |
| /// encoding checks trailing bits. The [position] is the first character containing non-zero |
| /// trailing bits. |
| /// - [`Padding`] if the input has an invalid padding length. This is only possible if the |
| /// encoding uses padding. The [position] is the first padding character of the first padding |
| /// of invalid length. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::BASE64; |
| /// assert_eq!(BASE64.decode(b"SGVsbA==byB3b3JsZA==").unwrap(), b"Hello world"); |
| /// ``` |
| /// |
| /// [`Length`]: enum.DecodeKind.html#variant.Length |
| /// [`Symbol`]: enum.DecodeKind.html#variant.Symbol |
| /// [`Trailing`]: enum.DecodeKind.html#variant.Trailing |
| /// [`Padding`]: enum.DecodeKind.html#variant.Padding |
| /// [position]: struct.DecodeError.html#structfield.position |
| #[cfg(feature = "alloc")] |
| pub fn decode(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError> { |
| let mut output = vec![0u8; self.decode_len(input.len())?]; |
| let len = self.decode_mut(input, &mut output).map_err(|partial| partial.error)?; |
| output.truncate(len); |
| Ok(output) |
| } |
| |
| /// Returns the bit-width |
| #[must_use] |
| pub fn bit_width(&self) -> usize { |
| self.bit() |
| } |
| |
| /// Returns whether the encoding is canonical |
| /// |
| /// An encoding is not canonical if one of the following conditions holds: |
| /// |
| /// - trailing bits are not checked |
| /// - padding is used |
| /// - characters are ignored |
| /// - characters are translated |
| #[must_use] |
| pub fn is_canonical(&self) -> bool { |
| if !self.ctb() { |
| return false; |
| } |
| let bit = self.bit(); |
| let sym = self.sym(); |
| let val = self.val(); |
| for i in 0 .. 256 { |
| if val[i] == INVALID { |
| continue; |
| } |
| if val[i] >= 1 << bit { |
| return false; |
| } |
| if sym[val[i] as usize] as usize != i { |
| return false; |
| } |
| } |
| true |
| } |
| |
| /// Returns the encoding specification |
| #[allow(clippy::missing_panics_doc)] // no panic |
| #[cfg(feature = "alloc")] |
| #[must_use] |
| pub fn specification(&self) -> Specification { |
| let mut specification = Specification::new(); |
| specification |
| .symbols |
| .push_str(core::str::from_utf8(&self.sym()[0 .. 1 << self.bit()]).unwrap()); |
| specification.bit_order = |
| if self.msb() { MostSignificantFirst } else { LeastSignificantFirst }; |
| specification.check_trailing_bits = self.ctb(); |
| if let Some(pad) = self.pad() { |
| specification.padding = Some(pad as char); |
| } |
| for i in 0 .. 128u8 { |
| if self.val()[i as usize] != IGNORE { |
| continue; |
| } |
| specification.ignore.push(i as char); |
| } |
| if let Some((col, end)) = self.wrap() { |
| specification.wrap.width = col; |
| specification.wrap.separator = core::str::from_utf8(end).unwrap().to_owned(); |
| } |
| for i in 0 .. 128u8 { |
| let canonical = if self.val()[i as usize] < 1 << self.bit() { |
| self.sym()[self.val()[i as usize] as usize] |
| } else if self.val()[i as usize] == PADDING { |
| self.pad().unwrap() |
| } else { |
| continue; |
| }; |
| if i == canonical { |
| continue; |
| } |
| specification.translate.from.push(i as char); |
| specification.translate.to.push(canonical as char); |
| } |
| specification |
| } |
| |
| #[doc(hidden)] |
| #[must_use] |
| pub const fn internal_new(implementation: &'static [u8]) -> Encoding { |
| #[cfg(feature = "alloc")] |
| let encoding = Encoding(Cow::Borrowed(implementation)); |
| #[cfg(not(feature = "alloc"))] |
| let encoding = Encoding(implementation); |
| encoding |
| } |
| |
| #[doc(hidden)] |
| #[must_use] |
| pub fn internal_implementation(&self) -> &[u8] { |
| &self.0 |
| } |
| } |
| |
| /// Encodes fragmented input to an output |
| /// |
| /// It is equivalent to use an [`Encoder`] with multiple calls to [`Encoder::append()`] than to |
| /// first concatenate all the input and then use [`Encoding::encode_append()`]. In particular, this |
| /// function will not introduce padding or wrapping between inputs. |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// // This is a bit inconvenient but we can't take a long-term reference to data_encoding::BASE64 |
| /// // because it's a constant. We need to use a static which has an address instead. This will be |
| /// // fixed in version 3 of the library. |
| /// static BASE64: data_encoding::Encoding = data_encoding::BASE64; |
| /// let mut output = String::new(); |
| /// let mut encoder = BASE64.new_encoder(&mut output); |
| /// encoder.append(b"hello"); |
| /// encoder.append(b"world"); |
| /// encoder.finalize(); |
| /// assert_eq!(output, BASE64.encode(b"helloworld")); |
| /// ``` |
| #[derive(Debug)] |
| #[cfg(feature = "alloc")] |
| pub struct Encoder<'a> { |
| encoding: &'a Encoding, |
| output: &'a mut String, |
| buffer: [u8; 255], |
| length: u8, |
| } |
| |
| #[cfg(feature = "alloc")] |
| impl<'a> Drop for Encoder<'a> { |
| fn drop(&mut self) { |
| self.encoding.encode_append(&self.buffer[.. self.length as usize], self.output); |
| } |
| } |
| |
| #[cfg(feature = "alloc")] |
| impl<'a> Encoder<'a> { |
| fn new(encoding: &'a Encoding, output: &'a mut String) -> Self { |
| Encoder { encoding, output, buffer: [0; 255], length: 0 } |
| } |
| |
| /// Encodes the provided input fragment and appends the result to the output |
| pub fn append(&mut self, mut input: &[u8]) { |
| #[allow(clippy::cast_possible_truncation)] // no truncation |
| let max = self.encoding.block_len().0 as u8; |
| if self.length != 0 { |
| let len = self.length; |
| #[allow(clippy::cast_possible_truncation)] // no truncation |
| let add = core::cmp::min((max - len) as usize, input.len()) as u8; |
| self.buffer[len as usize ..][.. add as usize].copy_from_slice(&input[.. add as usize]); |
| self.length += add; |
| input = &input[add as usize ..]; |
| if self.length != max { |
| debug_assert!(self.length < max); |
| debug_assert!(input.is_empty()); |
| return; |
| } |
| self.encoding.encode_append(&self.buffer[.. max as usize], self.output); |
| self.length = 0; |
| } |
| let len = floor(input.len(), max as usize); |
| self.encoding.encode_append(&input[.. len], self.output); |
| input = &input[len ..]; |
| #[allow(clippy::cast_possible_truncation)] // no truncation |
| let len = input.len() as u8; |
| self.buffer[.. len as usize].copy_from_slice(input); |
| self.length = len; |
| } |
| |
| /// Makes sure all inputs have been encoded and appended to the output |
| /// |
| /// This is equivalent to dropping the encoder and required for correctness, otherwise some |
| /// encoded data may be missing at the end. |
| pub fn finalize(self) {} |
| } |
| |
| #[derive(Debug, Copy, Clone)] |
| #[cfg(feature = "alloc")] |
| enum SpecificationErrorImpl { |
| BadSize, |
| NotAscii, |
| Duplicate(u8), |
| ExtraPadding, |
| WrapLength, |
| WrapWidth(u8), |
| FromTo, |
| Undefined(u8), |
| } |
| #[cfg(feature = "alloc")] |
| use crate::SpecificationErrorImpl::*; |
| |
| /// Specification error |
| #[derive(Debug, Copy, Clone)] |
| #[cfg(feature = "alloc")] |
| pub struct SpecificationError(SpecificationErrorImpl); |
| |
| #[cfg(feature = "alloc")] |
| impl core::fmt::Display for SpecificationError { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| match self.0 { |
| BadSize => write!(f, "invalid number of symbols"), |
| NotAscii => write!(f, "non-ascii character"), |
| Duplicate(c) => write!(f, "{:?} has conflicting definitions", c as char), |
| ExtraPadding => write!(f, "unnecessary padding"), |
| WrapLength => write!(f, "invalid wrap width or separator length"), |
| WrapWidth(x) => write!(f, "wrap width not a multiple of {}", x), |
| FromTo => write!(f, "translate from/to length mismatch"), |
| Undefined(c) => write!(f, "{:?} is undefined", c as char), |
| } |
| } |
| } |
| |
| #[cfg(feature = "std")] |
| impl std::error::Error for SpecificationError { |
| fn description(&self) -> &str { |
| match self.0 { |
| BadSize => "invalid number of symbols", |
| NotAscii => "non-ascii character", |
| Duplicate(_) => "conflicting definitions", |
| ExtraPadding => "unnecessary padding", |
| WrapLength => "invalid wrap width or separator length", |
| WrapWidth(_) => "wrap width not a multiple", |
| FromTo => "translate from/to length mismatch", |
| Undefined(_) => "undefined character", |
| } |
| } |
| } |
| |
| #[cfg(feature = "alloc")] |
| impl Specification { |
| /// Returns a default specification |
| #[must_use] |
| pub fn new() -> Specification { |
| Specification { |
| symbols: String::new(), |
| bit_order: MostSignificantFirst, |
| check_trailing_bits: true, |
| padding: None, |
| ignore: String::new(), |
| wrap: Wrap { width: 0, separator: String::new() }, |
| translate: Translate { from: String::new(), to: String::new() }, |
| } |
| } |
| |
| /// Returns the specified encoding |
| /// |
| /// # Errors |
| /// |
| /// Returns an error if the specification is invalid. |
| pub fn encoding(&self) -> Result<Encoding, SpecificationError> { |
| let symbols = self.symbols.as_bytes(); |
| let bit: u8 = match symbols.len() { |
| 2 => 1, |
| 4 => 2, |
| 8 => 3, |
| 16 => 4, |
| 32 => 5, |
| 64 => 6, |
| _ => return Err(SpecificationError(BadSize)), |
| }; |
| let mut values = [INVALID; 128]; |
| let set = |v: &mut [u8; 128], i: u8, x: u8| { |
| check!(SpecificationError(NotAscii), i < 128); |
| if v[i as usize] == x { |
| return Ok(()); |
| } |
| check!(SpecificationError(Duplicate(i)), v[i as usize] == INVALID); |
| v[i as usize] = x; |
| Ok(()) |
| }; |
| for (v, symbols) in symbols.iter().enumerate() { |
| #[allow(clippy::cast_possible_truncation)] // no truncation |
| set(&mut values, *symbols, v as u8)?; |
| } |
| let msb = self.bit_order == MostSignificantFirst; |
| let ctb = self.check_trailing_bits || 8 % bit == 0; |
| let pad = match self.padding { |
| None => None, |
| Some(pad) => { |
| check!(SpecificationError(ExtraPadding), 8 % bit != 0); |
| check!(SpecificationError(NotAscii), pad.len_utf8() == 1); |
| set(&mut values, pad as u8, PADDING)?; |
| Some(pad as u8) |
| } |
| }; |
| for i in self.ignore.bytes() { |
| set(&mut values, i, IGNORE)?; |
| } |
| let wrap = if self.wrap.separator.is_empty() || self.wrap.width == 0 { |
| None |
| } else { |
| let col = self.wrap.width; |
| let end = self.wrap.separator.as_bytes(); |
| check!(SpecificationError(WrapLength), col < 256 && end.len() < 256); |
| #[allow(clippy::cast_possible_truncation)] // no truncation |
| let col = col as u8; |
| #[allow(clippy::cast_possible_truncation)] // no truncation |
| let dec = dec(bit as usize) as u8; |
| check!(SpecificationError(WrapWidth(dec)), col % dec == 0); |
| for &i in end { |
| set(&mut values, i, IGNORE)?; |
| } |
| Some((col, end)) |
| }; |
| let from = self.translate.from.as_bytes(); |
| let to = self.translate.to.as_bytes(); |
| check!(SpecificationError(FromTo), from.len() == to.len()); |
| for i in 0 .. from.len() { |
| check!(SpecificationError(NotAscii), to[i] < 128); |
| let v = values[to[i] as usize]; |
| check!(SpecificationError(Undefined(to[i])), v != INVALID); |
| set(&mut values, from[i], v)?; |
| } |
| let mut encoding = Vec::new(); |
| for _ in 0 .. 256 / symbols.len() { |
| encoding.extend_from_slice(symbols); |
| } |
| encoding.extend_from_slice(&values); |
| encoding.extend_from_slice(&[INVALID; 128]); |
| match pad { |
| None => encoding.push(INVALID), |
| Some(pad) => encoding.push(pad), |
| } |
| encoding.push(bit); |
| if msb { |
| encoding[513] |= 0x08; |
| } |
| if ctb { |
| encoding[513] |= 0x10; |
| } |
| if let Some((col, end)) = wrap { |
| encoding.push(col); |
| encoding.extend_from_slice(end); |
| } else if values.contains(&IGNORE) { |
| encoding.push(0); |
| } |
| Ok(Encoding(Cow::Owned(encoding))) |
| } |
| } |
| |
| /// Lowercase hexadecimal encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, HEXLOWER}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789abcdef"); |
| /// assert_eq!(HEXLOWER, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::HEXLOWER; |
| /// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; |
| /// assert_eq!(HEXLOWER.decode(b"deadbeef").unwrap(), deadbeef); |
| /// assert_eq!(HEXLOWER.encode(&deadbeef), "deadbeef"); |
| /// ``` |
| pub const HEXLOWER: Encoding = Encoding::internal_new(HEXLOWER_IMPL); |
| const HEXLOWER_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, |
| 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, |
| 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, |
| 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, |
| 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, |
| 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, |
| 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, |
| 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, |
| 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, |
| 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 97, 98, 99, 100, 101, 102, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 2, |
| 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, |
| ]; |
| |
| /// Lowercase hexadecimal encoding with case-insensitive decoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, HEXLOWER_PERMISSIVE}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789abcdef"); |
| /// spec.translate.from.push_str("ABCDEF"); |
| /// spec.translate.to.push_str("abcdef"); |
| /// assert_eq!(HEXLOWER_PERMISSIVE, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::HEXLOWER_PERMISSIVE; |
| /// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; |
| /// assert_eq!(HEXLOWER_PERMISSIVE.decode(b"DeadBeef").unwrap(), deadbeef); |
| /// assert_eq!(HEXLOWER_PERMISSIVE.encode(&deadbeef), "deadbeef"); |
| /// ``` |
| /// |
| /// You can also define a shorter name: |
| /// |
| /// ```rust |
| /// use data_encoding::{Encoding, HEXLOWER_PERMISSIVE}; |
| /// const HEX: Encoding = HEXLOWER_PERMISSIVE; |
| /// ``` |
| pub const HEXLOWER_PERMISSIVE: Encoding = Encoding::internal_new(HEXLOWER_PERMISSIVE_IMPL); |
| const HEXLOWER_PERMISSIVE_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, |
| 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, |
| 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, |
| 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, |
| 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, |
| 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, |
| 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, |
| 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, |
| 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, |
| 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 97, 98, 99, 100, 101, 102, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 0, 1, 2, |
| 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, |
| ]; |
| |
| /// Uppercase hexadecimal encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, HEXUPPER}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789ABCDEF"); |
| /// assert_eq!(HEXUPPER, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// It is compliant with [RFC4648] and known as "base16" or "hex". |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::HEXUPPER; |
| /// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; |
| /// assert_eq!(HEXUPPER.decode(b"DEADBEEF").unwrap(), deadbeef); |
| /// assert_eq!(HEXUPPER.encode(&deadbeef), "DEADBEEF"); |
| /// ``` |
| /// |
| /// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-8 |
| pub const HEXUPPER: Encoding = Encoding::internal_new(HEXUPPER_IMPL); |
| const HEXUPPER_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, |
| 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, |
| ]; |
| |
| /// Uppercase hexadecimal encoding with case-insensitive decoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, HEXUPPER_PERMISSIVE}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789ABCDEF"); |
| /// spec.translate.from.push_str("abcdef"); |
| /// spec.translate.to.push_str("ABCDEF"); |
| /// assert_eq!(HEXUPPER_PERMISSIVE, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// # Examples |
| /// |
| /// ```rust |
| /// use data_encoding::HEXUPPER_PERMISSIVE; |
| /// let deadbeef = vec![0xde, 0xad, 0xbe, 0xef]; |
| /// assert_eq!(HEXUPPER_PERMISSIVE.decode(b"DeadBeef").unwrap(), deadbeef); |
| /// assert_eq!(HEXUPPER_PERMISSIVE.encode(&deadbeef), "DEADBEEF"); |
| /// ``` |
| pub const HEXUPPER_PERMISSIVE: Encoding = Encoding::internal_new(HEXUPPER_PERMISSIVE_IMPL); |
| const HEXUPPER_PERMISSIVE_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, |
| 12, 13, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 28, |
| ]; |
| |
| /// Padded base32 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE32}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); |
| /// spec.padding = Some('='); |
| /// assert_eq!(BASE32, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// It conforms to [RFC4648]. |
| /// |
| /// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-6 |
| pub const BASE32: Encoding = Encoding::internal_new(BASE32_IMPL); |
| const BASE32_IMPL: &[u8] = &[ |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, |
| 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, |
| 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 130, 128, 128, |
| 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
| 25, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 29, |
| ]; |
| |
| /// Unpadded base32 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE32_NOPAD}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); |
| /// assert_eq!(BASE32_NOPAD, spec.encoding().unwrap()); |
| /// ``` |
| pub const BASE32_NOPAD: Encoding = Encoding::internal_new(BASE32_NOPAD_IMPL); |
| const BASE32_NOPAD_IMPL: &[u8] = &[ |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, |
| 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, |
| 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 50, 51, 52, 53, 54, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, |
| 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 50, 51, 52, 53, 54, 55, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
| 25, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 29, |
| ]; |
| |
| /// Padded base32hex encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE32HEX}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789ABCDEFGHIJKLMNOPQRSTUV"); |
| /// spec.padding = Some('='); |
| /// assert_eq!(BASE32HEX, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// It conforms to [RFC4648]. |
| /// |
| /// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-7 |
| pub const BASE32HEX: Encoding = Encoding::internal_new(BASE32HEX_IMPL); |
| const BASE32HEX_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, |
| 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, |
| 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, |
| 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 130, 128, 128, 128, 10, 11, |
| 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 29, |
| ]; |
| |
| /// Unpadded base32hex encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE32HEX_NOPAD}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789ABCDEFGHIJKLMNOPQRSTUV"); |
| /// assert_eq!(BASE32HEX_NOPAD, spec.encoding().unwrap()); |
| /// ``` |
| pub const BASE32HEX_NOPAD: Encoding = Encoding::internal_new(BASE32HEX_NOPAD_IMPL); |
| const BASE32HEX_NOPAD_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, |
| 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, |
| 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, |
| 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, |
| 79, 80, 81, 82, 83, 84, 85, 86, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, |
| 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, |
| 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 29, |
| ]; |
| |
| /// DNSSEC base32 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE32_DNSSEC}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789abcdefghijklmnopqrstuv"); |
| /// spec.translate.from.push_str("ABCDEFGHIJKLMNOPQRSTUV"); |
| /// spec.translate.to.push_str("abcdefghijklmnopqrstuv"); |
| /// assert_eq!(BASE32_DNSSEC, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// It conforms to [RFC5155]: |
| /// |
| /// - It uses a base32 extended hex alphabet. |
| /// - It is case-insensitive when decoding and uses lowercase when encoding. |
| /// - It does not use padding. |
| /// |
| /// [RFC5155]: https://tools.ietf.org/html/rfc5155 |
| pub const BASE32_DNSSEC: Encoding = Encoding::internal_new(BASE32_DNSSEC_IMPL); |
| const BASE32_DNSSEC_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, |
| 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, |
| 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, |
| 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, |
| 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, |
| 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, |
| 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, |
| 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, |
| 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, |
| 110, 111, 112, 113, 114, 115, 116, 117, 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, |
| 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, |
| 118, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, |
| 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, |
| 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, |
| 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 29, |
| ]; |
| |
| #[allow(clippy::doc_markdown)] |
| /// DNSCurve base32 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{BitOrder, Specification, BASE32_DNSCURVE}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("0123456789bcdfghjklmnpqrstuvwxyz"); |
| /// spec.bit_order = BitOrder::LeastSignificantFirst; |
| /// spec.translate.from.push_str("BCDFGHJKLMNPQRSTUVWXYZ"); |
| /// spec.translate.to.push_str("bcdfghjklmnpqrstuvwxyz"); |
| /// assert_eq!(BASE32_DNSCURVE, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// It conforms to [DNSCurve]. |
| /// |
| /// [DNSCurve]: https://dnscurve.org/in-implement.html |
| pub const BASE32_DNSCURVE: Encoding = Encoding::internal_new(BASE32_DNSCURVE_IMPL); |
| const BASE32_DNSCURVE_IMPL: &[u8] = &[ |
| 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, |
| 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, |
| 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, |
| 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, |
| 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, |
| 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, |
| 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, |
| 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, |
| 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, |
| 114, 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, |
| 100, 102, 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, |
| 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 98, 99, 100, 102, 103, 104, 106, 107, 108, 109, |
| 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 128, 128, 128, 128, 128, 128, 128, 128, 10, 11, |
| 12, 128, 13, 14, 15, 128, 16, 17, 18, 19, 20, 128, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, |
| 128, 128, 128, 128, 128, 128, 128, 10, 11, 12, 128, 13, 14, 15, 128, 16, 17, 18, 19, 20, 128, |
| 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 21, |
| ]; |
| |
| /// Padded base64 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE64}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); |
| /// spec.padding = Some('='); |
| /// assert_eq!(BASE64, spec.encoding().unwrap()); |
| /// ``` |
| /// |
| /// It conforms to [RFC4648]. |
| /// |
| /// [RFC4648]: https://tools.ietf.org/html/rfc4648#section-4 |
| pub const BASE64: Encoding = Encoding::internal_new(BASE64_IMPL); |
| const BASE64_IMPL: &[u8] = &[ |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, |
| 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, |
| 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, |
| 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, |
| 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, |
| 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, |
| 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, |
| 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, 68, |
| 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, |
| 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, |
| 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 130, 128, |
| 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, |
| 24, 25, 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, |
| 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 61, 30, |
| ]; |
| |
| /// Unpadded base64 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE64_NOPAD}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); |
| /// assert_eq!(BASE64_NOPAD, spec.encoding().unwrap()); |
| /// ``` |
| pub const BASE64_NOPAD: Encoding = Encoding::internal_new(BASE64_NOPAD_IMPL); |
| const BASE64_NOPAD_IMPL: &[u8] = &[ |
| 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, |
| 89, 90, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, |
| 115, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, |
| 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, |
| 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, |
| 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, |
| 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, |
| 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, |
| 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 65, 66, 67, 68, |
| 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, |
| 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, |
| 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 62, 128, 128, 128, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 128, 128, |
| 128, 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, |
| 24, 25, 128, 128, 128, 128, 128, 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, |
| 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, |
| 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 30, |
| ]; |
| |
| /// MIME base64 encoding |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, 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, |
| ]; |
| |
| /// MIME base64 encoding without trailing bits check |
| /// |
| /// This encoding is a static version of: |
| /// |
| /// ```rust |
| /// # use data_encoding::{Specification, BASE64_MIME_PERMISSIVE}; |
| /// let mut spec = Specification::new(); |
| /// spec.symbols.push_str("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); |
| /// spec.padding = Some('='); |
| /// spec.wrap.width = 76; |
| /// spec.wrap.separator.push_str("\r\n"); |
| /// spec.check_trailing_bits = false; |
| /// assert_eq!(BASE64_MIME_PERMISSIVE, 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_PERMISSIVE: Encoding = Encoding::internal_new(BASE64_MIME_PERMISSIVE_IMPL); |
| const BASE64_MIME_PERMISSIVE_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, 14, 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, |
| ]; |