use crate::error::{Error, Result};
use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
pub(crate) fn decode_bytes(input: &str, max_size: usize) -> Result<Vec<u8>> {
let result = URL_SAFE_NO_PAD
.decode(input)
.map_err(|e| Error::FormatInvalidBase64(format!("Base64URL decode failed: {e}")))?;
if result.len() > max_size {
return Err(Error::FormatInvalidBase64(format!(
"Decoded size exceeds limit: {} bytes (max: {})",
result.len(),
max_size
)));
}
Ok(result)
}
pub(crate) fn decode_string(input: &str, max_size: usize) -> Result<String> {
decode_bytes(input, max_size).and_then(|bytes| {
String::from_utf8(bytes)
.map_err(|e| Error::FormatInvalidBase64(format!("Invalid UTF-8: {e}")))
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decode_invalid() {
assert!(decode_bytes("!!!", 1000).is_err());
assert!(decode_bytes("SGVsbG8=", 1000).is_err()); }
#[test]
fn test_decode_valid() {
let result = decode_bytes("SGVsbG8", 1000).unwrap();
assert_eq!(result, b"Hello");
}
#[test]
fn test_decode_with_limit() {
let result = decode_bytes("SGVsbG8", 10).unwrap();
assert_eq!(result, b"Hello");
assert!(decode_bytes("SGVsbG8", 3).is_err());
}
#[test]
fn test_decode_empty() {
assert_eq!(decode_bytes("", 1000).unwrap(), Vec::<u8>::new());
assert_eq!(decode_bytes("", 10).unwrap(), Vec::<u8>::new());
}
#[test]
fn test_decode_string() {
let result = decode_string("SGVsbG8", 10).unwrap();
assert_eq!(result, "Hello");
assert!(decode_string("SGVsbG8", 3).is_err());
}
}