use base64::engine::general_purpose::STANDARD;
use base64::engine::general_purpose::STANDARD_NO_PAD;
use base64::Engine;
use crate::crypto::CryptoError;
pub fn base64_encode(bytes: &[u8]) -> String {
STANDARD.encode(bytes)
}
pub fn base64_decode(s: &str) -> Result<Vec<u8>, CryptoError> {
if s.contains('=') {
STANDARD
.decode(s.as_bytes())
.map_err(|e| CryptoError::Base64(e.to_string()))
} else {
STANDARD_NO_PAD
.decode(s.as_bytes())
.map_err(|e| CryptoError::Base64(e.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_round_trip() {
assert_eq!(base64_encode(b""), "");
assert_eq!(base64_decode("").unwrap(), Vec::<u8>::new());
}
#[test]
fn standard_vectors() {
assert_eq!(base64_encode(b"f"), "Zg==");
assert_eq!(base64_encode(b"fo"), "Zm8=");
assert_eq!(base64_encode(b"foo"), "Zm9v");
assert_eq!(base64_encode(b"foob"), "Zm9vYg==");
assert_eq!(base64_encode(b"fooba"), "Zm9vYmE=");
assert_eq!(base64_encode(b"foobar"), "Zm9vYmFy");
}
#[test]
fn unpadded_decodes_too() {
assert_eq!(base64_decode("Zg").unwrap(), b"f");
assert_eq!(base64_decode("Zm8").unwrap(), b"fo");
}
#[test]
fn invalid_input_errors() {
assert!(base64_decode("@@@").is_err());
assert!(base64_decode("####").is_err());
}
}