use super::EventsParser;
use crate::parser::{
ast::{Event, EventType, Span},
errors::ParseError,
};
use alloc::vec::Vec;
impl<'a> EventsParser<'a> {
pub fn parse_event_line(
line: &'a str,
format: &[&'a str],
line_number: u32,
) -> core::result::Result<Event<'a>, ParseError> {
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 Err(ParseError::InvalidEventType {
line: line_number as usize,
});
};
Self::parse_event_data_static(event_type, data.trim(), format, line_number)
}
fn parse_event_data_static(
event_type: EventType,
data: &'a str,
format: &[&'a str],
line_number: u32,
) -> core::result::Result<Event<'a>, ParseError> {
let format = if format.is_empty() {
&[
"Layer", "Start", "End", "Style", "Name", "MarginL", "MarginR", "MarginV",
"Effect", "Text",
]
} else {
format
};
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() {
return Err(ParseError::InsufficientFields {
expected: format.len(),
found: parts.len(),
line: line_number as usize,
});
}
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 span = Span::new(0, 0, line_number, 1);
Ok(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: get_field("Text"),
span,
})
}
}