Skip to main content

khive_fold/
result.rs

1//! Fold outcome type
2
3/// Outcome of a fold operation.
4///
5/// Deterministic: contains only derived state and entry count. No wall-clock timing.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct FoldOutcome<S> {
8    /// The derived state.
9    pub state: S,
10
11    /// Number of entries processed.
12    pub entries_processed: usize,
13}
14
15impl<S> FoldOutcome<S> {
16    /// Create a new fold outcome.
17    pub fn new(state: S, entries_processed: usize) -> Self {
18        Self {
19            state,
20            entries_processed,
21        }
22    }
23
24    /// Map the state to a different type.
25    pub fn map<T, F: FnOnce(S) -> T>(self, f: F) -> FoldOutcome<T> {
26        FoldOutcome::new(f(self.state), self.entries_processed)
27    }
28}
29
30impl<S: Default> Default for FoldOutcome<S> {
31    fn default() -> Self {
32        Self::new(S::default(), 0)
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn test_fold_outcome_creation() {
42        let result = FoldOutcome::new(42, 10);
43        assert_eq!(result.state, 42);
44        assert_eq!(result.entries_processed, 10);
45    }
46
47    #[test]
48    fn test_fold_outcome_map() {
49        let result = FoldOutcome::new(42, 10);
50        let mapped = result.map(|x| x.to_string());
51        assert_eq!(mapped.state, "42");
52        assert_eq!(mapped.entries_processed, 10);
53    }
54
55    #[test]
56    fn deterministic_no_timing_fields() {
57        let a = FoldOutcome::new(7usize, 3);
58        let b = FoldOutcome::new(7usize, 3);
59        assert_eq!(a, b);
60    }
61
62    #[test]
63    fn default_is_zero_state_zero_count() {
64        let d = FoldOutcome::<usize>::default();
65        assert_eq!(d.state, 0);
66        assert_eq!(d.entries_processed, 0);
67    }
68}