use base64::Engine;
use prost::bytes::Bytes;
use crate::error::CoreError;
pub fn decode_base64(input: &str) -> Result<Vec<u8>, CoreError> {
base64::engine::general_purpose::STANDARD
.decode(input.trim())
.map_err(|e| CoreError::InvalidBase64(e.to_string()))
}
pub fn decode_base64_bytes(input: &str) -> Result<Bytes, CoreError> {
decode_base64(input).map(Bytes::from)
}
pub fn decode_optional_base64(input: Option<&str>) -> Result<Option<Bytes>, CoreError> {
match input {
Some(s) if !s.trim().is_empty() => decode_base64_bytes(s).map(Some),
_ => Ok(None),
}
}
pub fn decode_hex(input: &str) -> Result<Bytes, CoreError> {
hex::decode(input.trim())
.map(Bytes::from)
.map_err(|e| CoreError::InvalidHex(e.to_string()))
}
pub fn decode_optional_hex(input: Option<&str>) -> Result<Option<Bytes>, CoreError> {
match input {
Some(s) if !s.trim().is_empty() => decode_hex(s).map(Some),
_ => Ok(None),
}
}
pub fn decode_base64_or_hex(input: &str) -> Result<Bytes, CoreError> {
match base64::engine::general_purpose::STANDARD.decode(input.trim()) {
Ok(bytes) => Ok(Bytes::from(bytes)),
Err(_) => decode_hex(input),
}
}
pub fn filter_username(username: Option<&str>) -> Option<&str> {
username.map(str::trim).filter(|s| !s.is_empty())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_decode_base64() {
let encoded = "SGVsbG8gV29ybGQ="; let decoded = decode_base64(encoded).unwrap();
assert_eq!(decoded, b"Hello World");
}
#[test]
fn test_decode_base64_invalid() {
let result = decode_base64("not-valid-base64!!!");
assert!(result.is_err());
}
#[test]
fn test_decode_hex() {
let encoded = "48656c6c6f"; let decoded = decode_hex(encoded).unwrap();
assert_eq!(decoded.as_ref(), b"Hello");
}
#[test]
fn test_decode_hex_invalid() {
let result = decode_hex("not-valid-hex");
assert!(result.is_err());
}
#[test]
fn test_decode_base64_or_hex_base64() {
let encoded = "SGVsbG8="; let decoded = decode_base64_or_hex(encoded).unwrap();
assert_eq!(decoded.as_ref(), b"Hello");
}
#[test]
fn test_decode_base64_or_hex_hex() {
let encoded = "48656c6c6f"; let decoded = decode_base64_or_hex(encoded).unwrap();
assert_eq!(decoded.as_ref(), b"Hello");
}
#[test]
fn test_decode_optional_base64_none() {
let result = decode_optional_base64(None).unwrap();
assert!(result.is_none());
}
#[test]
fn test_decode_optional_base64_empty() {
let result = decode_optional_base64(Some("")).unwrap();
assert!(result.is_none());
}
#[test]
fn test_decode_optional_hex_none() {
let result = decode_optional_hex(None).unwrap();
assert!(result.is_none());
}
#[test]
fn test_decode_base64_or_hex_ambiguity() {
let decoded = decode_base64_or_hex("AABB").unwrap();
assert_eq!(decoded.as_ref(), &[0x00, 0x00, 0x41]);
assert_ne!(decoded.as_ref(), &[0xAA, 0xBB]);
}
#[test]
fn test_filter_username_valid() {
let result = filter_username(Some("user123"));
assert_eq!(result, Some("user123"));
}
#[test]
fn test_filter_username_empty() {
let result = filter_username(Some(""));
assert_eq!(result, None);
}
#[test]
fn test_filter_username_whitespace() {
let result = filter_username(Some(" "));
assert_eq!(result, None);
}
#[test]
fn test_filter_username_none() {
let result = filter_username(None);
assert_eq!(result, None);
}
}