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