1use super::Value;
2
3pub trait IntoArma {
5 fn to_arma(&self) -> Value;
7}
8
9pub struct DirectReturn(Value);
10impl Value {
11 pub 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.to_string())
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 match self {
271 Some(v) => v.to_arma(),
272 None => Value::Null,
273 }
274 }
275}
276
277#[cfg(test)]
278#[test]
279fn test_option() {
280 assert_eq!(String::from("null"), None::<i32>.to_arma().to_string());
281 assert_eq!(String::from("1"), Some(1).to_arma().to_string());
282}
283
284impl<K, V, S> IntoArma for std::collections::HashMap<K, V, S>
285where
286 K: IntoArma,
287 V: IntoArma,
288 S: std::hash::BuildHasher,
289{
290 fn to_arma(&self) -> Value {
291 self.iter()
292 .map(|(k, v)| vec![k.to_arma(), v.to_arma()])
293 .collect::<Vec<Vec<Value>>>()
294 .to_arma()
295 }
296}
297
298impl<K, S> IntoArma for std::collections::HashMap<K, Value, S>
299where
300 K: IntoArma,
301 S: std::hash::BuildHasher,
302{
303 fn to_arma(&self) -> Value {
304 self.iter()
305 .map(|(k, v)| vec![k.to_arma(), v.clone()])
306 .collect::<Vec<Vec<Value>>>()
307 .to_arma()
308 }
309}
310
311#[cfg(test)]
312#[test]
313fn test_hashmap() {
314 use std::collections::HashMap;
315 {
316 let mut map = HashMap::new();
317 map.insert("key".to_string(), "value".to_string());
318 let map = map.to_arma();
319 assert_eq!(map.to_string(), r#"[["key","value"]]"#.to_string());
320 }
321 {
322 let mut map = HashMap::new();
323 map.insert("key1".to_string(), "value1".to_string());
324 map.insert("key2".to_string(), "value2".to_string());
325 let map = map.to_arma().to_string();
326 assert!(
327 map == r#"[["key1","value1"],["key2","value2"]]"#
328 || map == r#"[["key2","value2"],["key1","value1"]]"#
329 )
330 }
331}
332
333impl Value {
334 #[must_use]
335 pub const fn as_null(&self) -> Option<()> {
337 match self {
338 Self::Null => Some(()),
339 _ => None,
340 }
341 }
342
343 #[must_use]
344 pub const fn is_null(&self) -> bool {
346 self.as_null().is_some()
347 }
348
349 #[must_use]
350 pub const fn as_f64(&self) -> Option<f64> {
352 match *self {
353 Self::Number(n) => Some(n),
354 _ => None,
355 }
356 }
357
358 #[must_use]
359 pub const fn is_number(&self) -> bool {
361 self.as_f64().is_some()
362 }
363
364 #[must_use]
365 pub const fn as_vec(&self) -> Option<&Vec<Self>> {
367 match *self {
368 Self::Array(ref vec) => Some(vec),
369 _ => None,
370 }
371 }
372
373 #[must_use]
374 pub const fn is_array(&self) -> bool {
376 self.as_vec().is_some()
377 }
378
379 #[must_use]
380 pub const fn as_bool(&self) -> Option<bool> {
382 match *self {
383 Self::Boolean(bool) => Some(bool),
384 _ => None,
385 }
386 }
387
388 #[must_use]
389 pub const fn is_boolean(&self) -> bool {
391 self.as_bool().is_some()
392 }
393
394 #[must_use]
395 pub fn as_str(&self) -> Option<&str> {
397 match *self {
398 Self::String(ref string) => Some(string),
399 _ => None,
400 }
401 }
402
403 #[must_use]
404 pub fn is_string(&self) -> bool {
406 self.as_str().is_some()
407 }
408
409 #[must_use]
410 pub fn is_empty(&self) -> bool {
412 match self {
413 Self::Null => true,
414 Self::Number(n) => *n == 0.0,
415 Self::Array(a) => a.is_empty(),
416 Self::Boolean(b) => !*b,
417 Self::String(s) => s.is_empty(),
418 _ => false,
419 }
420 }
421}
422
423#[cfg(test)]
424mod tests {
425 use super::*;
426
427 #[test]
428 fn is_null() {
429 assert!(Value::Null.is_null());
430 assert!(!Value::Boolean(false).is_null());
431 }
432
433 #[test]
434 fn is_number() {
435 assert!(Value::Number(54.0).is_number());
436 assert!(!Value::Boolean(false).is_number());
437 }
438
439 #[test]
440 fn is_array() {
441 assert!(Value::Array(Vec::new()).is_array());
442 assert!(!Value::Boolean(false).is_array());
443 }
444
445 #[test]
446 fn is_boolean() {
447 assert!(Value::Boolean(false).is_boolean());
448 assert!(!Value::Number(54.0).is_boolean());
449 }
450
451 #[test]
452 fn is_string() {
453 assert!(Value::String(String::new()).is_string());
454 assert!(!Value::Boolean(false).is_string());
455 }
456
457 #[test]
458 fn as_nil() {
459 assert!(Value::Null.as_null().is_some())
460 }
461
462 #[test]
463 fn as_f32() {
464 let v = Value::Number(54.0).as_f64().unwrap();
465 assert!((54.0 - v) == 0.0)
466 }
467
468 #[test]
469 fn as_vec() {
470 let array = Value::Array(vec![Value::String("hello".into())]);
471 assert_eq!(array.to_string(), r#"["hello"]"#.to_string());
472 }
473
474 #[test]
475 fn as_bool() {
476 assert!(Value::Boolean(true).as_bool().unwrap());
477 }
478
479 #[test]
480 fn as_str() {
481 let v = Value::String("hello world".into());
482 let s = v.as_str().unwrap();
483 assert_eq!(s, "hello world");
484 }
485
486 #[test]
487 fn is_empty() {
488 assert!(Value::String("".into()).is_empty());
489 assert!(Value::Array(vec![]).is_empty());
490 assert!(Value::Boolean(false).is_empty());
491 assert!(Value::String(String::new()).is_empty());
492 assert!(Value::Number(0.0).is_empty());
493 assert!(Value::Null.is_empty());
494
495 assert!(!Value::String("test".into()).is_empty());
496 assert!(!Value::Array(vec![Value::Boolean(false)]).is_empty());
497 assert!(!Value::Boolean(true).is_empty());
498 assert!(!Value::Number(55.0).is_empty());
499 }
500
501 #[test]
502 fn to_array() {
503 let array = Value::Array(vec![]);
504 assert_eq!(array.to_string(), r#"[]"#.to_string());
505 }
506}