1use crate::core::{EditorError, Result};
8use crate::extensions::EditorExtension;
9use ass_core::plugin::{ExtensionRegistry, SectionProcessor, SectionResult, TagHandler, TagResult};
10
11#[cfg(not(feature = "std"))]
12use alloc::{
13 boxed::Box,
14 format,
15 string::{String, ToString},
16 vec::Vec,
17};
18
19pub struct RegistryIntegration {
21 registry: ExtensionRegistry,
23 tag_providers: Vec<Box<dyn EditorExtension>>,
25 section_providers: Vec<Box<dyn EditorExtension>>,
27}
28
29impl core::fmt::Debug for RegistryIntegration {
30 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
31 f.debug_struct("RegistryIntegration")
32 .field("registry", &self.registry)
33 .field(
34 "tag_providers",
35 &format!("{} providers", self.tag_providers.len()),
36 )
37 .field(
38 "section_providers",
39 &format!("{} providers", self.section_providers.len()),
40 )
41 .finish()
42 }
43}
44
45impl RegistryIntegration {
46 pub fn new() -> Self {
48 Self {
49 registry: ExtensionRegistry::new(),
50 tag_providers: Vec::new(),
51 section_providers: Vec::new(),
52 }
53 }
54
55 pub fn register_builtin_handlers(&mut self) -> Result<()> {
57 use ass_core::plugin::tags::*;
58
59 for handler in formatting::create_formatting_handlers() {
61 self.registry.register_tag_handler(handler).map_err(|e| {
62 EditorError::ExtensionError {
63 extension: "builtin".to_string(),
64 message: format!("Failed to register formatting handler: {e}"),
65 }
66 })?;
67 }
68
69 for handler in special::create_special_handlers() {
71 self.registry.register_tag_handler(handler).map_err(|e| {
72 EditorError::ExtensionError {
73 extension: "builtin".to_string(),
74 message: format!("Failed to register special handler: {e}"),
75 }
76 })?;
77 }
78
79 for handler in font::create_font_handlers() {
81 self.registry.register_tag_handler(handler).map_err(|e| {
82 EditorError::ExtensionError {
83 extension: "builtin".to_string(),
84 message: format!("Failed to register font handler: {e}"),
85 }
86 })?;
87 }
88
89 for handler in advanced::create_advanced_handlers() {
91 self.registry.register_tag_handler(handler).map_err(|e| {
92 EditorError::ExtensionError {
93 extension: "builtin".to_string(),
94 message: format!("Failed to register advanced handler: {e}"),
95 }
96 })?;
97 }
98
99 for handler in alignment::create_alignment_handlers() {
101 self.registry.register_tag_handler(handler).map_err(|e| {
102 EditorError::ExtensionError {
103 extension: "builtin".to_string(),
104 message: format!("Failed to register alignment handler: {e}"),
105 }
106 })?;
107 }
108
109 for handler in karaoke::create_karaoke_handlers() {
111 self.registry.register_tag_handler(handler).map_err(|e| {
112 EditorError::ExtensionError {
113 extension: "builtin".to_string(),
114 message: format!("Failed to register karaoke handler: {e}"),
115 }
116 })?;
117 }
118
119 for handler in position::create_position_handlers() {
121 self.registry.register_tag_handler(handler).map_err(|e| {
122 EditorError::ExtensionError {
123 extension: "builtin".to_string(),
124 message: format!("Failed to register position handler: {e}"),
125 }
126 })?;
127 }
128
129 for handler in color::create_color_handlers() {
131 self.registry.register_tag_handler(handler).map_err(|e| {
132 EditorError::ExtensionError {
133 extension: "builtin".to_string(),
134 message: format!("Failed to register color handler: {e}"),
135 }
136 })?;
137 }
138
139 for handler in transform::create_transform_handlers() {
141 self.registry.register_tag_handler(handler).map_err(|e| {
142 EditorError::ExtensionError {
143 extension: "builtin".to_string(),
144 message: format!("Failed to register transform handler: {e}"),
145 }
146 })?;
147 }
148
149 for handler in animation::create_animation_handlers() {
151 self.registry.register_tag_handler(handler).map_err(|e| {
152 EditorError::ExtensionError {
153 extension: "builtin".to_string(),
154 message: format!("Failed to register animation handler: {e}"),
155 }
156 })?;
157 }
158
159 for handler in clipping::create_clipping_handlers() {
161 self.registry.register_tag_handler(handler).map_err(|e| {
162 EditorError::ExtensionError {
163 extension: "builtin".to_string(),
164 message: format!("Failed to register clipping handler: {e}"),
165 }
166 })?;
167 }
168
169 for handler in misc::create_misc_handlers() {
171 self.registry.register_tag_handler(handler).map_err(|e| {
172 EditorError::ExtensionError {
173 extension: "builtin".to_string(),
174 message: format!("Failed to register misc handler: {e}"),
175 }
176 })?;
177 }
178
179 Ok(())
180 }
181
182 pub fn register_builtin_sections(&mut self) -> Result<()> {
184 use ass_core::plugin::sections::*;
185
186 self.registry
188 .register_section_processor(Box::new(aegisub::AegisubProjectProcessor))
189 .map_err(|e| EditorError::ExtensionError {
190 extension: "builtin".to_string(),
191 message: format!("Failed to register Aegisub section processor: {e}"),
192 })?;
193
194 Ok(())
195 }
196
197 pub fn registry(&self) -> &ExtensionRegistry {
199 &self.registry
200 }
201
202 pub fn registry_mut(&mut self) -> &mut ExtensionRegistry {
204 &mut self.registry
205 }
206
207 pub fn register_custom_tag_handler(
209 &mut self,
210 extension_name: String,
211 handler: Box<dyn TagHandler>,
212 ) -> Result<()> {
213 self.registry
214 .register_tag_handler(handler)
215 .map_err(|e| EditorError::ExtensionError {
216 extension: extension_name,
217 message: format!("Failed to register tag handler: {e}"),
218 })
219 }
220
221 pub fn register_custom_section_processor(
223 &mut self,
224 extension_name: String,
225 processor: Box<dyn SectionProcessor>,
226 ) -> Result<()> {
227 self.registry
228 .register_section_processor(processor)
229 .map_err(|e| EditorError::ExtensionError {
230 extension: extension_name,
231 message: format!("Failed to register section processor: {e}"),
232 })
233 }
234}
235
236#[allow(dead_code)]
238pub struct EditorTagHandlerAdapter {
239 extension_name: String,
240 tag_name: String,
241 extension: Box<dyn EditorExtension>,
242}
243
244impl EditorTagHandlerAdapter {
245 pub fn new(
247 extension_name: String,
248 tag_name: String,
249 extension: Box<dyn EditorExtension>,
250 ) -> Self {
251 Self {
252 extension_name,
253 tag_name,
254 extension,
255 }
256 }
257}
258
259impl TagHandler for EditorTagHandlerAdapter {
260 fn name(&self) -> &'static str {
261 Box::leak(self.tag_name.clone().into_boxed_str())
263 }
264
265 fn process(&self, _args: &str) -> TagResult {
266 TagResult::Processed
269 }
270
271 fn validate(&self, args: &str) -> bool {
272 !args.is_empty()
273 }
274}
275
276#[allow(dead_code)]
278pub struct EditorSectionProcessorAdapter {
279 extension_name: String,
280 section_name: String,
281 extension: Box<dyn EditorExtension>,
282}
283
284impl EditorSectionProcessorAdapter {
285 pub fn new(
287 extension_name: String,
288 section_name: String,
289 extension: Box<dyn EditorExtension>,
290 ) -> Self {
291 Self {
292 extension_name,
293 section_name,
294 extension,
295 }
296 }
297}
298
299impl SectionProcessor for EditorSectionProcessorAdapter {
300 fn name(&self) -> &'static str {
301 Box::leak(self.section_name.clone().into_boxed_str())
303 }
304
305 fn process(&self, _header: &str, _lines: &[&str]) -> SectionResult {
306 SectionResult::Processed
309 }
310
311 fn validate(&self, header: &str, lines: &[&str]) -> bool {
312 !header.is_empty() && !lines.is_empty()
313 }
314}
315
316impl Default for RegistryIntegration {
317 fn default() -> Self {
318 Self::new()
319 }
320}
321
322#[cfg(test)]
323mod tests {
324 use super::*;
325 #[cfg(not(feature = "std"))]
326 use alloc::string::ToString;
327
328 #[test]
329 fn test_registry_integration_creation() {
330 let integration = RegistryIntegration::new();
331 assert!(integration.tag_providers.is_empty());
332 assert!(integration.section_providers.is_empty());
333 }
334
335 #[test]
336 fn test_register_builtin_handlers() {
337 let mut integration = RegistryIntegration::new();
338
339 assert!(integration.register_builtin_handlers().is_ok());
341 }
342
343 #[test]
344 fn test_register_builtin_sections() {
345 let mut integration = RegistryIntegration::new();
346
347 assert!(integration.register_builtin_sections().is_ok());
349 }
350
351 #[test]
352 fn test_custom_tag_handler_registration() {
353 use ass_core::plugin::{TagHandler, TagResult};
354
355 struct TestTagHandler;
356 impl TagHandler for TestTagHandler {
357 fn name(&self) -> &'static str {
358 "test"
359 }
360
361 fn process(&self, _args: &str) -> TagResult {
362 TagResult::Processed
363 }
364
365 fn validate(&self, _args: &str) -> bool {
366 true
367 }
368 }
369
370 let mut integration = RegistryIntegration::new();
371 let handler = Box::new(TestTagHandler);
372
373 assert!(integration
374 .register_custom_tag_handler("test-extension".to_string(), handler)
375 .is_ok());
376 }
377
378 #[test]
379 fn test_custom_section_processor_registration() {
380 use ass_core::plugin::{SectionProcessor, SectionResult};
381
382 struct TestSectionProcessor;
383 impl SectionProcessor for TestSectionProcessor {
384 fn name(&self) -> &'static str {
385 "TestSection"
386 }
387
388 fn process(&self, _header: &str, _lines: &[&str]) -> SectionResult {
389 SectionResult::Processed
390 }
391
392 fn validate(&self, _header: &str, _lines: &[&str]) -> bool {
393 true
394 }
395 }
396
397 let mut integration = RegistryIntegration::new();
398 let processor = Box::new(TestSectionProcessor);
399
400 assert!(integration
401 .register_custom_section_processor("test-extension".to_string(), processor)
402 .is_ok());
403 }
404
405 #[test]
406 fn test_registry_access() {
407 let integration = RegistryIntegration::new();
408
409 let _registry = integration.registry();
411
412 let mut integration = RegistryIntegration::new();
414 let _registry_mut = integration.registry_mut();
415 }
416
417 #[test]
418 fn test_full_integration() {
419 let mut integration = RegistryIntegration::new();
420
421 assert!(integration.register_builtin_handlers().is_ok());
423 assert!(integration.register_builtin_sections().is_ok());
424
425 let registry = integration.registry();
428
429 let test_content = "[Script Info]\nTitle: Test\n\n[Events]\nDialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,,{\\b1}Bold{\\b0} text";
431
432 let result = ass_core::parser::Script::builder()
434 .with_registry(registry)
435 .parse(test_content);
436
437 assert!(result.is_ok());
438 }
439}