1use super::Value;
2
3pub trait IntoArma {
5 fn to_arma(&self) -> Value;
7}
8
9pub struct DirectReturn(Value);
10impl Value {
11 pub const fn direct(value: Value) -> DirectReturn {
13 DirectReturn(value)
14 }
15}
16
17impl IntoArma for DirectReturn {
18 fn to_arma(&self) -> Value {
19 self.0.clone()
20 }
21}
22
23impl IntoArma for () {
24 fn to_arma(&self) -> Value {
25 Value::Null
26 }
27}
28
29macro_rules! impl_into_arma_tuple {
30 { $c: expr, $($t:ident)* } => {
31 seq_macro::seq!(N in 0..$c {
32 impl<$($t),*> IntoArma for ($($t),*)
33 where
34 $($t: IntoArma),*
35 {
36 fn to_arma(&self) -> Value {
37 Value::Array(vec![
38 #(
39 self.N.to_arma(),
40 )*
41 ])
42 }
43 }
44 });
45 };
46}
47
48impl_into_arma_tuple! { 2, A B }
49impl_into_arma_tuple! { 3, A B C }
50impl_into_arma_tuple! { 4, A B C D }
51impl_into_arma_tuple! { 5, A B C D E }
52impl_into_arma_tuple! { 6, A B C D E F }
53impl_into_arma_tuple! { 7, A B C D E F G }
54impl_into_arma_tuple! { 8, A B C D E F G H }
55impl_into_arma_tuple! { 9, A B C D E F G H I }
56impl_into_arma_tuple! { 10, A B C D E F G H I J }
57impl_into_arma_tuple! { 11, A B C D E F G H I J K }
58impl_into_arma_tuple! { 12, A B C D E F G H I J K L }
59impl_into_arma_tuple! { 13, A B C D E F G H I J K L M }
60impl_into_arma_tuple! { 14, A B C D E F G H I J K L M N }
61impl_into_arma_tuple! { 15, A B C D E F G H I J K L M N O }
62impl_into_arma_tuple! { 16, A B C D E F G H I J K L M N O P }
63impl_into_arma_tuple! { 17, A B C D E F G H I J K L M N O P Q }
64impl_into_arma_tuple! { 18, A B C D E F G H I J K L M N O P Q R }
65impl_into_arma_tuple! { 19, A B C D E F G H I J K L M N O P Q R S }
66impl_into_arma_tuple! { 20, A B C D E F G H I J K L M N O P Q R S T }
67impl_into_arma_tuple! { 21, A B C D E F G H I J K L M N O P Q R S T U }
68impl_into_arma_tuple! { 22, A B C D E F G H I J K L M N O P Q R S T U V }
69impl_into_arma_tuple! { 23, A B C D E F G H I J K L M N O P Q R S T U V W }
70impl_into_arma_tuple! { 24, A B C D E F G H I J K L M N O P Q R S T U V W X }
71impl_into_arma_tuple! { 25, A B C D E F G H I J K L M N O P Q R S T U V W X Y }
72impl_into_arma_tuple! { 26, A B C D E F G H I J K L M N O P Q R S T U V W X Y Z }
73
74#[cfg(test)]
75#[test]
76fn test_tuples() {
77 let a = (1, "two");
78 assert_eq!(
79 Value::Array(vec![Value::Number(1.0), Value::String("two".to_string())]),
80 a.to_arma()
81 );
82}
83
84impl IntoArma for Vec<Value> {
85 fn to_arma(&self) -> Value {
86 Value::Array(self.clone())
87 }
88}
89
90impl<T> IntoArma for Vec<T>
91where
92 T: IntoArma,
93{
94 fn to_arma(&self) -> Value {
95 Value::Array(self.iter().map(IntoArma::to_arma).collect())
96 }
97}
98
99#[cfg(test)]
100#[test]
101fn test_vec() {
102 assert_eq!(String::from("[1,2,3]"), vec![1, 2, 3].to_arma().to_string());
103 assert_eq!(
104 String::from(r#"["hello","world"]"#),
105 vec!["hello", "world"].to_arma().to_string()
106 );
107}
108
109impl<T> IntoArma for &[T]
110where
111 T: IntoArma,
112{
113 fn to_arma(&self) -> Value {
114 Value::Array(self.iter().map(IntoArma::to_arma).collect())
115 }
116}
117
118#[cfg(test)]
119#[test]
120fn test_slice() {
121 assert_eq!(
122 String::from("[1,2,3]"),
123 vec![1, 2, 3].as_slice().to_arma().to_string()
124 );
125}
126
127impl IntoArma for String {
128 fn to_arma(&self) -> Value {
129 Value::String(self.clone())
130 }
131}
132
133#[cfg(test)]
134#[test]
135fn test_string() {
136 assert_eq!(
137 String::from("\"hello\""),
138 String::from("hello").to_arma().to_string()
139 );
140 assert_eq!(
141 String::from(r#""hello ""john"".""#),
142 String::from(r#"hello "john"."#).to_arma().to_string()
143 );
144}
145
146impl IntoArma for &'static str {
147 fn to_arma(&self) -> Value {
148 Value::String((*self).to_string())
149 }
150}
151
152#[cfg(test)]
153#[test]
154fn test_static_str() {
155 assert_eq!(String::from("\"hello\""), "hello".to_arma().to_string());
156}
157
158impl IntoArma for bool {
159 fn to_arma(&self) -> Value {
160 Value::Boolean(*self)
161 }
162}
163
164#[cfg(test)]
165#[test]
166fn test_bool() {
167 assert_eq!(String::from("true"), true.to_arma().to_string());
168}
169
170impl IntoArma for i8 {
171 fn to_arma(&self) -> Value {
172 Value::Number(f64::from(self.to_owned()))
173 }
174}
175
176#[cfg(test)]
177#[test]
178fn test_i8() {
179 assert_eq!(String::from("1"), 1i8.to_arma().to_string());
180}
181
182impl IntoArma for i16 {
183 fn to_arma(&self) -> Value {
184 Value::Number(f64::from(self.to_owned()))
185 }
186}
187
188#[cfg(test)]
189#[test]
190fn test_i16() {
191 assert_eq!(String::from("1"), 1i16.to_arma().to_string());
192}
193
194impl IntoArma for i32 {
195 fn to_arma(&self) -> Value {
196 Value::Number(f64::from(*self))
197 }
198}
199
200#[cfg(test)]
201#[test]
202fn test_i32() {
203 assert_eq!(String::from("1"), 1i32.to_arma().to_string());
204}
205
206impl IntoArma for f32 {
207 fn to_arma(&self) -> Value {
208 Value::Number(f64::from(*self))
209 }
210}
211
212#[cfg(test)]
213#[test]
214fn test_f32() {
215 assert_eq!(String::from("1"), 1f32.to_arma().to_string());
216 assert_eq!(String::from("1.5"), 1.5f32.to_arma().to_string());
217}
218
219impl IntoArma for f64 {
220 fn to_arma(&self) -> Value {
221 Value::Number(*self)
222 }
223}
224
225#[cfg(test)]
226#[test]
227fn test_f64() {
228 assert_eq!(String::from("1"), 1f64.to_arma().to_string());
229 assert_eq!(String::from("1.5"), 1.5f64.to_arma().to_string());
230}
231
232impl IntoArma for u8 {
233 fn to_arma(&self) -> Value {
234 Value::Number(f64::from(self.to_owned()))
235 }
236}
237
238#[cfg(test)]
239#[test]
240fn test_u8() {
241 assert_eq!(String::from("1"), 1u8.to_arma().to_string());
242}
243
244impl IntoArma for u16 {
245 fn to_arma(&self) -> Value {
246 Value::Number(f64::from(self.to_owned()))
247 }
248}
249
250#[cfg(test)]
251#[test]
252fn test_u16() {
253 assert_eq!(String::from("1"), 1u16.to_arma().to_string());
254}
255
256impl IntoArma for u32 {
257 fn to_arma(&self) -> Value {
258 Value::Number(f64::from(*self))
259 }
260}
261
262#[cfg(test)]
263#[test]
264fn test_u32() {
265 assert_eq!(String::from("1"), 1u32.to_arma().to_string());
266}
267
268impl<T: IntoArma> IntoArma for Option<T> {
269 fn to_arma(&self) -> Value {
270 self.as_ref().map_or(Value::Null, IntoArma::to_arma)
271 }
272}
273
274#[cfg(test)]
275#[test]
276fn test_option() {
277 assert_eq!(String::from("null"), None::<i32>.to_arma().to_string());
278 assert_eq!(String::from("1"), Some(1).to_arma().to_string());
279}
280
281impl<K, V, S> IntoArma for std::collections::HashMap<K, V, S>
282where
283 K: IntoArma,
284 V: IntoArma,
285 S: std::hash::BuildHasher,
286{
287 fn to_arma(&self) -> Value {
288 self.iter()
289 .map(|(k, v)| vec![k.to_arma(), v.to_arma()])
290 .collect::<Vec<Vec<Value>>>()
291 .to_arma()
292 }
293}
294
295impl<K, S> IntoArma for std::collections::HashMap<K, Value, S>
296where
297 K: IntoArma,
298 S: std::hash::BuildHasher,
299{
300 fn to_arma(&self) -> Value {
301 self.iter()
302 .map(|(k, v)| vec![k.to_arma(), v.clone()])
303 .collect::<Vec<Vec<Value>>>()
304 .to_arma()
305 }
306}
307
308#[cfg(test)]
309#[test]
310fn test_hashmap() {
311 use std::collections::HashMap;
312 {
313 let mut map = HashMap::new();
314 map.insert("key".to_string(), "value".to_string());
315 let map = map.to_arma();
316 assert_eq!(map.to_string(), r#"[["key","value"]]"#.to_string());
317 }
318 {
319 let mut map = HashMap::new();
320 map.insert("key1".to_string(), "value1".to_string());
321 map.insert("key2".to_string(), "value2".to_string());
322 let map = map.to_arma().to_string();
323 assert!(
324 map == r#"[["key1","value1"],["key2","value2"]]"#
325 || map == r#"[["key2","value2"],["key1","value1"]]"#
326 );
327 }
328}
329
330impl Value {
331 #[must_use]
332 pub const fn as_null(&self) -> Option<()> {
334 match self {
335 Self::Null => Some(()),
336 _ => None,
337 }
338 }
339
340 #[must_use]
341 pub const fn is_null(&self) -> bool {
343 self.as_null().is_some()
344 }
345
346 #[must_use]
347 pub const fn as_f64(&self) -> Option<f64> {
349 match *self {
350 Self::Number(n) => Some(n),
351 _ => None,
352 }
353 }
354
355 #[must_use]
356 pub const fn is_number(&self) -> bool {
358 self.as_f64().is_some()
359 }
360
361 #[must_use]
362 pub const fn as_vec(&self) -> Option<&Vec<Self>> {
364 match *self {
365 Self::Array(ref vec) => Some(vec),
366 _ => None,
367 }
368 }
369
370 #[must_use]
371 pub const fn is_array(&self) -> bool {
373 self.as_vec().is_some()
374 }
375
376 #[must_use]
377 pub const fn as_bool(&self) -> Option<bool> {
379 match *self {
380 Self::Boolean(bool) => Some(bool),
381 _ => None,
382 }
383 }
384
385 #[must_use]
386 pub const fn is_boolean(&self) -> bool {
388 self.as_bool().is_some()
389 }
390
391 #[must_use]
392 pub fn as_str(&self) -> Option<&str> {
394 match *self {
395 Self::String(ref string) => Some(string),
396 _ => None,
397 }
398 }
399
400 #[must_use]
401 pub fn is_string(&self) -> bool {
403 self.as_str().is_some()
404 }
405
406 #[must_use]
407 pub fn is_empty(&self) -> bool {
409 match self {
410 Self::Null => true,
411 Self::Number(n) => *n == 0.0,
412 Self::Array(a) => a.is_empty(),
413 Self::Boolean(b) => !*b,
414 Self::String(s) => s.is_empty(),
415 Self::Unknown(_) => false,
416 }
417 }
418}
419
420#[cfg(test)]
421mod tests {
422 use super::*;
423
424 #[test]
425 fn is_null() {
426 assert!(Value::Null.is_null());
427 assert!(!Value::Boolean(false).is_null());
428 }
429
430 #[test]
431 fn is_number() {
432 assert!(Value::Number(54.0).is_number());
433 assert!(!Value::Boolean(false).is_number());
434 }
435
436 #[test]
437 fn is_array() {
438 assert!(Value::Array(Vec::new()).is_array());
439 assert!(!Value::Boolean(false).is_array());
440 }
441
442 #[test]
443 fn is_boolean() {
444 assert!(Value::Boolean(false).is_boolean());
445 assert!(!Value::Number(54.0).is_boolean());
446 }
447
448 #[test]
449 fn is_string() {
450 assert!(Value::String(String::new()).is_string());
451 assert!(!Value::Boolean(false).is_string());
452 }
453
454 #[test]
455 fn as_nil() {
456 assert!(Value::Null.as_null().is_some());
457 }
458
459 #[test]
460 fn as_f32() {
461 let v = Value::Number(54.0).as_f64().unwrap();
462 assert!((54.0 - v) == 0.0);
463 }
464
465 #[test]
466 fn as_vec() {
467 let array = Value::Array(vec![Value::String("hello".into())]);
468 assert_eq!(array.to_string(), r#"["hello"]"#.to_string());
469 }
470
471 #[test]
472 fn as_bool() {
473 assert!(Value::Boolean(true).as_bool().unwrap());
474 }
475
476 #[test]
477 fn as_str() {
478 let v = Value::String("hello world".into());
479 let s = v.as_str().unwrap();
480 assert_eq!(s, "hello world");
481 }
482
483 #[test]
484 fn is_empty() {
485 assert!(Value::String(String::new()).is_empty());
486 assert!(Value::Array(vec![]).is_empty());
487 assert!(Value::Boolean(false).is_empty());
488 assert!(Value::String(String::new()).is_empty());
489 assert!(Value::Number(0.0).is_empty());
490 assert!(Value::Null.is_empty());
491
492 assert!(!Value::String("test".into()).is_empty());
493 assert!(!Value::Array(vec![Value::Boolean(false)]).is_empty());
494 assert!(!Value::Boolean(true).is_empty());
495 assert!(!Value::Number(55.0).is_empty());
496 }
497
498 #[test]
499 fn to_array() {
500 let array = Value::Array(vec![]);
501 assert_eq!(array.to_string(), r"[]".to_string());
502 }
503}