ass_core/parser/sections/mod.rs
1//! Section-specific parsers for ASS script components.
2//!
3//! This module contains specialized parsers for each type of section in ASS scripts,
4//! breaking down the monolithic parser into focused, maintainable components that
5//! adhere to the 200 LOC limit while maintaining zero-copy performance.
6//!
7//! # Architecture
8//!
9//! Each section parser is responsible for:
10//! - Parsing its specific section format and content
11//! - Handling format specifications and field mappings
12//! - Generating appropriate parse issues for validation
13//! - Maintaining zero-copy lifetime-generic references
14//!
15//! # Performance
16//!
17//! All parsers are designed for optimal performance:
18//! - Zero allocations via lifetime-generic spans
19//! - Linear time complexity for section content
20//! - Efficient format mapping and field extraction
21//! - Minimal memory overhead during parsing
22//!
23//! # Example
24//!
25/// ```rust
26/// use ass_core::parser::sections::{ScriptInfoParser, StylesParser, EventsParser};
27/// use ass_core::CoreError;
28///
29/// let source = "[Script Info]\nTitle: Test\n\n[V4+ Styles]\nFormat: Name, Fontname\nStyle: Default,Arial\n\n[Events]\nFormat: Layer, Start, End, Text\nDialogue: 0,0:00:00.00,0:00:05.00,Hello";
30/// let start_pos = 0;
31/// let start_line = 1;
32///
33/// // Parse script info section
34/// let info_parser = ScriptInfoParser::new(source, start_pos, start_line);
35/// let (section, version, issues, pos, line) = info_parser.parse()?;
36///
37/// // Parse styles section
38/// let styles_parser = StylesParser::new(source, start_pos, start_line);
39/// let (section, format, issues, pos, line) = styles_parser.parse()?;
40///
41/// // Parse events section
42/// let events_parser = EventsParser::new(source, start_pos, start_line);
43/// let (section, format, issues, pos, line) = events_parser.parse()?;
44/// # Ok::<(), CoreError>(())
45/// ```
46pub mod events;
47pub mod script_info;
48pub mod styles;
49
50pub use events::EventsParser;
51pub use script_info::ScriptInfoParser;
52pub use styles::StylesParser;
53
54use crate::parser::ast::{Section, SectionType};
55use crate::parser::errors::{ParseError, ParseResult};
56use alloc::vec::Vec;
57
58/// Formats detected during initial parse
59#[derive(Clone, Debug)]
60pub struct SectionFormats<'a> {
61 /// Format fields for styles section
62 pub styles_format: Option<Vec<&'a str>>,
63 /// Format fields for events section
64 pub events_format: Option<Vec<&'a str>>,
65}
66
67/// Parse a specific section type from text with context
68///
69/// # Errors
70///
71/// Returns [`ParseError::MissingFormat`] if required format is not provided
72/// Returns [`ParseError::UnsupportedSection`] for Fonts/Graphics sections
73/// Returns other parse errors from section-specific parsers
74pub fn parse_section_with_context<'a>(
75 section_type: SectionType,
76 text: &'a str,
77 line_offset: u32,
78 existing_formats: &SectionFormats<'a>,
79) -> ParseResult<Section<'a>> {
80 match section_type {
81 SectionType::ScriptInfo => {
82 let parser = ScriptInfoParser::new(text, 0, line_offset as usize);
83 let (section, ..) = parser.parse()?;
84 Ok(section)
85 }
86 SectionType::Styles => {
87 let format = existing_formats
88 .styles_format
89 .as_ref()
90 .ok_or(ParseError::MissingFormat)?;
91 let parser = StylesParser::with_format(text, format, 0, line_offset);
92 let (section, ..) = parser.parse()?;
93 Ok(section)
94 }
95 SectionType::Events => {
96 let format = existing_formats
97 .events_format
98 .as_ref()
99 .ok_or(ParseError::MissingFormat)?;
100 let parser = EventsParser::with_format(text, format, 0, line_offset);
101 let (section, ..) = parser.parse()?;
102 Ok(section)
103 }
104 SectionType::Fonts | SectionType::Graphics => {
105 // These sections are parsed as binary data
106 Err(ParseError::UnsupportedSection(section_type))
107 }
108 }
109}
110
111/// Result type for section parsing with metadata
112pub type SectionParseResult<'a> = (
113 crate::parser::ast::Section<'a>,
114 Option<Vec<&'a str>>,
115 Vec<crate::parser::errors::ParseIssue>,
116 usize,
117 usize,
118);
119
120/// Result type for script info parsing with version detection
121pub type ScriptInfoParseResult<'a> = (
122 crate::parser::ast::Section<'a>,
123 Option<crate::ScriptVersion>,
124 Vec<crate::parser::errors::ParseIssue>,
125 usize,
126 usize,
127);