use base64::DecodeError;
use cdumay_error::{AsError, Error, define_errors, define_kinds};
use std::collections::BTreeMap;
define_kinds! {
Base64Decode = ("Base64-00001", 400, "Base64 decode error"),
Base64Encode = ("Base64-00002", 400, "Base64 encode error"),
}
define_errors! {
InvalidByteError = Base64Decode,
InvalidLengthError = Base64Decode,
InvalidLastSymbolError = Base64Decode,
InvalidPaddingError = Base64Decode,
}
pub struct Base64Error;
impl Base64Error {
pub fn decode_error(error: &DecodeError, text: Option<String>, context: BTreeMap<String, serde_value::Value>) -> Error {
let text = text.unwrap_or(error.to_string());
match error {
DecodeError::InvalidByte(_, _) => InvalidByteError::new().set_message(text).set_details(context).into(),
DecodeError::InvalidLength(_) => InvalidLengthError::new().set_message(text).set_details(context).into(),
DecodeError::InvalidLastSymbol(_, _) => InvalidLastSymbolError::new().set_message(text).set_details(context).into(),
DecodeError::InvalidPadding => InvalidPaddingError::new().set_message(text).set_details(context).into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use base64::{Engine as _, engine::general_purpose};
#[test]
fn test_invalid_base64_decode_error() {
let invalid_data = "!!! not base64 !!!";
let result = general_purpose::STANDARD.decode(invalid_data);
assert!(result.is_err());
let err = result.unwrap_err();
let ctx = BTreeMap::new();
let custom = Base64Error::decode_error(&err, Some("Failed to decode base64".to_string()), ctx);
assert_eq!(custom.kind.message_id(), "Base64-00001");
assert_eq!(custom.message, "Failed to decode base64");
}
#[test]
fn test_valid_base64_decoding() {
let valid_data = general_purpose::STANDARD.encode(b"hello world");
let decoded = general_purpose::STANDARD.decode(&valid_data);
assert!(decoded.is_ok());
assert_eq!(decoded.unwrap(), b"hello world");
}
}