1mod array;
2mod statement;
3mod table;
4mod value;
5
6use crate::error::{ParseEntryError, ParseItemError, ParseStringError, UnknownError};
7use crate::{Item, VdfError};
8pub use array::Array;
9pub use statement::Statement;
10use std::any::type_name;
11use std::collections::HashMap;
12use std::fmt::Formatter;
13use std::mem::swap;
14use std::slice;
15pub use table::Table;
16pub use value::Value;
17
18#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
20#[serde(untagged)]
21pub enum Entry {
22 Table(Table),
24
25 Array(Array),
27
28 Value(Value),
30
31 Statement(Statement),
33}
34
35impl From<Item<'_>> for Entry {
36 fn from(item: Item) -> Self {
37 match item {
38 Item::Item { content, .. } => Entry::Value(content.into()),
39 Item::Statement { content, .. } => Entry::Statement(content.into()),
40 }
41 }
42}
43
44impl Entry {
45 pub fn lookup<S: AsRef<str>>(&self, path: S) -> Option<&Entry> {
47 let mut current = self;
48
49 for name in path.as_ref().split('.') {
50 if let Some(entry) = current.get(name.trim()) {
51 current = entry;
52 } else {
53 return None;
54 }
55 }
56
57 Some(current)
58 }
59
60 pub fn get<S: AsRef<str>>(&self, name: S) -> Option<&Entry> {
62 match self {
63 Entry::Table(value) => value.get(name.as_ref()),
64
65 Entry::Array(value) => name
66 .as_ref()
67 .parse::<usize>()
68 .ok()
69 .and_then(|i| value.get(i)),
70
71 _ => None,
72 }
73 }
74
75 pub fn to<T: ParseItem>(self) -> Result<T, ParseEntryError> {
77 T::from_entry(self)
78 }
79
80 pub fn as_table(&self) -> Option<&Table> {
82 if let Entry::Table(value) = self {
83 Some(value)
84 } else {
85 None
86 }
87 }
88
89 pub fn as_slice(&self) -> Option<&[Entry]> {
91 if let Entry::Array(value) = self {
92 Some(value.as_slice())
93 } else {
94 unsafe { Some(slice::from_raw_parts(self, 1)) }
95 }
96 }
97
98 pub fn as_statement(&self) -> Option<&Statement> {
100 if let Entry::Statement(value) = self {
101 Some(value)
102 } else {
103 None
104 }
105 }
106
107 pub fn as_value(&self) -> Option<&Value> {
109 if let Entry::Value(value) = self {
110 Some(value)
111 } else {
112 None
113 }
114 }
115
116 pub fn as_str(&self) -> Option<&str> {
118 match self {
119 Entry::Value(value) => Some(value),
120 Entry::Statement(value) => Some(value),
121 _ => None,
122 }
123 }
124
125 pub fn parse<'a, T: Deserialize<'a>>(&'a self) -> Result<T, ParseEntryError> {
126 let str = self
127 .as_str()
128 .ok_or_else(|| ParseEntryError::new(type_name::<T>(), self.clone()))?;
129 let mut deserializer = crate::serde::Deserializer::from_str(str);
130 let result = T::deserialize(&mut deserializer)
131 .map_err(|_| ParseEntryError::new(type_name::<T>(), self.clone()))?;
132 if deserializer.next().is_some() {
133 Err(ParseEntryError::new(type_name::<T>(), self.clone()))
134 } else {
135 Ok(result)
136 }
137 }
138
139 fn into_array(self) -> Result<Self, ParseEntryError> {
140 match self {
141 Entry::Array(array) => Ok(Entry::Array(array)),
142 Entry::Value(value) => {
143 let mut array = Array::default();
144 array.push(value.into());
145 Ok(Entry::Array(array))
146 }
147 entry => Err(ParseEntryError::new("array", entry)),
148 }
149 }
150
151 pub fn push(&mut self, value: Entry) -> Result<(), ParseEntryError> {
153 let mut tmp = Entry::Value(Value::default());
154
155 swap(self, &mut tmp);
156 *self = tmp.into_array()?;
157 if let Entry::Array(array) = self {
158 array.push(value);
159 } else {
160 panic!("into_array ensured this is an array")
161 }
162 Ok(())
163 }
164}
165
166pub trait ParseItem: Sized {
168 fn from_entry(entry: Entry) -> Result<Self, ParseEntryError> {
170 let string = match entry.as_str() {
171 Some(string) => string,
172 None => {
173 return Err(ParseEntryError::new(type_name::<Self>(), entry));
174 }
175 };
176 Self::from_str(string).map_err(|e| ParseEntryError::new(e.ty, entry))
177 }
178
179 fn from_item(item: Item) -> Result<Self, ParseItemError> {
181 Self::from_str(item.as_str()).map_err(|e| ParseItemError::new(e.ty, item))
182 }
183
184 fn from_str(item: &str) -> Result<Self, ParseStringError>;
186}
187
188macro_rules! from_str {
189 (for) => ();
190
191 (for $ty:ident $($rest:tt)*) => (
192 from_str!($ty);
193 from_str!(for $($rest)*);
194 );
195
196 ($ty:ident) => (
197 impl ParseItem for $ty {
198 fn from_entry(entry: Entry) -> Result<Self, ParseEntryError> {
199 let string = match entry.as_str() {
200 Some(string) => string,
201 None => {
202 return Err(ParseEntryError::new(type_name::<Self>(), entry));
203 }
204 };
205 string.parse::<$ty>().map_err(|_| ParseEntryError::new(type_name::<Self>(), entry))
206 }
207
208 fn from_item(item: Item) -> Result<Self, ParseItemError> {
209 item.as_str().parse::<$ty>().map_err(|_| ParseItemError::new(type_name::<Self>(), item))
210 }
211
212 fn from_str(item: &str) -> Result<Self, ParseStringError> {
213 item.parse::<$ty>().map_err(|_| ParseStringError::new(type_name::<Self>(), item))
214 }
215 }
216 );
217}
218
219use crate::entry::array::{ArraySeq, TableArraySeq};
220use crate::entry::table::TableSeq;
221use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
222use serde::{Deserialize, Deserializer, Serialize};
223use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
224from_str!(for IpAddr Ipv4Addr Ipv6Addr SocketAddr SocketAddrV4 SocketAddrV6);
225from_str!(for i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64);
226
227impl ParseItem for bool {
228 fn from_str(item: &str) -> Result<Self, ParseStringError> {
229 match item {
230 "0" => Ok(false),
231 "1" => Ok(true),
232 v => v
233 .parse::<bool>()
234 .map_err(|_| ParseStringError::new(type_name::<Self>(), item)),
235 }
236 }
237}
238
239impl ParseItem for String {
240 fn from_entry(entry: Entry) -> Result<Self, ParseEntryError> {
241 match entry {
242 Entry::Table(entry) => Err(ParseEntryError::new(
243 type_name::<Self>(),
244 Entry::Table(entry),
245 )),
246 Entry::Array(entry) => Err(ParseEntryError::new(
247 type_name::<Self>(),
248 Entry::Array(entry),
249 )),
250 Entry::Statement(statement) => Ok(statement.into()),
251 Entry::Value(value) => Ok(value.into()),
252 }
253 }
254
255 fn from_item(item: Item) -> Result<Self, ParseItemError> {
256 Ok(item.into_content().into())
257 }
258
259 fn from_str(item: &str) -> Result<Self, ParseStringError> {
260 Ok(item.into())
261 }
262}
263
264impl<T: ParseItem> ParseItem for Option<T> {
265 fn from_entry(entry: Entry) -> Result<Self, ParseEntryError> {
266 T::from_entry(entry).map(Some)
267 }
268
269 fn from_item(item: Item) -> Result<Self, ParseItemError> {
270 T::from_item(item).map(Some)
271 }
272
273 fn from_str(item: &str) -> Result<Self, ParseStringError> {
274 T::from_str(item).map(Some)
275 }
276}
277
278impl<'de> Deserialize<'de> for Entry {
279 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
280 where
281 D: Deserializer<'de>,
282 {
283 struct EntryVisitor;
284
285 impl<'v> Visitor<'v> for EntryVisitor {
286 type Value = Entry;
287
288 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
289 write!(formatter, "any string like value or group")
290 }
291
292 fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
293 where
294 E: Error,
295 {
296 Ok(Entry::Value(v.to_string().into()))
297 }
298
299 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
300 where
301 E: Error,
302 {
303 Ok(Entry::Value(v.to_string().into()))
304 }
305
306 fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
307 where
308 E: Error,
309 {
310 Ok(Entry::Value(v.to_string().into()))
311 }
312
313 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
314 where
315 E: Error,
316 {
317 if v.starts_with('#') {
318 Ok(Entry::Statement(v.to_string().into()))
319 } else {
320 Ok(Entry::Value(v.to_string().into()))
321 }
322 }
323
324 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
325 where
326 E: Error,
327 {
328 if v.starts_with('#') {
329 Ok(Entry::Statement(v.into()))
330 } else {
331 Ok(Entry::Value(v.into()))
332 }
333 }
334
335 fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
336 where
337 E: Error,
338 {
339 let v = if v { "1" } else { "0" };
340 Ok(Entry::Value(v.to_string().into()))
341 }
342
343 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
344 where
345 A: MapAccess<'v>,
346 {
347 let mut res = HashMap::new();
348
349 while let Some(entry) = map.next_entry()? {
350 res.insert(entry.0, entry.1);
351 }
352
353 Ok(Entry::Table(res.into()))
354 }
355
356 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
357 where
358 A: SeqAccess<'v>,
359 {
360 let mut res = Vec::new();
361
362 while let Some(entry) = seq.next_element()? {
363 res.push(entry);
364 }
365
366 Ok(Entry::Array(res.into()))
367 }
368 }
369
370 deserializer.deserialize_any(EntryVisitor)
371 }
372}
373
374impl<'de> Deserializer<'de> for Entry {
375 type Error = VdfError;
376
377 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
378 where
379 V: Visitor<'de>,
380 {
381 match self {
382 Entry::Table(table) => visitor.visit_map(TableSeq::new(table)),
383 Entry::Array(array) => visitor.visit_seq(ArraySeq::new(array)),
384 Entry::Value(val) => val.deserialize_any(visitor),
385 Entry::Statement(val) => visitor.visit_string(val.into()),
386 }
387 }
388
389 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
390 where
391 V: Visitor<'de>,
392 {
393 match self {
394 Entry::Value(val) => val.deserialize_bool(visitor),
395 Entry::Statement(val) => Value::from(val).deserialize_bool(visitor),
396 _ => Err(UnknownError::from("bool").into()),
397 }
398 }
399
400 fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
401 where
402 V: Visitor<'de>,
403 {
404 match self {
405 Entry::Value(val) => val.deserialize_i8(visitor),
406 Entry::Statement(val) => Value::from(val).deserialize_i8(visitor),
407 _ => Err(UnknownError::from("i8").into()),
408 }
409 }
410
411 fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
412 where
413 V: Visitor<'de>,
414 {
415 match self {
416 Entry::Value(val) => val.deserialize_i16(visitor),
417 Entry::Statement(val) => Value::from(val).deserialize_i16(visitor),
418 _ => Err(UnknownError::from("i16").into()),
419 }
420 }
421
422 fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
423 where
424 V: Visitor<'de>,
425 {
426 match self {
427 Entry::Value(val) => val.deserialize_i32(visitor),
428 Entry::Statement(val) => Value::from(val).deserialize_i32(visitor),
429 _ => Err(UnknownError::from("i32").into()),
430 }
431 }
432
433 fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
434 where
435 V: Visitor<'de>,
436 {
437 match self {
438 Entry::Value(val) => val.deserialize_i64(visitor),
439 Entry::Statement(val) => Value::from(val).deserialize_i64(visitor),
440 _ => Err(UnknownError::from("i64").into()),
441 }
442 }
443
444 fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
445 where
446 V: Visitor<'de>,
447 {
448 match self {
449 Entry::Value(val) => val.deserialize_u8(visitor),
450 Entry::Statement(val) => Value::from(val).deserialize_u8(visitor),
451 _ => Err(UnknownError::from("u8").into()),
452 }
453 }
454
455 fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
456 where
457 V: Visitor<'de>,
458 {
459 match self {
460 Entry::Value(val) => val.deserialize_u16(visitor),
461 Entry::Statement(val) => Value::from(val).deserialize_u16(visitor),
462 _ => Err(UnknownError::from("u16").into()),
463 }
464 }
465
466 fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
467 where
468 V: Visitor<'de>,
469 {
470 match self {
471 Entry::Value(val) => val.deserialize_u32(visitor),
472 Entry::Statement(val) => Value::from(val).deserialize_u32(visitor),
473 _ => Err(UnknownError::from("u32").into()),
474 }
475 }
476
477 fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
478 where
479 V: Visitor<'de>,
480 {
481 match self {
482 Entry::Value(val) => val.deserialize_u64(visitor),
483 Entry::Statement(val) => Value::from(val).deserialize_u64(visitor),
484 _ => Err(UnknownError::from("u64").into()),
485 }
486 }
487
488 fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
489 where
490 V: Visitor<'de>,
491 {
492 match self {
493 Entry::Value(val) => val.deserialize_f32(visitor),
494 Entry::Statement(val) => Value::from(val).deserialize_f32(visitor),
495 _ => Err(UnknownError::from("f32").into()),
496 }
497 }
498
499 fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
500 where
501 V: Visitor<'de>,
502 {
503 match self {
504 Entry::Value(val) => val.deserialize_f64(visitor),
505 Entry::Statement(val) => Value::from(val).deserialize_f64(visitor),
506 _ => Err(UnknownError::from("f64").into()),
507 }
508 }
509
510 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
511 where
512 V: Visitor<'de>,
513 {
514 match self {
515 Entry::Value(val) => val.deserialize_char(visitor),
516 Entry::Statement(val) => Value::from(val).deserialize_char(visitor),
517 _ => Err(UnknownError::from("char").into()),
518 }
519 }
520
521 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
522 where
523 V: Visitor<'de>,
524 {
525 match self {
526 Entry::Value(val) => val.deserialize_str(visitor),
527 Entry::Statement(val) => Value::from(val).deserialize_str(visitor),
528 _ => Err(UnknownError::from("str").into()),
529 }
530 }
531
532 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
533 where
534 V: Visitor<'de>,
535 {
536 match self {
537 Entry::Value(val) => val.deserialize_string(visitor),
538 Entry::Statement(val) => Value::from(val).deserialize_string(visitor),
539 _ => Err(UnknownError::from("string1").into()),
540 }
541 }
542
543 fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
544 where
545 V: Visitor<'de>,
546 {
547 match self {
548 Entry::Value(val) => val.deserialize_bytes(visitor),
549 _ => Err(UnknownError::from("bytes").into()),
550 }
551 }
552
553 fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
554 where
555 V: Visitor<'de>,
556 {
557 match self {
558 Entry::Value(val) => val.deserialize_bool(visitor),
559 _ => Err(UnknownError::from("bytes buf").into()),
560 }
561 }
562
563 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
564 where
565 V: Visitor<'de>,
566 {
567 match self {
568 Entry::Value(val) => val.deserialize_option(visitor),
569 Entry::Statement(val) => Value::from(val).deserialize_option(visitor),
570 _ => Err(UnknownError::from("option").into()),
571 }
572 }
573
574 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
575 where
576 V: Visitor<'de>,
577 {
578 match self {
579 Entry::Value(val) => val.deserialize_unit(visitor),
580 Entry::Statement(val) => Value::from(val).deserialize_unit(visitor),
581 _ => Err(UnknownError::from("unit").into()),
582 }
583 }
584
585 fn deserialize_unit_struct<V>(
586 self,
587 name: &'static str,
588 visitor: V,
589 ) -> Result<V::Value, Self::Error>
590 where
591 V: Visitor<'de>,
592 {
593 match self {
594 Entry::Value(val) => val.deserialize_unit_struct(name, visitor),
595 Entry::Statement(val) => Value::from(val).deserialize_unit_struct(name, visitor),
596 _ => Err(UnknownError::from("unit_struct").into()),
597 }
598 }
599
600 fn deserialize_newtype_struct<V>(
601 self,
602 _name: &'static str,
603 _visitor: V,
604 ) -> Result<V::Value, Self::Error>
605 where
606 V: Visitor<'de>,
607 {
608 todo!()
609 }
610
611 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
612 where
613 V: Visitor<'de>,
614 {
615 match self {
616 Entry::Array(arr) => visitor.visit_seq(ArraySeq::new(arr)),
617 Entry::Table(table) => visitor.visit_seq(TableArraySeq::new(table)),
618 _ => Err(UnknownError::from("array").into()),
619 }
620 }
621
622 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
623 where
624 V: Visitor<'de>,
625 {
626 match self {
627 Entry::Array(arr) => visitor.visit_seq(ArraySeq::new(arr)),
628 _ => Err(UnknownError::from("tuple").into()),
629 }
630 }
631
632 fn deserialize_tuple_struct<V>(
633 self,
634 _name: &'static str,
635 _len: usize,
636 visitor: V,
637 ) -> Result<V::Value, Self::Error>
638 where
639 V: Visitor<'de>,
640 {
641 match self {
642 Entry::Array(arr) => visitor.visit_seq(ArraySeq::new(arr)),
643 _ => Err(UnknownError::from("tuple_struct").into()),
644 }
645 }
646
647 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
648 where
649 V: Visitor<'de>,
650 {
651 match self {
652 Entry::Table(table) => visitor.visit_map(TableSeq::new(table)),
653 _ => Err(UnknownError::from("map").into()),
654 }
655 }
656
657 fn deserialize_struct<V>(
658 self,
659 _name: &'static str,
660 _fields: &'static [&'static str],
661 visitor: V,
662 ) -> Result<V::Value, Self::Error>
663 where
664 V: Visitor<'de>,
665 {
666 self.deserialize_map(visitor)
667 }
668
669 fn deserialize_enum<V>(
670 self,
671 _name: &'static str,
672 _variants: &'static [&'static str],
673 visitor: V,
674 ) -> Result<V::Value, Self::Error>
675 where
676 V: Visitor<'de>,
677 {
678 struct EnVarAccess {
679 variant: Value,
680 value: Entry,
681 }
682 struct EnValAccess {
683 value: Entry,
684 }
685
686 impl<'de> EnumAccess<'de> for EnVarAccess {
687 type Error = VdfError;
688 type Variant = EnValAccess;
689
690 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
691 where
692 V: DeserializeSeed<'de>,
693 {
694 seed.deserialize(self.variant)
695 .map(|v| (v, EnValAccess { value: self.value }))
696 }
697 }
698
699 impl<'de> VariantAccess<'de> for EnValAccess {
700 type Error = VdfError;
701
702 fn unit_variant(self) -> Result<(), Self::Error> {
703 Err(UnknownError::from("unit").into())
704 }
705
706 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
707 where
708 T: DeserializeSeed<'de>,
709 {
710 seed.deserialize(self.value)
711 }
712
713 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
714 where
715 V: Visitor<'de>,
716 {
717 self.value.deserialize_seq(visitor)
718 }
719
720 fn struct_variant<V>(
721 self,
722 _fields: &'static [&'static str],
723 visitor: V,
724 ) -> Result<V::Value, Self::Error>
725 where
726 V: Visitor<'de>,
727 {
728 self.value.deserialize_map(visitor)
729 }
730 }
731
732 match self {
733 Entry::Table(table) if table.len() == 1 => {
734 let (variant, value) = HashMap::from(table).into_iter().next().unwrap();
735 visitor.visit_enum(EnVarAccess {
736 variant: variant.into(),
737 value,
738 })
739 }
740 _ => Err(UnknownError::from("enum").into()),
741 }
742 }
743
744 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
745 where
746 V: Visitor<'de>,
747 {
748 self.deserialize_string(visitor)
749 }
750
751 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
752 where
753 V: Visitor<'de>,
754 {
755 self.deserialize_any(visitor)
756 }
757}
758
759#[cfg(test)]
760#[track_caller]
761fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
762 r.map_err(miette::Error::from).unwrap()
763}
764
765#[test]
766fn test_serde_entry() {
767 use maplit::hashmap;
768
769 let j = r#"1"#;
770 assert_eq!(Entry::Value("1".into()), unwrap_err(crate::from_str(j)));
771
772 let j = r#""foo bar""#;
773 assert_eq!(
774 Entry::Value("foo bar".into()),
775 unwrap_err(crate::from_str(j))
776 );
777
778 let j = r#"{foo bar}"#;
779
780 assert_eq!(
781 Entry::Table(hashmap! {"foo".into() => Entry::Value("bar".into())}.into()),
782 unwrap_err(crate::from_str(j))
783 );
784
785 let j = r#""[1 2 3]""#;
786
787 assert_eq!(
788 Entry::Array(
789 vec![
790 Value::from("1").into(),
791 Value::from("2").into(),
792 Value::from("3").into()
793 ]
794 .into()
795 ),
796 unwrap_err(crate::from_str(j))
797 );
798
799 let j = r#""{1 2 3}""#;
800
801 assert_eq!(
802 Entry::Array(
803 vec![
804 Value::from("1").into(),
805 Value::from("2").into(),
806 Value::from("3").into()
807 ]
808 .into()
809 ),
810 unwrap_err(crate::from_str(j))
811 );
812}
813
814#[test]
815fn test_parse_entry() {
816 assert_eq!(1, Entry::Value("1".into()).parse::<usize>().unwrap());
817 assert_eq!(
818 vec!(1, 2, 3),
819 Entry::Value("1 2 3".into()).parse::<Vec<u8>>().unwrap()
820 );
821 assert_eq!(
822 (1, 2, 3),
823 Entry::Value("1 2 3".into())
824 .parse::<(u8, u8, u8)>()
825 .unwrap()
826 );
827}
828
829pub(crate) fn string_is_array(string: &str) -> bool {
830 (string.starts_with('[') && string.ends_with(']'))
831 || (string.starts_with('{') && string.ends_with('}'))
832}