use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct ContentType {
pub main_type: String,
pub sub_type: String,
pub parameters: HashMap<String, String>,
}
impl ContentType {
pub fn parse(content_type: &str) -> Self {
let mut parameters = HashMap::new();
let tokens: Vec<&str> = content_type.split(';').map(|s| s.trim()).collect();
let (main_type, sub_type) = if let Some(type_part) = tokens.first() {
let parts: Vec<&str> = type_part.split('/').collect();
if parts.len() == 2 {
(parts[0].to_string(), parts[1].to_string())
} else {
(type_part.to_string(), String::new())
}
} else {
(String::new(), String::new())
};
for token in tokens.iter().skip(1) {
if let Some((key, val)) = token.split_once('=') {
let val = val.trim_matches('"').to_string();
parameters.insert(key.trim().to_string(), val);
}
}
ContentType {
main_type,
sub_type,
parameters,
}
}
pub fn mime_type(&self) -> String {
format!("{}/{}", self.main_type, self.sub_type)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_simple() {
let ct = ContentType::parse("text/plain");
assert_eq!(ct.main_type, "text");
assert_eq!(ct.sub_type, "plain");
assert!(ct.parameters.is_empty());
}
#[test]
fn test_parse_with_parameters() {
let ct = ContentType::parse("image/png; name=\"test.png\"; charset=utf-8");
assert_eq!(ct.main_type, "image");
assert_eq!(ct.sub_type, "png");
assert_eq!(ct.parameters.get("name"), Some(&"test.png".to_string()));
assert_eq!(ct.parameters.get("charset"), Some(&"utf-8".to_string()));
}
}