fhttp_core/preprocessing/
evaluation.rs1use std::ops::Range;
2
3use anyhow::Result;
4
5pub trait Evaluation {
6 fn backslashes(&self) -> &Range<usize>;
7
8 fn range(&self) -> &Range<usize>;
9
10 fn is_escaped(&self) -> bool {
11 self.backslashes().len() % 2 != 0
12 }
13
14 fn replace<S: Into<String>, F: FnOnce() -> Result<S>>(
15 &self,
16 target: &mut String,
17 producer: F,
18 ) -> Result<()> {
19 if !self.is_escaped() {
20 let text = producer()?.into();
21 let end_index = match text.chars().last() {
22 Some('\n') => text.len() - 1,
23 _ => text.len(),
24 };
25 target.replace_range(self.range().clone(), &text[0..end_index]);
26 }
27 escape_backslashes(target, self.backslashes());
28
29 Ok(())
30 }
31}
32
33fn escape_backslashes(target: &mut String, backslashes: &Range<usize>) {
34 if backslashes.is_empty() {
35 return;
36 }
37
38 let num_backslaches_to_remove = backslashes.len() / 2;
39 let new_end = backslashes.end - num_backslaches_to_remove;
40
41 target.replace_range(backslashes.start..new_end, "");
42}
43
44#[derive(Debug)]
45pub struct BaseEvaluation {
46 pub backslashes: Range<usize>,
47 pub range: Range<usize>,
48}
49
50impl BaseEvaluation {
51 pub fn new(range: Range<usize>, backslashes: Range<usize>) -> Self {
52 BaseEvaluation { range, backslashes }
53 }
54}
55
56impl AsRef<BaseEvaluation> for BaseEvaluation {
57 fn as_ref(&self) -> &BaseEvaluation {
58 self
59 }
60}
61
62impl<T: AsRef<BaseEvaluation>> Evaluation for T {
63 fn backslashes(&self) -> &Range<usize> {
64 &self.as_ref().backslashes
65 }
66
67 fn range(&self) -> &Range<usize> {
68 &self.as_ref().range
69 }
70}