use base64::Engine;
use base64::engine::general_purpose::STANDARD;
pub fn maybe_decode_base64(input: &str) -> String {
if input.is_empty() {
return String::new();
}
match STANDARD.decode(input.trim()) {
Ok(bytes) => match String::from_utf8(bytes) {
Ok(decoded) => {
let control_count = decoded
.chars()
.filter(|c| c.is_control() && *c != '\n')
.count();
if decoded.len() > 4 && control_count > decoded.len() / 4 {
input.to_string()
} else {
decoded
}
}
Err(_) => input.to_string(),
},
Err(_) => input.to_string(),
}
}
pub fn decode_epg_field(field: &Option<String>) -> Option<String> {
field.as_ref().map(|s| maybe_decode_base64(s))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decodes_valid_base64() {
assert_eq!(maybe_decode_base64("TmV3cw=="), "News");
}
#[test]
fn decodes_base64_description() {
assert_eq!(maybe_decode_base64("RGFpbHkgbmV3cw=="), "Daily news");
}
#[test]
fn returns_plain_text_unchanged() {
assert_eq!(maybe_decode_base64("Just plain text"), "Just plain text");
}
#[test]
fn handles_empty_string() {
assert_eq!(maybe_decode_base64(""), "");
}
#[test]
fn handles_unicode_plain_text() {
let text = "Programme en fran\u{00e7}ais";
assert_eq!(maybe_decode_base64(text), text);
}
#[test]
fn decode_epg_field_some() {
let field = Some("TmV3cw==".to_string());
assert_eq!(decode_epg_field(&field), Some("News".to_string()));
}
#[test]
fn decode_epg_field_none() {
assert_eq!(decode_epg_field(&None), None);
}
#[test]
fn decodes_base64_with_whitespace() {
assert_eq!(maybe_decode_base64(" TmV3cw== "), "News");
}
}