use ::base64::Engine;
use ::base64::engine::general_purpose::{
STANDARD,
STANDARD_NO_PAD,
URL_SAFE,
URL_SAFE_NO_PAD,
};
use crate::{
CodecError,
CodecResult,
Decoder,
Encoder,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Base64Codec {
url_safe: bool,
padding: bool,
}
impl Base64Codec {
pub fn standard() -> Self {
Self {
url_safe: false,
padding: true,
}
}
pub fn standard_no_pad() -> Self {
Self {
url_safe: false,
padding: false,
}
}
pub fn url_safe() -> Self {
Self {
url_safe: true,
padding: true,
}
}
pub fn url_safe_no_pad() -> Self {
Self {
url_safe: true,
padding: false,
}
}
pub fn encode(&self, bytes: &[u8]) -> String {
self.engine().encode(bytes)
}
pub fn decode(&self, text: &str) -> CodecResult<Vec<u8>> {
self.engine().decode(text).map_err(CodecError::from)
}
fn engine(&self) -> &'static ::base64::engine::GeneralPurpose {
match (self.url_safe, self.padding) {
(false, true) => &STANDARD,
(false, false) => &STANDARD_NO_PAD,
(true, true) => &URL_SAFE,
(true, false) => &URL_SAFE_NO_PAD,
}
}
}
impl Default for Base64Codec {
fn default() -> Self {
Self::standard()
}
}
impl Encoder<[u8]> for Base64Codec {
type Error = CodecError;
type Output = String;
fn encode(&self, input: &[u8]) -> Result<Self::Output, Self::Error> {
Ok(Base64Codec::encode(self, input))
}
}
impl Decoder<str> for Base64Codec {
type Error = CodecError;
type Output = Vec<u8>;
fn decode(&self, input: &str) -> Result<Self::Output, Self::Error> {
Base64Codec::decode(self, input)
}
}