use xberg::XbergError;
pub fn is_plain_text_format(mime: &str) -> bool {
let mime = mime.split(';').next().unwrap_or("").trim().to_ascii_lowercase();
if mime.is_empty() || mime.contains("vnd.") {
return false;
}
mime.starts_with("text/")
|| mime.ends_with("+xml")
|| mime.ends_with("+json")
|| matches!(
mime.as_str(),
"application/json"
| "application/xml"
| "application/yaml"
| "application/x-yaml"
| "application/toml"
| "application/x-toml"
| "application/csv"
)
}
pub fn should_retry_as_text(mime: Option<&str>, error: &XbergError) -> bool {
let Some(mime) = mime else { return false };
if mime
.split(';')
.next()
.unwrap_or("")
.trim()
.eq_ignore_ascii_case("text/plain")
{
return false;
}
is_plain_text_format(mime) && matches!(error, XbergError::Parsing { .. } | XbergError::Security { .. })
}
#[cfg(test)]
mod tests {
use super::*;
fn parsing() -> XbergError {
XbergError::parsing("Failed to parse YAML")
}
#[test]
fn text_like_formats_are_eligible_and_binary_ones_are_not() {
for mime in [
"application/x-yaml",
"text/yaml",
"text/csv",
"image/svg+xml",
"application/json",
"text/html; charset=utf-8",
"application/toml",
] {
assert!(is_plain_text_format(mime), "{mime}");
}
for mime in [
"application/pdf",
"image/png",
"application/zip",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.oasis.opendocument.text",
"",
] {
assert!(!is_plain_text_format(mime), "{mime}");
}
}
#[test]
fn only_parse_and_security_errors_on_text_formats_retry() {
assert!(should_retry_as_text(Some("application/x-yaml"), &parsing()));
assert!(should_retry_as_text(
Some("text/csv"),
&XbergError::security("Table cell limit exceeded")
));
assert!(!should_retry_as_text(Some("application/pdf"), &parsing()));
assert!(!should_retry_as_text(Some("text/plain"), &parsing()));
assert!(!should_retry_as_text(None, &parsing()));
let io = XbergError::Io(std::io::Error::other("disk"));
assert!(!should_retry_as_text(Some("text/csv"), &io));
assert!(!should_retry_as_text(
Some("text/csv"),
&XbergError::validation("bad config")
));
}
}