neutralts/
block_parser.rs1use crate::{bif::Bif, constants::*, shared::Shared, utils::extract_blocks};
2use std::rc::Rc;
3
4pub(crate) struct BlockInherit {
5 pub(crate) indir: String,
6 pub(crate) last_bif_out: bool,
7 pub(crate) last_coalesce_out: bool,
8 pub(crate) block_count: u64, pub(crate) bif_count: u64, pub(crate) alias: String,
11 pub(crate) current_file: String,
12 pub(crate) current_dir: String,
13 pub(crate) include_files: Vec<String>,
14 pub(crate) locale_files: Vec<String>,
15 pub(crate) data_files: Vec<String>,
16 pub(crate) in_cache: bool,
17 pub(crate) in_only: bool,
18}
19
20impl Clone for BlockInherit {
21 fn clone(&self) -> Self {
22 BlockInherit {
23 indir: self.indir.clone(),
24 last_bif_out: self.last_bif_out,
25 last_coalesce_out: self.last_coalesce_out,
26 block_count: self.block_count,
27 bif_count: self.bif_count,
28 alias: self.alias.clone(),
29 current_file: self.current_file.clone(),
30 current_dir: self.current_dir.clone(),
31 include_files: self.include_files.clone(),
32 locale_files: self.locale_files.clone(),
33 data_files: self.data_files.clone(),
34 in_cache: self.in_cache,
35 in_only: self.in_only,
36 }
37 }
38}
39
40impl BlockInherit {
41 pub(crate) fn new() -> Self {
42 BlockInherit {
43 indir: "block_0".to_string(),
44 last_bif_out: false,
45 last_coalesce_out: false,
46 block_count: 0,
47 bif_count: 0,
48 alias: String::new(),
49 current_file: String::new(),
50 current_dir: String::new(),
51 include_files: Vec::new(),
52 locale_files: Vec::new(),
53 data_files: Vec::new(),
54 in_cache: false,
55 in_only: false,
56 }
57 }
58
59 pub(crate) fn create_block_schema(&mut self, shared: &mut Shared) -> String {
65 let prev_id = self.indir.clone();
66
67 let block_id = if self.block_count < 1 {
71 "block_1".to_string()
72 } else {
73 format!("block_{}", self.block_count)
74 };
75
76 if prev_id != block_id {
79 if let Some(parent_rc) = shared.indir_store.get(&prev_id) {
80 let parent_rc = Rc::clone(parent_rc);
81 shared.indir_store.insert(block_id.clone(), parent_rc);
82 }
83 }
84
85 self.indir = block_id.clone();
86
87 block_id
88 }
89}
90
91pub(crate) struct BlockParser<'a> {
92 shared: &'a mut Shared,
93 inherit: BlockInherit,
94 _none: &'a str,
95}
96
97impl Drop for BlockParser<'_> {
98 fn drop(&mut self) {
99 let block_id = format!("block_{}", self.inherit.block_count);
101
102 if block_id != "block_1" {
104 if block_id == self.inherit.indir {
105 self.shared.indir_store.remove(&block_id);
106 }
107 }
108 }
109}
110
111impl<'a> BlockParser<'a> {
112 pub(crate) fn new(shared: &'a mut Shared, mut inherit: BlockInherit) -> Self {
113 inherit.block_count += 1;
114
115 BlockParser {
116 shared,
117 inherit,
118 _none: "",
119 }
120 }
121
122 pub(crate) fn update_indir(&mut self, indir: &String) {
123 if let Some(child_rc) = self.shared.indir_store.get(&self.inherit.indir) {
124 let child_rc = Rc::clone(child_rc);
125 self.shared.indir_store.insert(indir.clone(), child_rc);
126 }
127 }
128
129 pub(crate) fn parse(&mut self, raw_source: &'a str, only: &str) -> String {
130 let blocks = match extract_blocks(raw_source) {
131 Ok(b) => b,
132 Err(p) => {
133 self.handle_unmatched_block(p);
134 return EMPTY_STRING;
135 }
136 };
137
138 self.parse_with_blocks(raw_source, &blocks, only)
139 }
140
141 fn handle_unmatched_block(&mut self, p: usize) {
142 self.shared.status_code = "500".to_string();
143 self.shared.status_param = format!("Unmatched block at position {}", p);
144 eprintln!("Unmatched block at position {}", p);
145
146 if let Some(text) = STATUS_CODES.get(self.shared.status_code.as_str()) {
147 self.shared.status_text = text.to_string();
148 } else {
149 self.shared.status_text = EMPTY_STRING;
150 }
151 }
152
153 pub(crate) fn parse_with_blocks(
154 &mut self,
155 raw_source: &'a str,
156 blocks: &[(usize, usize)],
157 only: &str,
158 ) -> String {
159 let mut prev_end = 0;
160 let mut out = String::new();
161 for (start, end) in blocks {
162 let start = *start;
163 let end = *end;
164 let is_comment = raw_source[start..end].starts_with(BIF_COMMENT_OPEN);
165 let is_short_circuit_coalesce =
166 self.inherit.last_coalesce_out && self.inherit.alias == "coalesce";
167
168 if self.shared.exit {
169 return out.clone();
170 }
171
172 if prev_end < start {
173 out += &raw_source[prev_end..start];
174 }
175
176 if !is_comment && !is_short_circuit_coalesce {
177 let mut bif = Bif::new(
178 &raw_source[start..end],
179 self.shared,
180 &mut self.inherit,
181 only,
182 );
183 out += &bif.parse();
184 }
185
186 prev_end = end;
187 }
188 out += &raw_source[prev_end..];
189
190 out.trim().to_string()
191 }
192}