#[cfg(any(
feature = "base16",
feature = "hex"
))]
mod base16;
#[cfg(feature = "base32")]
mod base32;
#[cfg(feature = "base32hex")]
mod base32hex;
#[cfg(feature = "base64")]
mod base64;
#[cfg(feature = "base64url")]
mod base64url;
#[cfg(any(
feature = "base16",
feature = "hex"
))]
pub use base16::Base16Context;
#[cfg(feature = "base32")]
pub use base32::Base32Context;
#[cfg(feature = "base32hex")]
pub use base32hex::Base32HexContext;
#[cfg(feature = "base64")]
pub use base64::Base64Context;
#[cfg(feature = "base64url")]
pub use base64url::Base64UrlContext;
#[cfg(any(
feature = "base32",
feature = "base32hex",
feature = "base64",
feature = "base64url"
))]
use std::collections::HashMap;
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
const ZERO_PADDING_BYTES_BIT_STRING: u64 = 0x0;
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
const ONE_PADDING_BYTE_BIT_STRING: u64 = 0x3d;
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
const THREE_PADDING_BYTE_BIT_STRING: u64 = 0x3d_3d3d;
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
const FOUR_PADDING_BYTE_BIT_STRING: u64 = 0x3d3d_3d3d;
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
const SIX_PADDING_BYTE_BIT_STRING: u64 = 0x3d3d_3d3d_3d3d;
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
fn base32_decode(
ciphertext: &Vec<u8>,
alphabet: HashMap<u8, u64>,
) -> Vec<u8> {
let mut plaintext = Vec::new();
let mut iter = ciphertext.iter();
let mut maybe_next = iter.next();
while maybe_next != None {
let mut block: u64 = 0;
let mut byte = maybe_next.unwrap();
let mut character = *alphabet.get(byte).unwrap();
block |= character << 35;
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
block |= character << 30;
plaintext.push((block >> 32) as u8);
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
if character != 32 {
block |= character << 25;
} else {
break;
}
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
block |= character << 20;
plaintext.push((block >> 24) as u8);
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
if character != 32 {
block |= character << 15;
plaintext.push((block >> 16) as u8);
}
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
if character != 32 {
block |= character << 10;
} else {
break;
}
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
block |= character << 5;
plaintext.push((block >> 8) as u8);
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
if character != 32 {
block |= character;
plaintext.push(block as u8);
}
maybe_next = iter.next();
}
plaintext
}
#[cfg(any(
feature = "base32",
feature = "base32hex"
))]
fn base32_encode(
plaintext: &Vec<u8>,
alphabet: [u8; 33],
) -> Vec<u8> {
let mut ciphertext = Vec::new();
let mut iter = plaintext.iter();
let mut byte = iter.next();
while byte != None {
let mut block: u64 = 0;
for count in 1..=5 {
if let Some(byte) = byte {
let value = byte.clone();
match count {
1 => {
block |= ((value & 0b1111_1000) as u64) << 39;
block |= ((value & 0b0000_0111) as u64) << 38;
}
2 => {
block |= ((value & 0b1100_0000) as u64) << 30;
block |= ((value & 0b0011_1110) as u64) << 29;
block |= ((value & 0b0000_0001) as u64) << 28;
}
3 => {
block |= ((value & 0b1111_0000) as u64) << 20;
block |= ((value & 0b0000_1111) as u64) << 19;
}
4 => {
block |= ((value & 0b1000_0000) as u64) << 11;
block |= ((value & 0b0111_1100) as u64) << 10;
block |= ((value & 0b0000_0011) as u64) << 9;
}
_ => {
block |= ((value & 0b1110_0000) as u64) << 1;
block |= (value & 0b0001_1111) as u64;
}
}
} else {
match count {
2 => {
block |= 0b1_000_0000_0000_0000_0000_0000_0000_0000_0000;
block |= 0b10_0000_0000_0000_0000_0000_0000_0000;
}
3 => {
block |= 0b1000_0000_0000_0000_0000_0000;
}
4 => {
block |= 0b10_0000_0000_0000_0000;
block |= 0b1000_0000_0000;
}
_ => {
block |= 0b10_0000;
}
}
}
byte = iter.next();
}
let bits_per_ciphertext_value = 6;
for pos in (0_u64..8_u64).rev() {
ciphertext.push(
alphabet[((block >> (pos * bits_per_ciphertext_value)) & 0b11_1111) as usize]
);
}
}
ciphertext
}
#[cfg(any(
feature = "base64",
feature = "base64url"
))]
fn base64_decode(
ciphertext: &Vec<u8>,
alphabet: HashMap<u8, u32>,
) -> Vec<u8> {
let mut plaintext = Vec::new();
let mut iter = ciphertext.iter();
let mut maybe_next = iter.next();
while maybe_next != None {
let mut block: u32 = 0;
let mut byte = maybe_next.unwrap();
let mut character = *alphabet.get(byte).unwrap();
block |= character << 18;
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
block |= character << 12;
plaintext.push((block >> 16) as u8);
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
if character != 64 {
block |= character << 6;
plaintext.push((block >> 8) as u8);
}
byte = iter.next().unwrap();
character = *alphabet.get(byte).unwrap();
if character != 64 {
block |= character;
plaintext.push(block as u8);
}
maybe_next = iter.next();
}
plaintext
}
#[cfg(any(
feature = "base64",
feature = "base64url"
))]
fn base64_encode(
plaintext: &Vec<u8>,
alphabet: [u8; 65],
) -> Vec<u8> {
let mut ciphertext = Vec::new();
let mut iter = plaintext.iter();
let mut byte = iter.next();
while byte != None {
let mut block: u32 = 0;
for count in 1..=3 {
if let Some(byte) = byte {
let value = byte.clone();
match count {
1 => {
block |= ((value & 0b1111_1100) as u32) << 19;
block |= ((value & 0b0000_0011) as u32) << 18;
}
2 => {
block |= ((value & 0b1111_0000) as u32) << 10;
block |= ((value & 0b0000_1111) as u32) << 9;
}
_ => {
block |= ((value & 0b1100_0000) as u32) << 1;
block |= (value & 0b0011_1111) as u32;
}
}
} else {
match count {
2 => { block |= 0b10_0000_0000_0000; }
_ => { block |= 0b100_0000; }
}
}
byte = iter.next();
}
for pos in (0_u32..4_u32).rev() {
ciphertext.push(alphabet[((block >> (pos * 7)) & 0b111_1111) as usize]);
}
}
ciphertext
}