#![warn(unused_results, missing_docs)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum DecodeKind {
Length,
Symbol,
Trailing,
Padding,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DecodeError {
pub position: usize,
pub kind: DecodeKind,
}
impl std::error::Error for DecodeError {
fn description(&self) -> &str {
match self.kind {
DecodeKind::Length => "invalid length",
DecodeKind::Symbol => "invalid symbol",
DecodeKind::Trailing => "non-zero trailing bits",
DecodeKind::Padding => "invalid padding length",
}
}
}
impl std::fmt::Display for DecodeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use std::error::Error;
write!(f, "{} at {}", self.description(), self.position)
}
}
macro_rules! check { ($e: expr, $c: expr) => { if !$c { return Err($e); } }; }
fn div_ceil(x: usize, m: usize) -> usize { (x + m - 1) / m }
fn floor(x: usize, m: usize) -> usize { x / m * m }
unsafe fn chunk_unchecked(x: &[u8], n: usize, i: usize) -> &[u8] {
debug_assert!((i + 1) * n <= x.len());
let ptr = x.as_ptr().offset((n * i) as isize);
std::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().offset((n * i) as isize);
std::slice::from_raw_parts_mut(ptr, n)
}
trait Base: Copy {
fn bit(&self) -> usize;
fn msb(&self) -> bool;
}
macro_rules! make {
($val: expr, $msb: ident, $lsb: ident) => {
#[derive(Copy, Clone)] struct $msb;
impl Base for $msb {
fn bit(&self) -> usize { $val }
fn msb(&self) -> bool { true }
}
#[derive(Copy, Clone)] struct $lsb;
impl Base for $lsb {
fn bit(&self) -> usize { $val }
fn msb(&self) -> bool { false }
}
};
}
make!(1, M1, L1);
make!(2, M2, L2);
make!(3, M3, L3);
make!(4, M4, L4);
make!(5, M5, L5);
make!(6, M6, L6);
macro_rules! dispatch {
($fun: ident; $bit: expr, $msb: expr, $($arg: expr),*) => {
match ($bit, $msb) {
(1, true) => $fun(M1, $($arg),*),
(2, true) => $fun(M2, $($arg),*),
(3, true) => $fun(M3, $($arg),*),
(4, true) => $fun(M4, $($arg),*),
(5, true) => $fun(M5, $($arg),*),
(6, true) => $fun(M6, $($arg),*),
(1, false) => $fun(L1, $($arg),*),
(2, false) => $fun(L2, $($arg),*),
(3, false) => $fun(L3, $($arg),*),
(4, false) => $fun(L4, $($arg),*),
(5, false) => $fun(L5, $($arg),*),
(6, false) => $fun(L6, $($arg),*),
_ => unreachable!(),
}
};
}
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_block<B: Base>(base: B, symbols: &[u8; 256], input: &[u8],
output: &mut [u8]) {
let bit = base.bit();
let msb = base.msb();
let mut x = 0u64;
for i in 0 .. input.len() {
x |= (input[i] as u64) << 8 * order(msb, enc(bit), i);
}
for i in 0 .. output.len() {
let y = x >> bit * order(msb, dec(bit), i);
output[i] = symbols[y as usize % 256];
}
}
fn encode_mut<B: Base>(base: B, symbols: &[u8; 256], input: &[u8],
output: &mut [u8]) {
let enc = enc(base.bit());
let dec = dec(base.bit());
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_block(base, symbols, input, output);
}
encode_block(base, symbols, &input[enc * n ..], &mut output[dec * n ..]);
}
fn decode_block<B: Base>(base: B, values: &[u8; 256], input: &[u8],
output: &mut [u8]) -> Result<(), usize> {
let bit = base.bit();
let msb = base.msb();
let mut x = 0u64;
for j in 0 .. input.len() {
let y = values[input[j] as usize];
check!(j, y < 1 << bit);
x |= (y as u64) << bit * order(msb, dec(bit), j);
}
for j in 0 .. output.len() {
output[j] = (x >> 8 * order(msb, enc(bit), j)) as u8;
}
Ok(())
}
fn decode_mut<B: Base>(base: B, values: &[u8; 256], input: &[u8],
output: &mut [u8]) -> Result<(), usize> {
let enc = enc(base.bit());
let dec = dec(base.bit());
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(base, values, input, output).map_err(|e| dec * i + e)?;
}
decode_block(base, values, &input[dec * n ..], &mut output[enc * n ..])
.map_err(|e| dec * n + e)
}
fn check_trail<B: Base>(base: B, ctb: bool, values: &[u8; 256], input: &[u8])
-> Result<(), ()> {
if !ctb { return Ok(()) }
let trail = base.bit() * input.len() % 8;
if trail == 0 { return Ok(()) }
let mut mask = (1 << trail) - 1;
if !base.msb() { mask <<= base.bit() - trail; }
check!((), values[input[input.len() - 1] as usize] & mask == 0);
Ok(())
}
fn check_pad<B: Base>(base: B, pad: u8, input: &[u8]) -> Result<usize, usize> {
let bit = base.bit();
debug_assert_eq!(input.len(), dec(bit));
let count = input.iter().rev().take_while(|&x| *x == pad).count();
let len = input.len() - count;
check!(len, len > 0 && bit * len % 8 < bit);
Ok(len)
}
macro_rules! make_array {
($name: ident, $len: expr) => {
impl std::ops::Deref for $name {
type Target = [u8; $len];
fn deref(&self) -> &Self::Target { &self.0 }
}
impl std::ops::DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl Clone for $name { fn clone(&self) -> Self { *self } }
impl Copy for $name { }
impl std::fmt::Debug for $name {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
<&[u8] as std::fmt::Debug>::fmt(&(&self.0 as &[u8]), f)
}
}
impl PartialEq for $name {
fn eq(&self, other: &Self) -> bool {
&self.0 as &[u8] == &other.0 as &[u8]
}
}
impl Eq for $name { }
};
}
pub struct Array128([u8; 128]);
make_array!(Array128, 128);
struct Array256([u8; 256]);
make_array!(Array256, 256);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum BitOrder {
MostSignificantFirst,
LeastSignificantFirst,
}
use BitOrder::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct NoPad {
sym: Array256,
val: Array256,
bit: u8,
msb: bool,
ctb: bool,
}
impl NoPad {
fn bit(&self) -> usize { self.bit as usize }
pub fn encode_len(&self, len: usize) -> usize {
div_ceil(8 * len, self.bit())
}
pub fn encode_mut(&self, input: &[u8], output: &mut [u8]) {
assert_eq!(output.len(), self.encode_len(input.len()));
dispatch!(encode_mut; self.bit(), self.msb, &self.sym, input, output)
}
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) }
}
pub fn decode_len(&self, len: usize) -> Result<usize, DecodeError> {
let bit = self.bit();
let trail = bit * len % 8;
check!(DecodeError { position: len - trail / bit,
kind: DecodeKind::Length }, trail < bit);
Ok(bit * len / 8)
}
pub fn decode_mut(&self, input: &[u8], output: &mut [u8])
-> Result<(), DecodeError> {
assert_eq!(output.len(), self.decode_len(input.len()).unwrap());
dispatch!(decode_mut; self.bit(), self.msb, &self.val, input, output)
.map_err(|pos| DecodeError { position: pos,
kind: DecodeKind::Symbol })?;
dispatch!(check_trail; self.bit(), self.msb, self.ctb, &self.val, input)
.map_err(|()| DecodeError { position: input.len() - 1,
kind: DecodeKind::Trailing })?;
Ok(())
}
pub fn decode(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError> {
let mut output = vec![0u8; self.decode_len(input.len())?];
self.decode_mut(input, &mut output)?;
Ok(output)
}
pub fn bit_width(&self) -> usize { self.bit() }
pub fn bit_order(&self) -> BitOrder {
if self.msb { MostSignificantFirst } else { LeastSignificantFirst }
}
pub fn symbols(&self) -> &str {
let symbols = &self.sym[0 .. 1 << self.bit()];
unsafe { std::str::from_utf8_unchecked(symbols) }
}
pub fn translate(&self) -> (String, String) {
let mut from = vec![];
let mut to = vec![];
for i in 0 .. 128 {
if self.val[i] == 128 { continue; }
let canonical = self.sym[self.val[i] as usize];
if i as u8 == canonical { continue; }
from.push(i as u8);
to.push(canonical);
}
let from = unsafe { String::from_utf8_unchecked(from) };
let to = unsafe { String::from_utf8_unchecked(to) };
(from, to)
}
pub fn check_trailing_bits(&self) -> Option<bool> {
if 8 % self.bit() == 0 { None } else { Some(self.ctb) }
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Padded {
no_pad: NoPad,
pad: u8,
}
impl Padded {
pub fn encode_len(&self, len: usize) -> usize {
let bit = self.no_pad.bit();
div_ceil(len, enc(bit)) * dec(bit)
}
pub fn encode_mut(&self, input: &[u8], output: &mut [u8]) {
assert_eq!(output.len(), self.encode_len(input.len()));
let last = self.no_pad.encode_len(input.len());
self.no_pad.encode_mut(input, &mut output[0 .. last]);
for i in output[last ..].iter_mut() {
*i = self.pad;
}
}
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) }
}
pub fn decode_len(&self, len: usize) -> Result<usize, DecodeError> {
let bit = self.no_pad.bit();
check!(DecodeError { position: floor(len, dec(bit)),
kind: DecodeKind::Length },
len % dec(bit) == 0);
Ok(len / dec(bit) * enc(bit))
}
pub fn decode_mut(&self, input: &[u8], output: &mut [u8])
-> Result<usize, DecodeError> {
if input.len() == 0 { return Ok(0); }
assert_eq!(output.len(), self.decode_len(input.len()).unwrap());
let dec = dec(self.no_pad.bit());
let ilen = input.len() - dec;
let irem = dispatch!(check_pad; self.no_pad.bit(), self.no_pad.msb,
self.pad, &input[ilen ..])
.map_err(|e| DecodeError { position: ilen + e,
kind: DecodeKind::Padding })?;
let olen = self.no_pad.decode_len(ilen + irem).unwrap();
self.no_pad.decode_mut(&input[.. ilen + irem], &mut output[.. olen])?;
Ok(olen)
}
pub fn decode(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError> {
let mut output = vec![0u8; self.decode_len(input.len())?];
let len = self.decode_mut(input, &mut output)?;
output.truncate(len);
Ok(output)
}
pub fn decode_concat_mut(&self, input: &[u8], output: &mut [u8])
-> Result<usize, DecodeError> {
assert_eq!(output.len(), self.decode_len(input.len()).unwrap());
let bit = self.no_pad.bit();
let enc = enc(bit);
let dec = dec(bit);
let mut inpos = 0;
let mut outpos = 0;
let mut outend = output.len();
while inpos < input.len() {
let ret = self.no_pad.decode_mut(
&input[inpos ..], &mut output[outpos .. outend]);
match ret {
Ok(()) => break,
Err(err) => {
debug_assert_eq!(err.kind, DecodeKind::Symbol);
inpos += err.position / dec * dec;
outpos += err.position / dec * enc;
},
}
let inlen = dispatch!(check_pad; self.no_pad.bit(), self.no_pad.msb,
self.pad, &input[inpos .. inpos + dec])
.map_err(|e| DecodeError { position: inpos + e,
kind: DecodeKind::Padding })?;
let outlen = self.no_pad.decode_len(inlen).unwrap();
self.no_pad.decode_mut(&input[inpos .. inpos + inlen],
&mut output[outpos .. outpos + outlen])
.map_err(|mut e| { e.position += inpos; e })?;
inpos += dec;
outpos += outlen;
outend -= enc - outlen;
}
Ok(outend)
}
pub fn decode_concat(&self, input: &[u8]) -> Result<Vec<u8>, DecodeError> {
let mut output = vec![0u8; self.decode_len(input.len())?];
let len = self.decode_concat_mut(input, &mut output)?;
output.truncate(len);
Ok(output)
}
pub fn no_pad(&self) -> &NoPad { &self.no_pad }
pub fn padding(&self) -> u8 { self.pad }
}
#[derive(Debug, Clone)]
pub struct Builder {
pub symbols: Box<[u8]>,
pub values: Box<Array128>,
pub bit_order: BitOrder,
pub padding: Option<u8>,
pub check_trailing_bits: bool,
}
#[derive(Debug, Copy, Clone)]
enum BuilderErrorImpl {
BadSize,
BadSym(u8),
BadVal(u8),
BadPad(Option<u8>),
}
use BuilderErrorImpl::*;
#[derive(Debug, Copy, Clone)]
pub struct BuilderError(BuilderErrorImpl);
impl std::fmt::Display for BuilderError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.0 {
BadSize => write!(f, "Invalid number of symbols"),
BadSym(s) => write!(f, "Non-ascii symbol {:#x}", s),
BadVal(s) => write!(f, "Invalid value for {:?}", s as char),
BadPad(Some(s)) if s < 128 => write!(f, "Padding symbol conflict"),
BadPad(Some(pad)) => write!(f, "Non-ascii padding {:#x}", pad),
BadPad(None) => write!(f, "Unnecessary or missing padding"),
}
}
}
impl std::error::Error for BuilderError {
fn description(&self) -> &str {
match self.0 {
BadSize => "invalid number of symbols",
BadSym(_) => "non-ascii symbol",
BadVal(_) => "invalid value",
BadPad(Some(s)) if s < 128 => "padding symbol conflict",
BadPad(Some(_)) => "non-ascii padding",
BadPad(None) => "unnecessary or missing padding",
}
}
}
impl Builder {
fn bit(&self) -> Result<u8, BuilderError> {
match self.symbols.len() {
2 => Ok(1),
4 => Ok(2),
8 => Ok(3),
16 => Ok(4),
32 => Ok(5),
64 => Ok(6),
_ => Err(BuilderError(BadSize)),
}
}
fn check(&self) -> Result<(), BuilderError> {
let bit = self.bit()?;
let even = 8 % bit == 0;
check!(BuilderError(BadPad(None)), self.padding.is_none() || !even);
for v in 0 .. self.symbols.len() {
let s = self.symbols[v];
check!(BuilderError(BadSym(s)), s < 128);
check!(BuilderError(BadVal(s)), self.values[s as usize] == v as u8);
}
for s in 0 .. self.values.len() {
if self.values[s] == 128 { continue; }
check!(BuilderError(BadVal(s as u8)), self.values[s] < 1 << bit);
}
if let Some(pad) = self.padding {
check!(BuilderError(BadPad(Some(pad))), pad < 128);
for s in 0 .. self.values.len() {
if self.values[s] == 128 { continue; }
check!(BuilderError(BadPad(Some(pad))), pad != s as u8);
}
}
Ok(())
}
fn no_pad_unchecked(&self) -> NoPad {
let bit = self.bit().unwrap();
let mut base = NoPad {
sym: Array256([0; 256]), val: Array256([128; 256]), bit: bit,
msb: self.bit_order == MostSignificantFirst,
ctb: 8 % bit != 0 && self.check_trailing_bits,
};
for i in 0 .. base.sym.len() {
base.sym[i] = self.symbols[i % self.symbols.len()];
}
for i in 0 .. self.values.len() {
base.val[i] = self.values[i];
}
base
}
pub fn new(symbols: &[u8]) -> Builder {
let mut builder = Builder {
symbols: symbols.to_vec().into_boxed_slice(),
values: Box::new(Array128([128; 128])),
bit_order: MostSignificantFirst,
padding: None,
check_trailing_bits: true,
};
for v in 0 .. symbols.len() {
if symbols[v] >= 128 { continue; }
builder.values[symbols[v] as usize] = v as u8;
}
builder
}
pub fn pad(&mut self, pad: u8) -> &mut Builder {
self.padding = Some(pad);
self
}
pub fn translate(&mut self, from: &[u8], to: &[u8]) -> &mut Builder {
assert_eq!(from.len(), to.len());
for i in 0 .. from.len() {
if from[i] >= 128 || to[i] >= 128 { continue; }
self.values[from[i] as usize] = self.values[to[i] as usize];
}
self
}
pub fn least_significant_bit_first(&mut self) -> &mut Builder {
self.bit_order = LeastSignificantFirst;
self
}
pub fn ignore_trailing_bits(&mut self) -> &mut Builder {
self.check_trailing_bits = false;
self
}
pub fn no_pad(&self) -> Result<NoPad, BuilderError> {
check!(BuilderError(BadPad(None)), self.padding.is_none());
self.check()?;
Ok(self.no_pad_unchecked())
}
pub fn padded(&self) -> Result<Padded, BuilderError> {
let pad = self.padding.ok_or(BuilderError(BadPad(None)))?;
self.check()?;
Ok(Padded { no_pad: self.no_pad_unchecked(), pad: pad })
}
}
impl<'a> From<&'a NoPad> for Builder {
fn from(no_pad: &NoPad) -> Builder {
let mut builder = Builder {
symbols: no_pad.symbols().as_bytes().to_vec().into_boxed_slice(),
values: Box::new(Array128([0; 128])),
bit_order: no_pad.bit_order(),
padding: None,
check_trailing_bits: no_pad.ctb,
};
builder.values.copy_from_slice(&no_pad.val[0 .. 128]);
builder
}
}
impl<'a> From<&'a Padded> for Builder {
fn from(padded: &Padded) -> Builder {
let mut builder = Builder::from(&padded.no_pad);
builder.padding = Some(padded.pad);
builder
}
}
const X_: u8 = 128;
macro_rules! make_val {
($($v: expr),*) => { [
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
$($v),*,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
] };
}
macro_rules! make_sym {
(7; $($s: expr),*) => { [ $($s),*, $($s),*, ] };
(6; $($s: expr),*) => { make_sym!(7; $($s),*, $($s),*) };
(5; $($s: expr),*) => { make_sym!(6; $($s),*, $($s),*) };
(4; $($s: expr),*) => { make_sym!(5; $($s),*, $($s),*) };
}
macro_rules! make_base {
($b: tt; $($v: expr),*; $($s: expr),*;) => {
NoPad {
sym: Array256(make_sym!($b; $($s),*)),
val: Array256(make_val!($($v),*)),
bit: $b,
msb: true,
ctb: 8 % $b != 0,
}
};
($p: expr; $b: tt; $($v: expr),*; $($s: expr),*;) => {
Padded {
no_pad: make_base!($b; $($v),*; $($s),*;),
pad: $p,
}
};
}
pub const HEXLOWER: &'static NoPad = HEXLOWER_IMPL;
const HEXLOWER_IMPL: &'static NoPad = &make_base!{
4;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, 10, 11, 12, 13, 14, 15, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_;
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f';
};
pub const HEXUPPER: &'static NoPad = HEXUPPER_IMPL;
const HEXUPPER_IMPL: &'static NoPad = &make_base!{
4;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , X_, X_, X_, X_, X_, X_,
X_, 10, 11, 12, 13, 14, 15, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_;
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F';
};
pub const HEXLOWER_PERMISSIVE: &'static NoPad = HEXLOWER_PERMISSIVE_IMPL;
const HEXLOWER_PERMISSIVE_IMPL: &'static NoPad = &make_base!{
4;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , X_, X_, X_, X_, X_, X_,
X_, 10, 11, 12, 13, 14, 15, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, 10, 11, 12, 13, 14, 15, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_;
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f';
};
pub const BASE32: &'static Padded = BASE32_IMPL;
const BASE32_IMPL: &'static Padded = &make_base!{
b'='; 5;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, 26, 27, 28, 29, 30, 31, X_, X_, X_, X_, X_, X_, X_, X_,
X_, 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, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_;
b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H',
b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P',
b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X',
b'Y', b'Z', b'2', b'3', b'4', b'5', b'6', b'7';
};
pub const BASE32HEX: &'static Padded = BASE32HEX_IMPL;
const BASE32HEX_IMPL: &'static Padded = &make_base!{
b'='; 5;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
0_, 1_, 2_, 3_, 4_, 5_, 6_, 7_, 8_, 9_, X_, X_, X_, X_, X_, X_,
X_, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_,
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_;
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
b'8', b'9', b'A', b'B', b'C', b'D', b'E', b'F',
b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N',
b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V';
};
pub const BASE64: &'static Padded = BASE64_IMPL;
const BASE64_IMPL: &'static Padded = &make_base!{
b'='; 6;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, 62, X_, X_, X_, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, X_, X_, X_, X_, X_, X_,
X_, 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, X_, X_, X_, X_, X_,
X_, 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, X_, X_, X_, X_, X_;
b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H',
b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P',
b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X',
b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f',
b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n',
b'o', b'p', b'q', b'r', b's', b't', b'u', b'v',
b'w', b'x', b'y', b'z', b'0', b'1', b'2', b'3',
b'4', b'5', b'6', b'7', b'8', b'9', b'+', b'/';
};
pub const BASE64URL: &'static Padded = BASE64URL_IMPL;
const BASE64URL_IMPL: &'static Padded = &make_base!{
b'='; 6;
X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, X_, 62, X_, X_,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, X_, X_, X_, X_, X_, X_,
X_, 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, X_, X_, X_, X_, 63,
X_, 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, X_, X_, X_, X_, X_;
b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H',
b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P',
b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X',
b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f',
b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n',
b'o', b'p', b'q', b'r', b's', b't', b'u', b'v',
b'w', b'x', b'y', b'z', b'0', b'1', b'2', b'3',
b'4', b'5', b'6', b'7', b'8', b'9', b'-', b'_';
};