use serde::{Serialize, Deserialize};
use base64::{engine::{general_purpose::GeneralPurpose, GeneralPurposeConfig, DecodePaddingMode}, alphabet::Alphabet};
use crate::util::*;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Suitability)]
#[serde(deny_unknown_fields)]
pub struct Base64Config {
#[serde(default, skip_serializing_if = "is_default")]
pub alphabet: Base64Alphabet,
#[serde(default = "get_true", skip_serializing_if = "is_true")]
pub encode_padding: bool,
#[serde(default, skip_serializing_if = "is_default")]
pub decode_padding: Base64DecodePaddingMode,
#[serde(default, skip_serializing_if = "is_default")]
pub decode_allow_trailing_bits: bool
}
impl Base64Config {
pub fn build(&self) -> GeneralPurpose {
GeneralPurpose::new(
self.alphabet.get(),
GeneralPurposeConfig::new()
.with_decode_padding_mode(self.decode_padding.build())
.with_encode_padding(self.encode_padding)
.with_decode_allow_trailing_bits(self.decode_allow_trailing_bits)
)
}
}
impl Default for Base64Config {
fn default() -> Self {
Self {
alphabet: Default::default(),
encode_padding: true,
decode_padding: Default::default(),
decode_allow_trailing_bits: false
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Suitability)]
#[serde(deny_unknown_fields)]
pub enum Base64Alphabet {
Standard,
#[default]
UrlSafe,
Crypt,
Bcrypt,
IMAPMUTF7,
BinHex
}
impl Base64Alphabet {
pub fn get(&self) -> &Alphabet {
match self {
Self::Standard => &base64::alphabet::STANDARD,
Self::UrlSafe => &base64::alphabet::URL_SAFE,
Self::Crypt => &base64::alphabet::CRYPT,
Self::Bcrypt => &base64::alphabet::BCRYPT,
Self::IMAPMUTF7 => &base64::alphabet::IMAP_MUTF7,
Self::BinHex => &base64::alphabet::BIN_HEX
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, Suitability)]
#[serde(deny_unknown_fields)]
pub enum Base64DecodePaddingMode {
#[default]
Indifferent,
RequireCanonical,
RequireNone
}
impl Base64DecodePaddingMode {
pub fn build(&self) -> DecodePaddingMode {
match self {
Self::Indifferent => DecodePaddingMode::Indifferent,
Self::RequireCanonical => DecodePaddingMode::RequireCanonical,
Self::RequireNone => DecodePaddingMode::RequireNone
}
}
}