1use serde::{Deserialize, Serialize};
2
3#[derive(Deserialize, Serialize, Debug, Default, Clone, PartialEq, Eq)]
4pub struct Select {
5 #[serde(skip_serializing_if = "Option::is_none")]
6 pub id: Option<String>,
7
8 pub name: String,
9
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub color: Option<SelectColor>,
12}
13
14impl Select {
15 pub fn id<T>(mut self, id: T) -> Self
16 where
17 T: AsRef<str>,
18 {
19 self.id = Some(id.as_ref().to_string());
20 self
21 }
22
23 pub fn name<T>(mut self, name: T) -> Self
24 where
25 T: AsRef<str>,
26 {
27 self.name = name.as_ref().to_string();
28 self
29 }
30
31 pub fn color(mut self, color: SelectColor) -> Self {
32 self.color = Some(color);
33 self
34 }
35}
36
37impl<T> From<T> for Select
38where
39 T: AsRef<str>,
40{
41 fn from(value: T) -> Self {
42 Self::default().name(value)
43 }
44}
45
46impl std::fmt::Display for Select {
47 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
48 write!(f, "{}", self.name)
49 }
50}
51
52#[derive(Deserialize, Serialize, Debug, Default, Clone, PartialEq, Eq)]
54pub struct SelectGroup {
55 pub id: String,
56 pub name: String,
57 pub color: SelectColor,
58 pub option_ids: Vec<String>,
59}
60
61impl std::fmt::Display for SelectGroup {
62 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63 write!(f, "{}", self.name)
64 }
65}
66
67#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Default)]
74#[serde(rename_all = "snake_case")]
75pub enum SelectColor {
76 #[default]
77 Default,
78
79 Blue,
80 Brown,
81 Gray,
82 Green,
83 Orange,
84 Pink,
85 Purple,
86 Red,
87 Yellow,
88}
89
90impl std::str::FromStr for SelectColor {
91 type Err = serde_plain::Error;
92
93 fn from_str(s: &str) -> Result<Self, Self::Err> {
94 serde_plain::from_str(s)
95 }
96}
97
98impl std::fmt::Display for SelectColor {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 serde_plain::to_string(self)
101 .map_err(|_| std::fmt::Error)?
102 .fmt(f)
103 }
104}
105
106#[cfg(test)]
113mod tests {
114 use std::str::FromStr;
115
116 use super::*;
117
118 #[test]
119 fn deserialize_select() {
120 let json = r#"{
121 "id": "id",
122 "name": "name",
123 "color": "blue"
124 }"#;
125 let select: Select = serde_json::from_str(json).unwrap();
126 assert_eq!(select.id, Some("id".to_string()));
127 assert_eq!(select.name, "name");
128 assert_eq!(select.color, Some(SelectColor::Blue));
129 }
130
131 #[test]
132 fn serialize_select() {
133 let select = Select {
134 id: Some("id".to_string()),
135 name: "name".to_string(),
136 color: Some(SelectColor::Blue),
137 };
138
139 let json = serde_json::to_string(&select).expect("serialization failed");
140
141 let expected = r#"{"id":"id","name":"name","color":"blue"}"#;
142
143 assert_eq!(json, expected);
144 }
145
146 #[test]
147 fn deserialize_select_group() {
148 let json = r#"{
149 "id": "id",
150 "name": "name",
151 "color": "blue",
152 "option_ids": ["option_id"]
153 }"#;
154 let select_group: SelectGroup = serde_json::from_str(json).unwrap();
155 assert_eq!(select_group.id, "id");
156 assert_eq!(select_group.name, "name");
157 assert_eq!(select_group.color, SelectColor::Blue);
158 assert_eq!(select_group.option_ids, vec!["option_id"]);
159 }
160
161 #[test]
162 fn check_try_from_color() {
163 let cases = vec![
164 ("blue", Some(SelectColor::Blue)),
165 ("brown", Some(SelectColor::Brown)),
166 ("gray", Some(SelectColor::Gray)),
167 ("green", Some(SelectColor::Green)),
168 ("orange", Some(SelectColor::Orange)),
169 ("pink", Some(SelectColor::Pink)),
170 ("purple", Some(SelectColor::Purple)),
171 ("red", Some(SelectColor::Red)),
172 ("yellow", Some(SelectColor::Yellow)),
173 ("default", Some(SelectColor::Default)),
174 ("invalid_color", None),
175 ];
176
177 for (input, expected) in cases {
178 match SelectColor::from_str(input) {
179 Ok(color) => assert_eq!(Some(color), expected, "Input: {}", input),
180 Err(_) => assert!(expected.is_none(), "Expected None for input: {}", input),
181 }
182 }
183 }
184}