use std::collections::HashMap;
#[derive(Debug, Default, Clone)]
pub struct ContentDisposition {
variables: HashMap<String, String>,
is_file_field: bool,
has_name_field: bool,
}
pub struct ContentDispositionParseResult {
pub variables: HashMap<String, String>,
pub is_file_field: bool,
pub has_name_field: bool,
}
#[allow(dead_code)]
impl ContentDisposition {
pub fn create(content_disposition: &str) -> Self {
let result = Self::parse(content_disposition);
Self {
variables: result.variables,
is_file_field: result.is_file_field,
has_name_field: result.has_name_field,
}
}
pub fn get_variable(&self, key: &str) -> Option<&str> {
self.variables.get(key).map(|v| v.as_str())
}
pub fn get_variables(&self) -> &HashMap<String, String> {
&self.variables
}
pub fn is_file_field(&self) -> bool {
self.is_file_field
}
pub fn has_name_field(&self) -> bool {
self.has_name_field
}
pub fn get_name(&self) -> Option<&str> {
self.get_variable("name")
}
pub fn get_filename(&self) -> Option<&str> {
self.get_variable("filename")
}
pub fn parse(content_disposition: &str) -> ContentDispositionParseResult {
let mut variables = HashMap::new();
for part in content_disposition.split(';') {
let part = part.trim();
if let Some((key, value)) = part.split_once('=') {
let key = key.trim().to_string();
let value = value.trim().trim_matches('"').to_string();
variables.insert(key, value);
}
}
ContentDispositionParseResult {
is_file_field: variables.contains_key("filename"),
has_name_field: variables.contains_key("name"),
variables,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_valid_disposition() {
let content_disposition = "form-data; name=\"file\"; filename=\"example.txt\"";
let content = ContentDisposition::create(content_disposition);
assert_eq!(content.get_variable("name"), Some("file"));
assert_eq!(content.get_variable("filename"), Some("example.txt"));
assert!(content.is_file_field());
assert!(content.has_name_field());
}
#[test]
fn test_create_no_filename() {
let content_disposition = "form-data; name=\"file\"";
let content = ContentDisposition::create(content_disposition);
assert_eq!(content.get_variable("name"), Some("file"));
assert_eq!(content.get_variable("filename"), None);
assert!(!content.is_file_field());
assert!(content.has_name_field());
}
#[test]
fn test_create_empty_disposition() {
let content_disposition = "";
let content = ContentDisposition::create(content_disposition);
assert!(content.get_variables().is_empty());
assert!(!content.is_file_field());
assert!(!content.has_name_field());
}
#[test]
fn test_parse_multiple_parameters() {
let content_disposition =
"form-data; name=\"file\"; filename=\"example.txt\"; another_param=\"value\"";
let result = ContentDisposition::parse(content_disposition);
assert_eq!(result.variables.get("name"), Some(&"file".to_string()));
assert_eq!(
result.variables.get("filename"),
Some(&"example.txt".to_string())
);
assert_eq!(
result.variables.get("another_param"),
Some(&"value".to_string())
);
assert!(result.is_file_field);
assert!(result.has_name_field);
}
#[test]
fn test_parse_name_only() {
let content_disposition = "form-data; name=\"file\"";
let result = ContentDisposition::parse(content_disposition);
assert_eq!(result.variables.get("name"), Some(&"file".to_string()));
assert!(!result.is_file_field);
assert!(result.has_name_field);
}
#[test]
fn test_parse_filename_only() {
let content_disposition = "form-data; filename=\"example.txt\"";
let result = ContentDisposition::parse(content_disposition);
assert_eq!(
result.variables.get("filename"),
Some(&"example.txt".to_string())
);
assert!(result.is_file_field);
assert!(!result.has_name_field);
}
#[test]
fn test_parse_no_fields() {
let content_disposition = "form-data";
let result = ContentDisposition::parse(content_disposition);
assert!(result.variables.is_empty());
assert!(!result.is_file_field);
assert!(!result.has_name_field);
}
#[test]
fn test_parse_quoted_values() {
let content_disposition = r#"form-data; name="some name"; filename="test.txt""#;
let result = ContentDisposition::parse(content_disposition);
assert_eq!(result.variables.get("name"), Some(&"some name".to_string()));
assert_eq!(
result.variables.get("filename"),
Some(&"test.txt".to_string())
);
assert!(result.is_file_field);
assert!(result.has_name_field);
}
#[test]
fn test_get_variable() {
let content_disposition = "form-data; name=\"file\"; filename=\"example.txt\"";
let content = ContentDisposition::create(content_disposition);
assert_eq!(content.get_variable("name"), Some("file"));
assert_eq!(content.get_variable("filename"), Some("example.txt"));
assert_eq!(content.get_variable("nonexistent"), None);
}
#[test]
fn test_get_variables() {
let content_disposition = "form-data; name=\"file\"; filename=\"example.txt\"";
let content = ContentDisposition::create(content_disposition);
let variables = content.get_variables();
assert_eq!(variables.get("name"), Some(&"file".to_string()));
assert_eq!(variables.get("filename"), Some(&"example.txt".to_string()));
}
#[test]
fn test_parse_with_spaces() {
let content_disposition = " form-data ; name = \"file\" ; filename = \"example.txt\" ";
let result = ContentDisposition::parse(content_disposition);
assert_eq!(result.variables.get("name"), Some(&"file".to_string()));
assert_eq!(
result.variables.get("filename"),
Some(&"example.txt".to_string())
);
}
}