Skip to main content

camel_api/
loop_eip.rs

1use crate::filter::FilterPredicate;
2
3/// How the loop terminates.
4#[derive(Clone)]
5pub enum LoopMode {
6    /// Fixed iteration count.
7    Count(usize),
8    /// While a runtime predicate evaluates to true.
9    While(FilterPredicate),
10}
11
12impl std::fmt::Debug for LoopMode {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        match self {
15            LoopMode::Count(n) => write!(f, "Count({n})"),
16            LoopMode::While(_) => write!(f, "While(<predicate>)"),
17        }
18    }
19}
20
21#[derive(Clone, Debug)]
22pub struct LoopConfig {
23    pub mode: LoopMode,
24    pub max_iterations: usize,
25}
26
27impl LoopConfig {
28    pub fn new(mode: LoopMode) -> Self {
29        Self {
30            mode,
31            max_iterations: MAX_LOOP_ITERATIONS,
32        }
33    }
34
35    pub fn with_max_iterations(mut self, max: usize) -> Self {
36        self.max_iterations = max;
37        self
38    }
39
40    pub fn mode_name(&self) -> &'static str {
41        match &self.mode {
42            LoopMode::Count(_) => "count",
43            LoopMode::While(_) => "while",
44        }
45    }
46}
47
48/// Maximum iterations for while-mode loops. Prevents infinite loops.
49pub const MAX_LOOP_ITERATIONS: usize = 10_000;
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    fn always_true() -> FilterPredicate {
56        FilterPredicate::new(|_| true)
57    }
58
59    #[test]
60    fn loop_config_new_count() {
61        let cfg = LoopConfig::new(LoopMode::Count(5));
62        assert_eq!(cfg.mode_name(), "count");
63    }
64
65    #[test]
66    fn loop_config_new_while() {
67        let cfg = LoopConfig::new(LoopMode::While(always_true()));
68        assert_eq!(cfg.mode_name(), "while");
69    }
70
71    #[test]
72    fn loop_mode_debug_count() {
73        let mode = LoopMode::Count(3);
74        assert_eq!(format!("{mode:?}"), "Count(3)");
75    }
76
77    #[test]
78    fn loop_mode_debug_while() {
79        let mode = LoopMode::While(always_true());
80        assert_eq!(format!("{mode:?}"), "While(<predicate>)");
81    }
82
83    #[test]
84    fn loop_mode_clone_count() {
85        let mode = LoopMode::Count(10);
86        let cloned = mode.clone();
87        assert_eq!(format!("{cloned:?}"), "Count(10)");
88    }
89
90    #[test]
91    fn loop_config_clone() {
92        let cfg = LoopConfig::new(LoopMode::Count(2));
93        let cloned = cfg.clone();
94        assert_eq!(cloned.mode_name(), "count");
95    }
96
97    #[test]
98    fn max_loop_iterations_value() {
99        assert_eq!(MAX_LOOP_ITERATIONS, 10_000);
100    }
101
102    #[test]
103    fn loop_config_default_max_iterations() {
104        let cfg = LoopConfig::new(LoopMode::Count(5));
105        assert_eq!(cfg.max_iterations, MAX_LOOP_ITERATIONS);
106    }
107
108    #[test]
109    fn loop_config_with_max_iterations() {
110        let cfg = LoopConfig::new(LoopMode::Count(5)).with_max_iterations(500_000);
111        assert_eq!(cfg.max_iterations, 500_000);
112    }
113}