vespertide_core/schema/
str_or_bool.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
15#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
16#[serde(rename_all = "snake_case", untagged)]
17#[non_exhaustive]
18pub enum StrOrBoolOrArray {
19 Str(String),
21 Array(Vec<String>),
23 Bool(bool),
25}
26
27impl StrOrBoolOrArray {
28 #[must_use]
30 pub fn as_str(&self) -> Option<&str> {
31 match self {
32 StrOrBoolOrArray::Str(s) => Some(s.as_str()),
33 StrOrBoolOrArray::Array(_) | StrOrBoolOrArray::Bool(_) => None,
34 }
35 }
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
54#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
55#[serde(untagged)]
56#[non_exhaustive]
57pub enum DefaultValue {
58 Bool(bool),
60 Integer(i64),
62 Float(f64),
64 String(String),
66}
67
68impl Eq for DefaultValue {}
69
70impl DefaultValue {
71 #[must_use]
73 pub fn as_bool(&self) -> Option<bool> {
74 match self {
75 DefaultValue::Bool(b) => Some(*b),
76 DefaultValue::Integer(_) | DefaultValue::Float(_) | DefaultValue::String(_) => None,
77 }
78 }
79
80 pub fn to_sql(&self) -> String {
83 match self {
84 DefaultValue::Bool(b) => b.to_string(),
85 DefaultValue::Integer(n) => n.to_string(),
86 DefaultValue::Float(f) => f.to_string(),
87 DefaultValue::String(s) => {
88 if s.is_empty() {
89 "''".to_string()
90 } else {
91 s.clone()
92 }
93 }
94 }
95 }
96
97 pub fn is_string(&self) -> bool {
99 matches!(self, DefaultValue::String(_))
100 }
101
102 pub fn is_empty_string(&self) -> bool {
104 matches!(self, DefaultValue::String(s) if s.is_empty())
105 }
106}
107
108impl From<bool> for DefaultValue {
109 fn from(b: bool) -> Self {
110 DefaultValue::Bool(b)
111 }
112}
113
114impl From<i64> for DefaultValue {
115 fn from(n: i64) -> Self {
116 DefaultValue::Integer(n)
117 }
118}
119
120impl From<i32> for DefaultValue {
121 fn from(n: i32) -> Self {
122 DefaultValue::Integer(i64::from(n))
123 }
124}
125
126impl From<f64> for DefaultValue {
127 fn from(f: f64) -> Self {
128 DefaultValue::Float(f)
129 }
130}
131
132impl From<String> for DefaultValue {
133 fn from(s: String) -> Self {
134 DefaultValue::String(s)
135 }
136}
137
138impl From<&str> for DefaultValue {
139 fn from(s: &str) -> Self {
140 DefaultValue::String(s.to_string())
141 }
142}
143
144pub type StringOrBool = DefaultValue;
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn test_default_value_to_sql_bool() {
153 let val = DefaultValue::Bool(true);
154 assert_eq!(val.to_sql(), "true");
155
156 let val = DefaultValue::Bool(false);
157 assert_eq!(val.to_sql(), "false");
158 }
159
160 #[test]
161 fn test_default_value_to_sql_integer() {
162 let val = DefaultValue::Integer(42);
163 assert_eq!(val.to_sql(), "42");
164
165 let val = DefaultValue::Integer(-100);
166 assert_eq!(val.to_sql(), "-100");
167 }
168
169 #[test]
170 fn test_default_value_to_sql_float() {
171 let val = DefaultValue::Float(1.5);
172 assert_eq!(val.to_sql(), "1.5");
173 }
174
175 #[test]
176 fn test_default_value_to_sql_string() {
177 let val = DefaultValue::String("hello".into());
178 assert_eq!(val.to_sql(), "hello");
179 }
180
181 #[test]
182 fn test_default_value_to_sql_empty_string() {
183 let val = DefaultValue::String(String::new());
184 assert_eq!(val.to_sql(), "''");
185 }
186
187 #[test]
188 fn test_default_value_is_empty_string() {
189 assert!(DefaultValue::String(String::new()).is_empty_string());
190 assert!(!DefaultValue::String("hello".into()).is_empty_string());
191 assert!(!DefaultValue::Bool(true).is_empty_string());
192 assert!(!DefaultValue::Integer(0).is_empty_string());
193 }
194
195 #[test]
196 fn test_default_value_from_bool() {
197 let val: DefaultValue = true.into();
198 assert_eq!(val, DefaultValue::Bool(true));
199
200 let val: DefaultValue = false.into();
201 assert_eq!(val, DefaultValue::Bool(false));
202 }
203
204 #[test]
205 fn test_default_value_from_integer() {
206 let val: DefaultValue = 42i64.into();
207 assert_eq!(val, DefaultValue::Integer(42));
208
209 let val: DefaultValue = 100i32.into();
210 assert_eq!(val, DefaultValue::Integer(100));
211 }
212
213 #[test]
214 fn test_default_value_from_float() {
215 let val: DefaultValue = 1.5f64.into();
216 assert_eq!(val, DefaultValue::Float(1.5));
217 }
218
219 #[test]
220 fn test_default_value_from_string() {
221 let val: DefaultValue = String::from("test").into();
222 assert_eq!(val, DefaultValue::String("test".into()));
223 }
224
225 #[test]
226 fn test_default_value_from_str() {
227 let val: DefaultValue = "test".into();
228 assert_eq!(val, DefaultValue::String("test".into()));
229 }
230
231 #[test]
232 fn test_default_value_is_string() {
233 assert!(DefaultValue::String("test".into()).is_string());
234 assert!(!DefaultValue::Bool(true).is_string());
235 assert!(!DefaultValue::Integer(42).is_string());
236 assert!(!DefaultValue::Float(1.5).is_string());
237 }
238
239 #[test]
240 fn test_string_or_bool_as_bool() {
241 assert_eq!(StringOrBool::Bool(true).as_bool(), Some(true));
242 assert_eq!(StringOrBool::Bool(false).as_bool(), Some(false));
243 assert_eq!(StringOrBool::String("value".into()).as_bool(), None);
244 }
245
246 #[test]
247 fn test_str_or_bool_or_array_as_str() {
248 assert_eq!(StrOrBoolOrArray::Str("name".into()).as_str(), Some("name"));
249 assert_eq!(StrOrBoolOrArray::Bool(true).as_str(), None);
250 assert_eq!(StrOrBoolOrArray::Array(vec!["name".into()]).as_str(), None);
251 }
252}