use base64::{
Engine,
alphabet::STANDARD,
engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig},
};
use crate::{
error::{Error, ErrorKind},
secrets::{SecretBytes, SecretMap, encodings::strip_ascii_whitespace},
};
const FORGIVING: GeneralPurpose = GeneralPurpose::new(
&STANDARD,
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent),
);
#[derive(Debug, Clone, Copy, Default)]
pub struct Base64Encoding;
impl SecretMap for Base64Encoding {
type In = SecretBytes;
type Out = SecretBytes;
fn apply(&self, input: SecretBytes) -> Result<SecretBytes, Error> {
let stripped = strip_ascii_whitespace(input.expose_secret(), |b| match b {
b'-' => b'+',
b'_' => b'/',
other => other,
});
let decoded = FORGIVING
.decode(&*stripped)
.map_err(|source| Error::new(ErrorKind::Config, source))?;
Ok(SecretBytes::new(decoded))
}
}