adrscope/domain/
status.rs1use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum Status {
12 #[default]
14 Proposed,
15 Accepted,
17 Deprecated,
19 Superseded,
21}
22
23impl Status {
24 #[must_use]
26 pub const fn as_str(&self) -> &'static str {
27 match self {
28 Self::Proposed => "proposed",
29 Self::Accepted => "accepted",
30 Self::Deprecated => "deprecated",
31 Self::Superseded => "superseded",
32 }
33 }
34
35 #[must_use]
37 pub const fn css_class(&self) -> &'static str {
38 match self {
39 Self::Proposed => "status-proposed",
40 Self::Accepted => "status-accepted",
41 Self::Deprecated => "status-deprecated",
42 Self::Superseded => "status-superseded",
43 }
44 }
45
46 #[must_use]
48 pub const fn color(&self) -> &'static str {
49 match self {
50 Self::Proposed => "#f59e0b", Self::Accepted => "#10b981", Self::Deprecated => "#ef4444", Self::Superseded => "#6b7280", }
55 }
56
57 #[must_use]
59 pub const fn all() -> &'static [Self] {
60 &[
61 Self::Proposed,
62 Self::Accepted,
63 Self::Deprecated,
64 Self::Superseded,
65 ]
66 }
67}
68
69impl std::fmt::Display for Status {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{}", self.as_str())
72 }
73}
74
75impl std::str::FromStr for Status {
76 type Err = String;
77
78 fn from_str(s: &str) -> Result<Self, Self::Err> {
79 match s.to_lowercase().as_str() {
80 "proposed" => Ok(Self::Proposed),
81 "accepted" => Ok(Self::Accepted),
82 "deprecated" => Ok(Self::Deprecated),
83 "superseded" => Ok(Self::Superseded),
84 _ => Err(format!("invalid status: {s}")),
85 }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_status_as_str() {
95 assert_eq!(Status::Proposed.as_str(), "proposed");
96 assert_eq!(Status::Accepted.as_str(), "accepted");
97 assert_eq!(Status::Deprecated.as_str(), "deprecated");
98 assert_eq!(Status::Superseded.as_str(), "superseded");
99 }
100
101 #[test]
102 fn test_status_default() {
103 assert_eq!(Status::default(), Status::Proposed);
104 }
105
106 #[test]
107 fn test_status_from_str() {
108 assert_eq!("proposed".parse::<Status>().ok(), Some(Status::Proposed));
109 assert_eq!("ACCEPTED".parse::<Status>().ok(), Some(Status::Accepted));
110 assert_eq!(
111 "Deprecated".parse::<Status>().ok(),
112 Some(Status::Deprecated)
113 );
114 assert!("invalid".parse::<Status>().is_err());
115 }
116
117 #[test]
118 fn test_status_display() {
119 assert_eq!(format!("{}", Status::Accepted), "accepted");
120 }
121
122 #[test]
123 fn test_status_css_class() {
124 assert_eq!(Status::Proposed.css_class(), "status-proposed");
125 assert_eq!(Status::Accepted.css_class(), "status-accepted");
126 assert_eq!(Status::Deprecated.css_class(), "status-deprecated");
127 assert_eq!(Status::Superseded.css_class(), "status-superseded");
128 }
129
130 #[test]
131 fn test_status_color() {
132 assert_eq!(Status::Proposed.color(), "#f59e0b");
133 assert_eq!(Status::Accepted.color(), "#10b981");
134 assert_eq!(Status::Deprecated.color(), "#ef4444");
135 assert_eq!(Status::Superseded.color(), "#6b7280");
136 }
137
138 #[test]
139 fn test_status_all() {
140 let all = Status::all();
141 assert_eq!(all.len(), 4);
142 assert!(all.contains(&Status::Proposed));
143 assert!(all.contains(&Status::Accepted));
144 assert!(all.contains(&Status::Deprecated));
145 assert!(all.contains(&Status::Superseded));
146 }
147
148 #[test]
149 fn test_status_serialization() {
150 let status = Status::Accepted;
151 let json = serde_json::to_string(&status).ok();
152 assert_eq!(json, Some("\"accepted\"".to_string()));
153 }
154
155 #[test]
156 fn test_status_deserialization() {
157 let status: Status = serde_json::from_str("\"proposed\"").expect("should parse");
158 assert_eq!(status, Status::Proposed);
159 }
160}