uv_pypi_types/
project_status.rs1use std::borrow::Cow;
7
8use serde::Deserialize;
9use tracing::info;
10use uv_small_str::SmallString;
11
12#[derive(
14 Clone, Copy, Debug, Default, Eq, PartialEq, rkyv::Archive, rkyv::Deserialize, rkyv::Serialize,
15)]
16#[rkyv(derive(Debug))]
17pub enum Status {
18 #[default]
19 Active,
20 Archived,
21 Quarantined,
22 Deprecated,
23}
24
25impl Status {
26 pub fn new(status: &str) -> Option<Self> {
27 match status {
28 "active" => Some(Self::Active),
29 "archived" => Some(Self::Archived),
30 "quarantined" => Some(Self::Quarantined),
31 "deprecated" => Some(Self::Deprecated),
32 _ => {
33 info!("Unknown project status: '{status}'");
34 None
35 }
36 }
37 }
38}
39
40impl<'de> Deserialize<'de> for Status {
41 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
42 where
43 D: serde::Deserializer<'de>,
44 {
45 let s = <Cow<'_, str>>::deserialize(deserializer)?;
46 Ok(Self::new(&s).unwrap_or_default())
48 }
49}
50
51#[derive(Clone, Debug, Default, Deserialize, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
55#[rkyv(derive(Debug))]
56pub struct ProjectStatus {
57 #[serde(default)]
58 pub status: Status,
59 #[serde(default)]
60 pub reason: Option<SmallString>,
61}
62
63#[cfg(test)]
64mod tests {
65 use uv_small_str::SmallString;
66
67 use crate::{ProjectStatus, Status};
68
69 #[test]
70 fn test_status() {
71 assert_eq!(Status::new("active"), Some(Status::Active));
72 assert_eq!(Status::new("archived"), Some(Status::Archived));
73 assert_eq!(Status::new("quarantined"), Some(Status::Quarantined));
74 assert_eq!(Status::new("deprecated"), Some(Status::Deprecated));
75 assert_eq!(Status::new("unknown"), None);
76 assert_eq!(Status::new("ACTIVE"), None);
77 assert_eq!(Status::new("acTiVe"), None);
78 }
79
80 #[test]
82 fn test_deserialize_empty() {
83 let json = "{}";
84
85 let project_status: ProjectStatus = serde_json::from_str(json).unwrap();
86 assert_eq!(project_status.status, Status::Active);
87 assert_eq!(project_status.reason, None);
88 }
89
90 #[test]
92 fn test_deserialize_null() {
93 let json = r#"
94 {
95 "reason": null
96 }
97 "#;
98
99 let project_status: ProjectStatus = serde_json::from_str(json).unwrap();
100 assert_eq!(project_status.status, Status::Active);
101 assert_eq!(project_status.reason, None);
102 }
103
104 #[test]
106 fn test_deserialize() {
107 let json = r#"
108 {
109 "status": "archived",
110 "reason": "This project is no longer maintained."
111 }
112 "#;
113
114 let project_status: ProjectStatus = serde_json::from_str(json).unwrap();
115 assert_eq!(project_status.status, Status::Archived);
116 assert_eq!(
117 project_status.reason,
118 Some(SmallString::from("This project is no longer maintained."))
119 );
120 }
121
122 #[test]
124 fn test_deserialize_unknown_status() {
125 let json = r#"
126 {
127 "status": "unknown",
128 "reason": "This project has an unrecognized status."
129 }
130 "#;
131
132 let project_status: ProjectStatus = serde_json::from_str(json).unwrap();
133 assert_eq!(project_status.status, Status::Active);
134 assert_eq!(
135 project_status.reason,
136 Some(SmallString::from(
137 "This project has an unrecognized status."
138 ))
139 );
140 }
141}