ass_core/plugin/sections/
aegisub.rs1use crate::plugin::{SectionProcessor, SectionResult};
19use alloc::string::String;
20
21pub struct AegisubProjectProcessor;
26
27impl SectionProcessor for AegisubProjectProcessor {
28 fn name(&self) -> &'static str {
29 "Aegisub Project"
30 }
31
32 fn process(&self, header: &str, lines: &[&str]) -> SectionResult {
33 if !header.eq_ignore_ascii_case("Aegisub Project") {
34 return SectionResult::Ignored;
35 }
36
37 for line in lines {
39 let line = line.trim();
40 if line.is_empty() || line.starts_with('!') {
41 continue;
42 }
43
44 if !line.contains('=') && !line.contains(':') {
46 return SectionResult::Failed(String::from(
47 "Invalid Aegisub project line format (expected key=value or key: value)",
48 ));
49 }
50 }
51
52 SectionResult::Processed
53 }
54
55 fn validate(&self, header: &str, lines: &[&str]) -> bool {
56 header.eq_ignore_ascii_case("Aegisub Project") && !lines.is_empty()
57 }
58}
59
60pub struct AegisubExtradataProcessor;
65
66impl SectionProcessor for AegisubExtradataProcessor {
67 fn name(&self) -> &'static str {
68 "Aegisub Extradata"
69 }
70
71 fn process(&self, header: &str, lines: &[&str]) -> SectionResult {
72 if !header.eq_ignore_ascii_case("Aegisub Extradata") {
73 return SectionResult::Ignored;
74 }
75
76 for line in lines {
78 let line = line.trim();
79 if line.is_empty() {
80 continue;
81 }
82
83 if line.len() > 10000 {
86 return SectionResult::Failed(String::from(
87 "Extradata line exceeds maximum length",
88 ));
89 }
90 }
91
92 SectionResult::Processed
93 }
94
95 fn validate(&self, header: &str, _lines: &[&str]) -> bool {
96 header.eq_ignore_ascii_case("Aegisub Extradata")
97 }
98}
99
100#[must_use]
116pub fn create_aegisub_processors() -> alloc::vec::Vec<alloc::boxed::Box<dyn SectionProcessor>> {
117 alloc::vec![
118 alloc::boxed::Box::new(AegisubProjectProcessor),
119 alloc::boxed::Box::new(AegisubExtradataProcessor),
120 ]
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 #[cfg(not(feature = "std"))]
127 use alloc::vec;
128
129 #[test]
130 fn aegisub_project_processor_valid() {
131 let processor = AegisubProjectProcessor;
132 let lines = vec!["Active Line: 0", "Video Position: 0"];
133
134 assert_eq!(
135 processor.process("Aegisub Project", &lines),
136 SectionResult::Processed
137 );
138 }
139
140 #[test]
141 fn aegisub_project_processor_invalid_header() {
142 let processor = AegisubProjectProcessor;
143 let lines = vec!["Active Line: 0"];
144
145 assert_eq!(
146 processor.process("Wrong Header", &lines),
147 SectionResult::Ignored
148 );
149 }
150
151 #[test]
152 fn aegisub_project_processor_invalid_format() {
153 let processor = AegisubProjectProcessor;
154 let lines = vec!["Invalid line without equals"];
155
156 assert!(matches!(
157 processor.process("Aegisub Project", &lines),
158 SectionResult::Failed(_)
159 ));
160 }
161
162 #[test]
163 fn aegisub_extradata_processor_valid() {
164 let processor = AegisubExtradataProcessor;
165 let lines = vec!["Data: some_binary_data", "More: extra_info"];
166
167 assert_eq!(
168 processor.process("Aegisub Extradata", &lines),
169 SectionResult::Processed
170 );
171 }
172
173 #[test]
174 fn aegisub_extradata_processor_long_line() {
175 let processor = AegisubExtradataProcessor;
176 let long_line = "x".repeat(20000);
177 let lines = vec![long_line.as_str()];
178
179 assert!(matches!(
180 processor.process("Aegisub Extradata", &lines),
181 SectionResult::Failed(_)
182 ));
183 }
184
185 #[test]
186 fn processor_names_correct() {
187 assert_eq!(AegisubProjectProcessor.name(), "Aegisub Project");
188 assert_eq!(AegisubExtradataProcessor.name(), "Aegisub Extradata");
189 }
190
191 #[test]
192 fn create_aegisub_processors_returns_two() {
193 let processors = create_aegisub_processors();
194 assert_eq!(processors.len(), 2);
195 }
196
197 #[test]
198 fn case_insensitive_headers() {
199 let processor = AegisubProjectProcessor;
200 let lines = vec!["Active Line: 0"];
201
202 assert_eq!(
203 processor.process("aegisub project", &lines),
204 SectionResult::Processed
205 );
206 assert_eq!(
207 processor.process("AEGISUB PROJECT", &lines),
208 SectionResult::Processed
209 );
210 }
211}