• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kaspar030 / laze / 14035553007

24 Mar 2025 12:42PM UTC coverage: 82.165% (+0.004%) from 82.161%
14035553007

push

github

web-flow
fix(env): fix state reset with escaped expressions (#682)

1 of 1 new or added line in 1 file covered. (100.0%)

1 existing line in 1 file now uncovered.

3575 of 4351 relevant lines covered (82.17%)

104.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.62
/src/nested_env/expr.rs
1
use std::borrow::Cow;
2

3
use evalexpr::EvalexprError;
4

5
pub trait Eval {
6
    fn eval(&self) -> Result<String, EvalexprError>;
7
}
8

9
impl Eval for String {
10
    fn eval(&self) -> Result<Self, EvalexprError> {
439✔
11
        Ok(eval(self)?.into())
439✔
12
    }
439✔
13
}
14

15
pub fn eval(input: &str) -> Result<Cow<'_, str>, EvalexprError> {
439✔
16
    if input.contains("$(") {
439✔
17
        eval_recursive(input, false)
6✔
18
    } else {
19
        Ok(input.into())
433✔
20
    }
21
}
439✔
22

23
fn eval_recursive(input: &str, is_eval: bool) -> Result<Cow<'_, str>, EvalexprError> {
8✔
24
    let mut result = String::new();
8✔
25
    let mut start = 0;
8✔
26
    let mut level = 0;
8✔
27
    let mut input_changed = false;
8✔
28

29
    for (i, character) in input.char_indices() {
479✔
30
        if character == '$'
479✔
31
            && i + 1 < input.len()
44✔
32
            && input[i + 1..i + 2] == *"("
44✔
33
            && (i == 0 || (input[i - 1..i] != *"$"))
8✔
34
        {
35
            if level == 0 {
2✔
36
                start = i + 1;
2✔
37
            }
2✔
38
        } else if character == '(' && start > 0 {
477✔
39
            level += 1;
2✔
40
        } else if character == ')' && level > 0 && start > 0 {
475✔
41
            level -= 1;
2✔
42
            if level == 0 {
2✔
43
                input_changed = true;
2✔
44
                result.push_str(&eval_recursive(&input[start + 1..i], true)?);
2✔
45
                start = 0;
1✔
UNCOV
46
            }
×
47
        } else if level == 0 {
473✔
48
            result.push(character);
468✔
49
        }
468✔
50
    }
51

52
    if is_eval {
7✔
53
        let expr = evalexpr::eval(&result)?.to_string();
2✔
54
        input_changed = true;
1✔
55
        result = expr;
1✔
56
    }
5✔
57

58
    if input_changed {
6✔
59
        Ok(result.into())
2✔
60
    } else {
61
        Ok(input.into())
4✔
62
    }
63
}
8✔
64

65
#[cfg(test)]
66
mod tests {
67
    use super::*;
68

69
    #[test]
70
    fn basic() {
71
        let result = eval("foo $(1+$(1+1)) after_foo");
72
        assert_eq!(result.unwrap(), "foo 3 after_foo");
73
    }
74
    #[test]
75
    fn nested_braces() {
76
        let result = eval("$((0))");
77
        assert_eq!(result.unwrap(), "0");
78
    }
79
    #[test]
80
    fn basic_eval_max() {
81
        let result = eval("$(max(1,2,3,4))");
82
        assert_eq!(result.unwrap(), "4");
83
    }
84
    #[test]
85
    fn basic_eval_add() {
86
        let result = eval("$(str::to_uppercase \"foobar\")");
87
        assert_eq!(result.unwrap(), "\"FOOBAR\"");
88
    }
89
    #[test]
90
    fn unchanged() {
91
        let result = eval("just some text");
92
        assert_eq!(result.unwrap(), Cow::Borrowed("just some text"));
93
    }
94
    #[test]
95
    fn escaped_dollar() {
96
        let literal = "just some $$(foo) text";
97
        let result = eval(literal);
98
        assert_eq!(result.unwrap(), Cow::Borrowed(literal));
99
    }
100
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc