zero_operator_state/
label.rs1use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum Label {
16 Fresh,
18 Steady,
20 Elevated,
22 Tilt,
24 Fatigued,
26 Recovery,
28}
29
30impl Label {
31 #[must_use]
36 pub const fn short(self) -> &'static str {
37 match self {
38 Self::Fresh => "FRESH",
39 Self::Steady => "STEADY",
40 Self::Elevated => "ELEVATED",
41 Self::Tilt => "TILT",
42 Self::Fatigued => "FATIGUED",
43 Self::Recovery => "RECOVERY",
44 }
45 }
46
47 #[must_use]
50 pub const fn color_hint(self) -> ColorHint {
51 match self {
52 Self::Fresh | Self::Steady => ColorHint::Phosphor,
53 Self::Elevated | Self::Fatigued => ColorHint::Amber,
54 Self::Tilt => ColorHint::Red,
55 Self::Recovery => ColorHint::MutedOlive,
56 }
57 }
58}
59
60impl std::fmt::Display for Label {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 f.write_str(self.short())
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70pub enum ColorHint {
71 Phosphor,
72 Amber,
73 Red,
74 MutedOlive,
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn short_labels_are_uppercase_single_word() {
83 for l in [
84 Label::Fresh,
85 Label::Steady,
86 Label::Elevated,
87 Label::Tilt,
88 Label::Fatigued,
89 Label::Recovery,
90 ] {
91 assert!(l.short().chars().all(|c| c.is_ascii_uppercase()));
92 assert!(!l.short().contains(' '));
93 }
94 }
95
96 #[test]
97 fn color_hints_match_spec() {
98 assert_eq!(Label::Fresh.color_hint(), ColorHint::Phosphor);
99 assert_eq!(Label::Steady.color_hint(), ColorHint::Phosphor);
100 assert_eq!(Label::Elevated.color_hint(), ColorHint::Amber);
101 assert_eq!(Label::Fatigued.color_hint(), ColorHint::Amber);
102 assert_eq!(Label::Tilt.color_hint(), ColorHint::Red);
103 assert_eq!(Label::Recovery.color_hint(), ColorHint::MutedOlive);
104 }
105}