sevenmark_parser/
context.rs1use crate::error::SevenMarkError;
2
3macro_rules! context_setters {
4 ($($name:ident => $field:ident),*) => {
5 $(
6 paste::paste! {
7 pub fn [<set_ $name _context>](&mut self) {
9 self.$field = true;
10 }
11
12 pub fn [<unset_ $name _context>](&mut self) {
14 self.$field = false;
15 }
16 }
17 )*
18 };
19}
20
21#[derive(Debug, Clone)]
22pub struct ParseContext<'i> {
23 pub recursion_depth: usize,
24 pub trim_depth: usize,
25 pub inside_header: bool,
26 pub inside_bold: bool,
27 pub inside_italic: bool,
28 pub inside_strikethrough: bool,
29 pub inside_subscript: bool,
30 pub inside_superscript: bool,
31 pub inside_underline: bool,
32 pub inside_footnote: bool,
33 pub inside_media_element: bool,
34 pub original_input: &'i [u8],
35 pub max_recursion_depth: usize,
36 pub section_counter: usize,
37 pub footnote_counter: usize,
38}
39
40impl<'i> ParseContext<'i> {
41 pub fn new(input: &'i str) -> Self {
43 Self {
44 recursion_depth: 0,
45 trim_depth: 0,
46 inside_header: false,
47 inside_bold: false,
48 inside_italic: false,
49 inside_strikethrough: false,
50 inside_subscript: false,
51 inside_superscript: false,
52 inside_underline: false,
53 inside_footnote: false,
54 inside_media_element: false,
55 original_input: input.as_bytes(),
56 max_recursion_depth: 16,
57 section_counter: 1,
58 footnote_counter: 1,
59 }
60 }
61
62 pub fn is_at_line_start(&self, position: usize) -> bool {
64 position == 0 || self.original_input.get(position - 1) == Some(&b'\n')
65 }
66
67 pub fn increase_depth(&mut self) -> Result<(), SevenMarkError> {
69 let new_depth = self.recursion_depth + 1;
70 if new_depth > self.max_recursion_depth {
71 return Err(SevenMarkError::RecursionDepthExceeded {
72 depth: new_depth,
73 max_depth: self.max_recursion_depth,
74 });
75 }
76 self.recursion_depth = new_depth;
77 Ok(())
78 }
79
80 pub fn decrease_depth(&mut self) {
82 self.recursion_depth = self.recursion_depth.saturating_sub(1);
83 }
84
85 pub fn is_at_max_depth(&self) -> bool {
87 self.recursion_depth >= self.max_recursion_depth
88 }
89
90 pub fn current_depth(&self) -> usize {
92 self.recursion_depth
93 }
94
95 pub fn remaining_depth(&self) -> usize {
97 self.max_recursion_depth
98 .saturating_sub(self.recursion_depth)
99 }
100
101 pub fn next_section_index(&mut self) -> usize {
103 let idx = self.section_counter;
104 self.section_counter += 1;
105 idx
106 }
107
108 pub fn next_footnote_index(&mut self) -> usize {
110 let idx = self.footnote_counter;
111 self.footnote_counter += 1;
112 idx
113 }
114
115 pub fn increase_trim_depth(&mut self) {
117 self.trim_depth += 1;
118 }
119
120 pub fn decrease_trim_depth(&mut self) {
122 self.trim_depth = self.trim_depth.saturating_sub(1);
123 }
124
125 pub fn is_trimming(&self) -> bool {
127 self.trim_depth > 0
128 }
129
130 context_setters! {
131 header => inside_header,
132 bold => inside_bold,
133 italic => inside_italic,
134 strikethrough => inside_strikethrough,
135 subscript => inside_subscript,
136 superscript => inside_superscript,
137 underline => inside_underline,
138 footnote => inside_footnote,
139 media_element => inside_media_element
140 }
141}