ass_core/parser/script/
update.rs1use alloc::{boxed::Box, vec::Vec};
8
9use crate::parser::ast::Section;
10use crate::parser::errors::ParseError;
11
12use super::types::{Change, LineContent};
13use super::Script;
14
15impl<'a> Script<'a> {
16 pub fn update_line_at_offset(
35 &mut self,
36 offset: usize,
37 new_line: &'a str,
38 line_number: u32,
39 ) -> core::result::Result<LineContent<'a>, ParseError> {
40 let section_index = self
42 .sections
43 .iter()
44 .position(|s| {
45 s.span()
46 .is_some_and(|span| span.start <= offset && offset < span.end)
47 })
48 .ok_or(ParseError::SectionNotFound)?;
49
50 let (_, new_content) = self.parse_line_auto(new_line, line_number)?;
52
53 let result = match (&mut self.sections[section_index], new_content.clone()) {
55 (Section::Styles(styles), LineContent::Style(new_style)) => {
56 styles
58 .iter()
59 .position(|s| s.span.start <= offset && offset < s.span.end)
60 .map_or(Err(ParseError::IndexOutOfBounds), |style_index| {
61 let old_style = styles[style_index].clone();
62 styles[style_index] = *new_style;
63 Ok(LineContent::Style(Box::new(old_style)))
64 })
65 }
66 (Section::Events(events), LineContent::Event(new_event)) => {
67 events
69 .iter()
70 .position(|e| e.span.start <= offset && offset < e.span.end)
71 .map_or(Err(ParseError::IndexOutOfBounds), |event_index| {
72 let old_event = events[event_index].clone();
73 events[event_index] = *new_event;
74 Ok(LineContent::Event(Box::new(old_event)))
75 })
76 }
77 (Section::ScriptInfo(info), LineContent::Field(key, value)) => {
78 if let Some(field_index) = info.fields.iter().position(|(k, _)| *k == key) {
80 let old_value = info.fields[field_index].1;
81 info.fields[field_index] = (key, value);
82 Ok(LineContent::Field(key, old_value))
83 } else {
84 info.fields.push((key, value));
86 self.change_tracker.record(Change::Added {
88 offset,
89 content: LineContent::Field(key, value),
90 line_number,
91 });
92 Ok(LineContent::Field(key, ""))
93 }
94 }
95 _ => Err(ParseError::InvalidFieldFormat {
96 line: line_number as usize,
97 }),
98 };
99
100 if let Ok(old_content) = &result {
102 if !matches!(old_content, LineContent::Field(_, "")) {
103 self.change_tracker.record(Change::Modified {
105 offset,
106 old_content: old_content.clone(),
107 new_content,
108 line_number,
109 });
110 }
111 }
112
113 result
114 }
115
116 pub fn set_styles_format(&mut self, format: Vec<&'a str>) {
118 self.styles_format = Some(format);
119 }
120
121 pub fn set_events_format(&mut self, format: Vec<&'a str>) {
123 self.events_format = Some(format);
124 }
125}