use crate::core::{EditorError, Result};
use crate::extensions::EditorExtension;
use ass_core::plugin::{ExtensionRegistry, SectionProcessor, SectionResult, TagHandler, TagResult};
#[cfg(not(feature = "std"))]
use alloc::{
boxed::Box,
format,
string::{String, ToString},
vec::Vec,
};
pub struct RegistryIntegration {
registry: ExtensionRegistry,
tag_providers: Vec<Box<dyn EditorExtension>>,
section_providers: Vec<Box<dyn EditorExtension>>,
}
impl core::fmt::Debug for RegistryIntegration {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("RegistryIntegration")
.field("registry", &self.registry)
.field(
"tag_providers",
&format!("{} providers", self.tag_providers.len()),
)
.field(
"section_providers",
&format!("{} providers", self.section_providers.len()),
)
.finish()
}
}
impl RegistryIntegration {
pub fn new() -> Self {
Self {
registry: ExtensionRegistry::new(),
tag_providers: Vec::new(),
section_providers: Vec::new(),
}
}
pub fn register_builtin_handlers(&mut self) -> Result<()> {
use ass_core::plugin::tags::*;
for handler in formatting::create_formatting_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register formatting handler: {e}"),
}
})?;
}
for handler in special::create_special_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register special handler: {e}"),
}
})?;
}
for handler in font::create_font_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register font handler: {e}"),
}
})?;
}
for handler in advanced::create_advanced_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register advanced handler: {e}"),
}
})?;
}
for handler in alignment::create_alignment_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register alignment handler: {e}"),
}
})?;
}
for handler in karaoke::create_karaoke_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register karaoke handler: {e}"),
}
})?;
}
for handler in position::create_position_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register position handler: {e}"),
}
})?;
}
for handler in color::create_color_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register color handler: {e}"),
}
})?;
}
for handler in transform::create_transform_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register transform handler: {e}"),
}
})?;
}
for handler in animation::create_animation_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register animation handler: {e}"),
}
})?;
}
for handler in clipping::create_clipping_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register clipping handler: {e}"),
}
})?;
}
for handler in misc::create_misc_handlers() {
self.registry.register_tag_handler(handler).map_err(|e| {
EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register misc handler: {e}"),
}
})?;
}
Ok(())
}
pub fn register_builtin_sections(&mut self) -> Result<()> {
use ass_core::plugin::sections::*;
self.registry
.register_section_processor(Box::new(aegisub::AegisubProjectProcessor))
.map_err(|e| EditorError::ExtensionError {
extension: "builtin".to_string(),
message: format!("Failed to register Aegisub section processor: {e}"),
})?;
Ok(())
}
pub fn registry(&self) -> &ExtensionRegistry {
&self.registry
}
pub fn registry_mut(&mut self) -> &mut ExtensionRegistry {
&mut self.registry
}
pub fn register_custom_tag_handler(
&mut self,
extension_name: String,
handler: Box<dyn TagHandler>,
) -> Result<()> {
self.registry
.register_tag_handler(handler)
.map_err(|e| EditorError::ExtensionError {
extension: extension_name,
message: format!("Failed to register tag handler: {e}"),
})
}
pub fn register_custom_section_processor(
&mut self,
extension_name: String,
processor: Box<dyn SectionProcessor>,
) -> Result<()> {
self.registry
.register_section_processor(processor)
.map_err(|e| EditorError::ExtensionError {
extension: extension_name,
message: format!("Failed to register section processor: {e}"),
})
}
}
#[allow(dead_code)]
pub struct EditorTagHandlerAdapter {
extension_name: String,
tag_name: String,
extension: Box<dyn EditorExtension>,
}
impl EditorTagHandlerAdapter {
pub fn new(
extension_name: String,
tag_name: String,
extension: Box<dyn EditorExtension>,
) -> Self {
Self {
extension_name,
tag_name,
extension,
}
}
}
impl TagHandler for EditorTagHandlerAdapter {
fn name(&self) -> &'static str {
Box::leak(self.tag_name.clone().into_boxed_str())
}
fn process(&self, _args: &str) -> TagResult {
TagResult::Processed
}
fn validate(&self, args: &str) -> bool {
!args.is_empty()
}
}
#[allow(dead_code)]
pub struct EditorSectionProcessorAdapter {
extension_name: String,
section_name: String,
extension: Box<dyn EditorExtension>,
}
impl EditorSectionProcessorAdapter {
pub fn new(
extension_name: String,
section_name: String,
extension: Box<dyn EditorExtension>,
) -> Self {
Self {
extension_name,
section_name,
extension,
}
}
}
impl SectionProcessor for EditorSectionProcessorAdapter {
fn name(&self) -> &'static str {
Box::leak(self.section_name.clone().into_boxed_str())
}
fn process(&self, _header: &str, _lines: &[&str]) -> SectionResult {
SectionResult::Processed
}
fn validate(&self, header: &str, lines: &[&str]) -> bool {
!header.is_empty() && !lines.is_empty()
}
}
impl Default for RegistryIntegration {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(not(feature = "std"))]
use alloc::string::ToString;
#[test]
fn test_registry_integration_creation() {
let integration = RegistryIntegration::new();
assert!(integration.tag_providers.is_empty());
assert!(integration.section_providers.is_empty());
}
#[test]
fn test_register_builtin_handlers() {
let mut integration = RegistryIntegration::new();
assert!(integration.register_builtin_handlers().is_ok());
}
#[test]
fn test_register_builtin_sections() {
let mut integration = RegistryIntegration::new();
assert!(integration.register_builtin_sections().is_ok());
}
#[test]
fn test_custom_tag_handler_registration() {
use ass_core::plugin::{TagHandler, TagResult};
struct TestTagHandler;
impl TagHandler for TestTagHandler {
fn name(&self) -> &'static str {
"test"
}
fn process(&self, _args: &str) -> TagResult {
TagResult::Processed
}
fn validate(&self, _args: &str) -> bool {
true
}
}
let mut integration = RegistryIntegration::new();
let handler = Box::new(TestTagHandler);
assert!(integration
.register_custom_tag_handler("test-extension".to_string(), handler)
.is_ok());
}
#[test]
fn test_custom_section_processor_registration() {
use ass_core::plugin::{SectionProcessor, SectionResult};
struct TestSectionProcessor;
impl SectionProcessor for TestSectionProcessor {
fn name(&self) -> &'static str {
"TestSection"
}
fn process(&self, _header: &str, _lines: &[&str]) -> SectionResult {
SectionResult::Processed
}
fn validate(&self, _header: &str, _lines: &[&str]) -> bool {
true
}
}
let mut integration = RegistryIntegration::new();
let processor = Box::new(TestSectionProcessor);
assert!(integration
.register_custom_section_processor("test-extension".to_string(), processor)
.is_ok());
}
#[test]
fn test_registry_access() {
let integration = RegistryIntegration::new();
let _registry = integration.registry();
let mut integration = RegistryIntegration::new();
let _registry_mut = integration.registry_mut();
}
#[test]
fn test_full_integration() {
let mut integration = RegistryIntegration::new();
assert!(integration.register_builtin_handlers().is_ok());
assert!(integration.register_builtin_sections().is_ok());
let registry = integration.registry();
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";
let result = ass_core::parser::Script::builder()
.with_registry(registry)
.parse(test_content);
assert!(result.is_ok());
}
}