ass_core/parser/incremental/
section_bounds.rs1use crate::parser::errors::ParseError;
4use crate::parser::SectionType;
5
6pub fn find_section_header_start(
12 source: &str,
13 start_hint: usize,
14 section_type: SectionType,
15) -> Result<usize, ParseError> {
16 let header = match section_type {
18 SectionType::ScriptInfo => "[Script Info]",
19 SectionType::Styles => "[V4+ Styles]",
20 SectionType::Events => "[Events]",
21 SectionType::Fonts => "[Fonts]",
22 SectionType::Graphics => "[Graphics]",
23 };
24
25 let search_start = start_hint.saturating_sub(header.len() + 100); let search_text = &source[search_start..start_hint.min(source.len())];
28
29 search_text
30 .rfind(header)
31 .map_or(Err(ParseError::SectionNotFound), |pos| {
32 let header_pos = search_start + pos;
34 let line_start = source[..header_pos].rfind('\n').map_or(0, |p| p + 1);
35 Ok(line_start)
36 })
37}
38
39pub fn find_section_end(
45 source: &str,
46 end_hint: usize,
47 _section_type: SectionType,
48) -> Result<usize, ParseError> {
49 let section_headers = [
51 "[Script Info]",
52 "[V4+ Styles]",
53 "[Events]",
54 "[Fonts]",
55 "[Graphics]",
56 ];
57
58 let search_text = &source[end_hint..];
59
60 let mut min_pos = None;
62 for header in §ion_headers {
63 if let Some(pos) = search_text.find(header) {
64 min_pos = Some(min_pos.map_or(pos, |min: usize| min.min(pos)));
65 }
66 }
67
68 min_pos.map_or(Ok(source.len()), |pos| {
69 let next_section_pos = end_hint + pos;
71 let line_start = source[..next_section_pos].rfind('\n').map_or(0, |p| p + 1);
72 Ok(line_start)
73 })
74}