use super::EventsParser;
use crate::parser::{
ast::{Event, EventType},
errors::{IssueCategory, IssueSeverity, ParseIssue},
position_tracker::PositionTracker,
};
use alloc::{format, vec::Vec};
impl<'a> EventsParser<'a> {
pub(super) fn parse_event_line_internal(
&mut self,
line: &'a str,
line_start: &PositionTracker<'a>,
) -> Option<Event<'a>> {
let (event_type, data) = if let Some(data) = line.strip_prefix("Dialogue:") {
(EventType::Dialogue, data)
} else if let Some(data) = line.strip_prefix("Comment:") {
(EventType::Comment, data)
} else if let Some(data) = line.strip_prefix("Picture:") {
(EventType::Picture, data)
} else if let Some(data) = line.strip_prefix("Sound:") {
(EventType::Sound, data)
} else if let Some(data) = line.strip_prefix("Movie:") {
(EventType::Movie, data)
} else if let Some(data) = line.strip_prefix("Command:") {
(EventType::Command, data)
} else {
return None;
};
self.parse_event_data(event_type, data.trim(), line_start)
}
fn parse_event_data(
&mut self,
event_type: EventType,
data: &'a str,
line_start: &PositionTracker<'a>,
) -> Option<Event<'a>> {
let format = self.format.as_deref().unwrap_or(&[
"Layer", "Start", "End", "Style", "Name", "MarginL", "MarginR", "MarginV", "Effect",
"Text",
]);
let has_text_field = format
.iter()
.any(|&field| field.eq_ignore_ascii_case("Text"));
let parts: Vec<&str> = if has_text_field {
data.splitn(format.len(), ',').collect()
} else {
data.splitn(10, ',').collect()
};
if parts.len() < format.len() {
self.issues.push(ParseIssue::new(
IssueSeverity::Warning,
IssueCategory::Format,
format!(
"Event line has {} fields, expected at least {}",
parts.len(),
format.len()
),
line_start.line() as usize,
));
return None;
}
let get_field = |name: &str| -> &'a str {
format
.iter()
.position(|&field| field.eq_ignore_ascii_case(name))
.and_then(|idx| parts.get(idx))
.map_or("", |s| s.trim())
};
let text = get_field("Text");
let full_line = self.current_line();
let span = line_start.span_for(full_line.len());
Some(Event {
event_type,
layer: get_field("Layer"),
start: get_field("Start"),
end: get_field("End"),
style: get_field("Style"),
name: get_field("Name"),
margin_l: get_field("MarginL"),
margin_r: get_field("MarginR"),
margin_v: get_field("MarginV"),
margin_t: format
.iter()
.any(|&f| f.eq_ignore_ascii_case("MarginT"))
.then(|| get_field("MarginT")),
margin_b: format
.iter()
.any(|&f| f.eq_ignore_ascii_case("MarginB"))
.then(|| get_field("MarginB")),
effect: get_field("Effect"),
text,
span,
})
}
}