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);