Skip to main content

fallow_types/
churn.rs

1//! Shared churn output contracts.
2
3/// Churn trend indicator based on comparing recent vs older halves of the
4/// analysis period.
5#[derive(
6    Debug,
7    Clone,
8    Copy,
9    PartialEq,
10    Eq,
11    serde::Serialize,
12    serde::Deserialize,
13    bitcode::Encode,
14    bitcode::Decode,
15)]
16#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
17#[serde(rename_all = "snake_case")]
18pub enum ChurnTrend {
19    /// Recent half has >1.5x the commits of the older half.
20    Accelerating,
21    /// Churn is roughly stable between halves.
22    Stable,
23    /// Recent half has <0.67x the commits of the older half.
24    Cooling,
25}
26
27impl std::fmt::Display for ChurnTrend {
28    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29        match self {
30            Self::Accelerating => write!(f, "accelerating"),
31            Self::Stable => write!(f, "stable"),
32            Self::Cooling => write!(f, "cooling"),
33        }
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn churn_trend_display_matches_wire_values() {
43        assert_eq!(ChurnTrend::Accelerating.to_string(), "accelerating");
44        assert_eq!(ChurnTrend::Stable.to_string(), "stable");
45        assert_eq!(ChurnTrend::Cooling.to_string(), "cooling");
46    }
47
48    #[test]
49    fn churn_trend_serializes_as_snake_case() {
50        assert_eq!(
51            serde_json::to_string(&ChurnTrend::Accelerating).unwrap(),
52            r#""accelerating""#,
53        );
54        assert_eq!(
55            serde_json::to_string(&ChurnTrend::Stable).unwrap(),
56            r#""stable""#,
57        );
58        assert_eq!(
59            serde_json::to_string(&ChurnTrend::Cooling).unwrap(),
60            r#""cooling""#,
61        );
62    }
63}