use crate::plugin::{SectionProcessor, SectionResult};
use alloc::string::String;
pub struct AegisubProjectProcessor;
impl SectionProcessor for AegisubProjectProcessor {
fn name(&self) -> &'static str {
"Aegisub Project"
}
fn process(&self, header: &str, lines: &[&str]) -> SectionResult {
if !header.eq_ignore_ascii_case("Aegisub Project") {
return SectionResult::Ignored;
}
for line in lines {
let line = line.trim();
if line.is_empty() || line.starts_with('!') {
continue;
}
if !line.contains('=') && !line.contains(':') {
return SectionResult::Failed(String::from(
"Invalid Aegisub project line format (expected key=value or key: value)",
));
}
}
SectionResult::Processed
}
fn validate(&self, header: &str, lines: &[&str]) -> bool {
header.eq_ignore_ascii_case("Aegisub Project") && !lines.is_empty()
}
}
pub struct AegisubExtradataProcessor;
impl SectionProcessor for AegisubExtradataProcessor {
fn name(&self) -> &'static str {
"Aegisub Extradata"
}
fn process(&self, header: &str, lines: &[&str]) -> SectionResult {
if !header.eq_ignore_ascii_case("Aegisub Extradata") {
return SectionResult::Ignored;
}
for line in lines {
let line = line.trim();
if line.is_empty() {
continue;
}
if line.len() > 10000 {
return SectionResult::Failed(String::from(
"Extradata line exceeds maximum length",
));
}
}
SectionResult::Processed
}
fn validate(&self, header: &str, _lines: &[&str]) -> bool {
header.eq_ignore_ascii_case("Aegisub Extradata")
}
}
#[must_use]
pub fn create_aegisub_processors() -> alloc::vec::Vec<alloc::boxed::Box<dyn SectionProcessor>> {
alloc::vec![
alloc::boxed::Box::new(AegisubProjectProcessor),
alloc::boxed::Box::new(AegisubExtradataProcessor),
]
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(not(feature = "std"))]
use alloc::vec;
#[test]
fn aegisub_project_processor_valid() {
let processor = AegisubProjectProcessor;
let lines = vec!["Active Line: 0", "Video Position: 0"];
assert_eq!(
processor.process("Aegisub Project", &lines),
SectionResult::Processed
);
}
#[test]
fn aegisub_project_processor_invalid_header() {
let processor = AegisubProjectProcessor;
let lines = vec!["Active Line: 0"];
assert_eq!(
processor.process("Wrong Header", &lines),
SectionResult::Ignored
);
}
#[test]
fn aegisub_project_processor_invalid_format() {
let processor = AegisubProjectProcessor;
let lines = vec!["Invalid line without equals"];
assert!(matches!(
processor.process("Aegisub Project", &lines),
SectionResult::Failed(_)
));
}
#[test]
fn aegisub_extradata_processor_valid() {
let processor = AegisubExtradataProcessor;
let lines = vec!["Data: some_binary_data", "More: extra_info"];
assert_eq!(
processor.process("Aegisub Extradata", &lines),
SectionResult::Processed
);
}
#[test]
fn aegisub_extradata_processor_long_line() {
let processor = AegisubExtradataProcessor;
let long_line = "x".repeat(20000);
let lines = vec![long_line.as_str()];
assert!(matches!(
processor.process("Aegisub Extradata", &lines),
SectionResult::Failed(_)
));
}
#[test]
fn processor_names_correct() {
assert_eq!(AegisubProjectProcessor.name(), "Aegisub Project");
assert_eq!(AegisubExtradataProcessor.name(), "Aegisub Extradata");
}
#[test]
fn create_aegisub_processors_returns_two() {
let processors = create_aegisub_processors();
assert_eq!(processors.len(), 2);
}
#[test]
fn case_insensitive_headers() {
let processor = AegisubProjectProcessor;
let lines = vec!["Active Line: 0"];
assert_eq!(
processor.process("aegisub project", &lines),
SectionResult::Processed
);
assert_eq!(
processor.process("AEGISUB PROJECT", &lines),
SectionResult::Processed
);
}
}