1use std::collections::HashMap;
10use std::convert::TryFrom;
11use std::error::Error;
12use std::fmt;
13
14use schemars::JsonSchema;
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
26#[serde(untagged)]
27pub enum MetadataValue {
28 String(String),
29 Bool(bool),
30 Number(serde_json::Number),
31 List(Vec<MetadataValue>),
32 Map(MetadataMap),
33}
34
35impl MetadataValue {
36 fn variant_name(&self) -> &'static str {
38 match self {
39 MetadataValue::String(_) => "String",
40 MetadataValue::Bool(_) => "Bool",
41 MetadataValue::Number(_) => "Number",
42 MetadataValue::List(_) => "List",
43 MetadataValue::Map(_) => "Map",
44 }
45 }
46
47 pub fn as_str(&self) -> Option<&str> {
49 match self {
50 MetadataValue::String(s) => Some(s),
51 _ => None,
52 }
53 }
54
55 pub fn as_number(&self) -> Option<&serde_json::Number> {
56 match self {
57 MetadataValue::Number(n) => Some(n),
58 _ => None,
59 }
60 }
61
62 pub fn as_bool(&self) -> Option<bool> {
63 match self {
64 MetadataValue::Bool(v) => Some(*v),
65 _ => None,
66 }
67 }
68
69 pub fn as_list(&self) -> Option<&[MetadataValue]> {
70 match self {
71 MetadataValue::List(v) => Some(v.as_slice()),
72 _ => None,
73 }
74 }
75
76 pub fn as_map(&self) -> Option<&MetadataMap> {
77 match self {
78 MetadataValue::Map(m) => Some(m),
79 _ => None,
80 }
81 }
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
87pub enum MetadataConversionError {
88 WrongType {
89 expected: &'static str,
90 found: &'static str,
91 },
92 NumberOutOfRange {
93 expected: &'static str,
94 found: serde_json::Number,
95 },
96 FloatNotRepresentable,
99}
100
101impl fmt::Display for MetadataConversionError {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 match self {
104 MetadataConversionError::WrongType { expected, found } => {
105 write!(
106 f,
107 "wrong metadata value type: expected {expected}, found {found}"
108 )
109 }
110 MetadataConversionError::NumberOutOfRange { expected, found } => {
111 write!(
112 f,
113 "number out of range when converting metadata value: expected {expected}, found {found}"
114 )
115 }
116 MetadataConversionError::FloatNotRepresentable => {
117 write!(f, "float not representable for metadata value")
118 }
119 }
120 }
121}
122
123impl Error for MetadataConversionError {}
124
125impl From<String> for MetadataValue {
126 fn from(value: String) -> Self {
127 MetadataValue::String(value)
128 }
129}
130
131impl From<&str> for MetadataValue {
132 fn from(value: &str) -> Self {
133 MetadataValue::String(value.to_string())
134 }
135}
136
137impl From<i64> for MetadataValue {
138 fn from(value: i64) -> Self {
139 MetadataValue::Number(serde_json::Number::from(value))
140 }
141}
142
143impl From<bool> for MetadataValue {
144 fn from(value: bool) -> Self {
145 MetadataValue::Bool(value)
146 }
147}
148
149impl From<u64> for MetadataValue {
150 fn from(value: u64) -> Self {
151 MetadataValue::Number(serde_json::Number::from(value))
152 }
153}
154
155impl From<f64> for MetadataValue {
156 fn from(value: f64) -> Self {
157 serde_json::Number::from_f64(value)
159 .map(MetadataValue::Number)
160 .unwrap_or_else(|| MetadataValue::String(value.to_string()))
161 }
162}
163
164impl<T: Into<MetadataValue>> From<Vec<T>> for MetadataValue {
165 fn from(v: Vec<T>) -> Self {
166 MetadataValue::List(v.into_iter().map(|e| e.into()).collect())
167 }
168}
169
170impl From<MetadataMap> for MetadataValue {
171 fn from(m: MetadataMap) -> Self {
172 MetadataValue::Map(m)
173 }
174}
175
176impl TryFrom<MetadataValue> for String {
179 type Error = MetadataConversionError;
180
181 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
182 match value {
183 MetadataValue::String(s) => Ok(s),
184 other => Err(MetadataConversionError::WrongType {
185 expected: "String",
186 found: other.variant_name(),
187 }),
188 }
189 }
190}
191
192impl<'a> TryFrom<&'a MetadataValue> for &'a str {
193 type Error = MetadataConversionError;
194
195 fn try_from(value: &'a MetadataValue) -> Result<Self, Self::Error> {
196 match value {
197 MetadataValue::String(s) => Ok(s.as_str()),
198 other => Err(MetadataConversionError::WrongType {
199 expected: "String",
200 found: other.variant_name(),
201 }),
202 }
203 }
204}
205
206impl TryFrom<&MetadataValue> for String {
207 type Error = MetadataConversionError;
208
209 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
210 match value {
211 MetadataValue::String(s) => Ok(s.clone()),
212 other => Err(MetadataConversionError::WrongType {
213 expected: "String",
214 found: other.variant_name(),
215 }),
216 }
217 }
218}
219
220impl TryFrom<MetadataValue> for bool {
221 type Error = MetadataConversionError;
222
223 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
224 match value {
225 MetadataValue::Bool(v) => Ok(v),
226 other => Err(MetadataConversionError::WrongType {
227 expected: "Bool",
228 found: other.variant_name(),
229 }),
230 }
231 }
232}
233
234impl TryFrom<&MetadataValue> for bool {
235 type Error = MetadataConversionError;
236
237 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
238 match value {
239 MetadataValue::Bool(v) => Ok(*v),
240 other => Err(MetadataConversionError::WrongType {
241 expected: "Bool",
242 found: other.variant_name(),
243 }),
244 }
245 }
246}
247
248impl TryFrom<MetadataValue> for serde_json::Number {
249 type Error = MetadataConversionError;
250
251 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
252 match value {
253 MetadataValue::Number(n) => Ok(n),
254 other => Err(MetadataConversionError::WrongType {
255 expected: "Number",
256 found: other.variant_name(),
257 }),
258 }
259 }
260}
261
262impl TryFrom<&MetadataValue> for serde_json::Number {
263 type Error = MetadataConversionError;
264
265 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
266 match value {
267 MetadataValue::Number(n) => Ok(n.clone()),
268 other => Err(MetadataConversionError::WrongType {
269 expected: "Number",
270 found: other.variant_name(),
271 }),
272 }
273 }
274}
275
276impl TryFrom<MetadataValue> for i64 {
277 type Error = MetadataConversionError;
278
279 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
280 match value {
281 MetadataValue::Number(n) => {
282 n.as_i64().ok_or(MetadataConversionError::NumberOutOfRange {
283 expected: "i64",
284 found: n,
285 })
286 }
287 other => Err(MetadataConversionError::WrongType {
288 expected: "Number",
289 found: other.variant_name(),
290 }),
291 }
292 }
293}
294
295impl TryFrom<&MetadataValue> for i64 {
296 type Error = MetadataConversionError;
297
298 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
299 match value {
300 MetadataValue::Number(n) => {
301 n.as_i64().ok_or(MetadataConversionError::NumberOutOfRange {
302 expected: "i64",
303 found: n.clone(),
304 })
305 }
306 other => Err(MetadataConversionError::WrongType {
307 expected: "Number",
308 found: other.variant_name(),
309 }),
310 }
311 }
312}
313
314impl TryFrom<MetadataValue> for u64 {
315 type Error = MetadataConversionError;
316
317 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
318 match value {
319 MetadataValue::Number(n) => {
320 n.as_u64().ok_or(MetadataConversionError::NumberOutOfRange {
321 expected: "u64",
322 found: n,
323 })
324 }
325 other => Err(MetadataConversionError::WrongType {
326 expected: "Number",
327 found: other.variant_name(),
328 }),
329 }
330 }
331}
332
333impl TryFrom<&MetadataValue> for u64 {
334 type Error = MetadataConversionError;
335
336 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
337 match value {
338 MetadataValue::Number(n) => {
339 n.as_u64()
340 .ok_or_else(|| MetadataConversionError::NumberOutOfRange {
341 expected: "u64",
342 found: n.clone(),
343 })
344 }
345 other => Err(MetadataConversionError::WrongType {
346 expected: "Number",
347 found: other.variant_name(),
348 }),
349 }
350 }
351}
352
353impl TryFrom<MetadataValue> for f64 {
354 type Error = MetadataConversionError;
355
356 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
357 match value {
358 MetadataValue::Number(n) => n
359 .as_f64()
360 .ok_or(MetadataConversionError::FloatNotRepresentable),
361 other => Err(MetadataConversionError::WrongType {
362 expected: "Number",
363 found: other.variant_name(),
364 }),
365 }
366 }
367}
368
369impl TryFrom<&MetadataValue> for f64 {
370 type Error = MetadataConversionError;
371
372 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
373 match value {
374 MetadataValue::Number(n) => n
375 .as_f64()
376 .ok_or(MetadataConversionError::FloatNotRepresentable),
377 other => Err(MetadataConversionError::WrongType {
378 expected: "Number",
379 found: other.variant_name(),
380 }),
381 }
382 }
383}
384
385impl TryFrom<MetadataValue> for Vec<MetadataValue> {
386 type Error = MetadataConversionError;
387
388 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
389 match value {
390 MetadataValue::List(v) => Ok(v),
391 other => Err(MetadataConversionError::WrongType {
392 expected: "List",
393 found: other.variant_name(),
394 }),
395 }
396 }
397}
398
399impl TryFrom<&MetadataValue> for Vec<MetadataValue> {
400 type Error = MetadataConversionError;
401
402 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
403 match value {
404 MetadataValue::List(v) => Ok(v.clone()),
405 other => Err(MetadataConversionError::WrongType {
406 expected: "List",
407 found: other.variant_name(),
408 }),
409 }
410 }
411}
412
413impl TryFrom<MetadataValue> for MetadataMap {
414 type Error = MetadataConversionError;
415
416 fn try_from(value: MetadataValue) -> Result<Self, Self::Error> {
417 match value {
418 MetadataValue::Map(m) => Ok(m),
419 other => Err(MetadataConversionError::WrongType {
420 expected: "Map",
421 found: other.variant_name(),
422 }),
423 }
424 }
425}
426
427impl TryFrom<&MetadataValue> for MetadataMap {
428 type Error = MetadataConversionError;
429
430 fn try_from(value: &MetadataValue) -> Result<Self, Self::Error> {
431 match value {
432 MetadataValue::Map(m) => Ok(m.clone()),
433 other => Err(MetadataConversionError::WrongType {
434 expected: "Map",
435 found: other.variant_name(),
436 }),
437 }
438 }
439}
440
441#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default, JsonSchema)]
444pub struct MetadataMap {
445 #[serde(flatten)]
446 pub inner: HashMap<String, MetadataValue>,
447}
448
449impl MetadataMap {
450 pub fn new() -> Self {
452 Self {
453 inner: HashMap::new(),
454 }
455 }
456
457 pub fn iter(&self) -> impl Iterator<Item = (&String, &MetadataValue)> {
459 self.inner.iter()
460 }
461
462 pub fn insert<K: Into<String>, V: Into<MetadataValue>>(&mut self, key: K, value: V) {
464 self.inner.insert(key.into(), value.into());
465 }
466
467 pub fn get(&self, key: &str) -> Option<&MetadataValue> {
469 self.inner.get(key)
470 }
471
472 pub fn get_mut(&mut self, key: &str) -> Option<&mut MetadataValue> {
474 self.inner.get_mut(key)
475 }
476
477 pub fn is_empty(&self) -> bool {
479 self.inner.is_empty()
480 }
481
482 pub fn len(&self) -> usize {
484 self.inner.len()
485 }
486
487 pub fn extend(&mut self, other: MetadataMap) {
489 self.inner.extend(other.inner);
490 }
491}
492
493impl<K, V> std::iter::FromIterator<(K, V)> for MetadataMap
494where
495 K: Into<String>,
496 V: Into<MetadataValue>,
497{
498 fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
499 let mut map = MetadataMap::new();
500 for (k, v) in iter {
501 map.insert(k, v);
502 }
503 map
504 }
505}
506
507impl From<&MetadataValue> for prost_types::Value {
509 fn from(value: &MetadataValue) -> Self {
510 let kind = match value {
511 MetadataValue::String(s) => prost_types::value::Kind::StringValue(s.clone()),
512 MetadataValue::Bool(v) => prost_types::value::Kind::BoolValue(*v),
513 MetadataValue::Number(n) => {
514 prost_types::value::Kind::NumberValue(
516 n.as_f64().unwrap_or_else(|| n.as_i64().unwrap_or(0) as f64),
517 )
518 }
519 MetadataValue::List(list) => {
520 let values = list.iter().map(prost_types::Value::from).collect();
521 prost_types::value::Kind::ListValue(prost_types::ListValue { values })
522 }
523 MetadataValue::Map(map) => {
524 let fields = map
525 .inner
526 .iter()
527 .map(|(k, v)| (k.clone(), prost_types::Value::from(v)))
528 .collect();
529 prost_types::value::Kind::StructValue(prost_types::Struct { fields })
530 }
531 };
532
533 prost_types::Value { kind: Some(kind) }
534 }
535}
536
537#[cfg(test)]
538mod tests {
539 use std::f64;
540
541 use super::*;
542 use serde_json::{Value, json};
543
544 #[test]
545 fn insert_and_get_primitives() {
546 let mut m = MetadataMap::new();
547 m.insert("s", "hello");
548 m.insert("b", true);
549 m.insert("i", 42i64);
550 m.insert("u", 7u64);
551 m.insert("f", std::f64::consts::PI);
552
553 assert!(matches!(m.get("s"), Some(MetadataValue::String(v)) if v == "hello"));
554 assert!(matches!(m.get("b"), Some(MetadataValue::Bool(v)) if *v));
555 assert!(matches!(m.get("i"), Some(MetadataValue::Number(n)) if n.as_i64()==Some(42)));
556 assert!(matches!(m.get("u"), Some(MetadataValue::Number(n)) if n.as_u64()==Some(7)));
557 assert!(matches!(m.get("f"), Some(MetadataValue::Number(_))));
559 }
560
561 #[test]
562 fn list_and_nested_map() {
563 let mut child = MetadataMap::new();
564 child.insert("k", "v");
565
566 let mut root = MetadataMap::new();
567 root.insert("list", vec![1i64, 2i64, 3i64]);
568 root.insert("child", child.clone());
569
570 match root.get("list").unwrap() {
571 MetadataValue::List(v) => assert_eq!(v.len(), 3),
572 _ => panic!("expected list"),
573 }
574 match root.get("child").unwrap() {
575 MetadataValue::Map(m) => {
576 assert!(matches!(m.get("k"), Some(MetadataValue::String(s)) if s == "v"))
577 }
578 _ => panic!("expected map"),
579 }
580 }
581
582 #[test]
583 fn serialize_to_json() {
584 let mut m = MetadataMap::new();
585 m.insert("name", "slim");
586 m.insert("enabled", true);
587 m.insert("version", 1u64);
588 m.insert("values", vec!["a", "b", "c"]);
589 let mut nested = MetadataMap::new();
590 nested.insert("inner", 10i64);
591 m.insert("nested", nested);
592
593 let json_str = serde_json::to_string(&m).unwrap();
594 let v: Value = serde_json::from_str(&json_str).unwrap();
595 assert_eq!(v["name"], json!("slim"));
596 assert_eq!(v["enabled"], json!(true));
597 assert_eq!(v["version"], json!(1));
598 assert_eq!(v["values"], json!(["a", "b", "c"]));
599 assert_eq!(v["nested"]["inner"], json!(10));
600 }
601
602 #[test]
603 fn deserialize_from_json() {
604 let raw = r#"{
605 "alpha":"a",
606 "enabled": true,
607 "num": 5,
608 "list": [1,2,3],
609 "deep": {"k":"v","n":9}
610 }"#;
611 let m: MetadataMap = serde_json::from_str(raw).unwrap();
612 assert!(matches!(m.get("alpha"), Some(MetadataValue::String(s)) if s=="a"));
613 assert!(matches!(m.get("enabled"), Some(MetadataValue::Bool(v)) if *v));
614 assert!(matches!(m.get("num"), Some(MetadataValue::Number(n)) if n.as_i64()==Some(5)));
615 assert!(matches!(m.get("list"), Some(MetadataValue::List(v)) if v.len()==3));
616 match m.get("deep").unwrap() {
617 MetadataValue::Map(dm) => {
618 assert!(matches!(dm.get("k"), Some(MetadataValue::String(s)) if s=="v"));
619 assert!(
620 matches!(dm.get("n"), Some(MetadataValue::Number(n)) if n.as_i64()==Some(9))
621 );
622 }
623 _ => panic!("expected deep map"),
624 }
625 }
626
627 #[test]
628 fn overwrite_key() {
629 let mut m = MetadataMap::new();
630 m.insert("k", 1i64);
631 m.insert("k", "now_string");
632 assert!(matches!(m.get("k"), Some(MetadataValue::String(s)) if s=="now_string"));
633 }
634
635 #[test]
636 fn schema_generation() {
637 let _schema = schemars::schema_for!(MetadataMap);
639 }
640
641 #[test]
642 fn collect_into_metadata_map() {
643 let pairs = vec![("a", "alpha"), ("b", "beta"), ("c", "gamma")];
644 let m: MetadataMap = pairs.into_iter().collect();
645 assert_eq!(m.get("a").unwrap().as_str(), Some("alpha"));
646 assert_eq!(m.get("b").unwrap().as_str(), Some("beta"));
647 assert_eq!(m.get("c").unwrap().as_str(), Some("gamma"));
648 }
649
650 #[test]
651 fn try_from_string_ok() {
652 let v: MetadataValue = "hello".into();
653 let s: String = v.clone().try_into().unwrap();
654 assert_eq!(s, "hello");
655 let s_ref: &str = (&v).try_into().unwrap();
656 assert_eq!(s_ref, "hello");
657 }
658
659 #[test]
660 fn try_from_number_variants() {
661 let vu: MetadataValue = 10u64.into();
662 assert_eq!(u64::try_from(vu.clone()).unwrap(), 10);
663 assert_eq!(i64::try_from(vu.clone()).unwrap(), 10);
664 let vf: MetadataValue = f64::consts::PI.into();
665 let f = f64::try_from(vf.clone()).unwrap();
666 assert!((f - f64::consts::PI).abs() < 1e-10);
667 }
668
669 #[test]
670 fn try_from_wrong_type_errors() {
671 let v: MetadataValue = vec![1i64, 2i64].into();
672 let err = String::try_from(v.clone()).unwrap_err();
673 match err {
674 MetadataConversionError::WrongType { expected, found } => {
675 assert_eq!(expected, "String");
676 assert_eq!(found, "List");
677 }
678 _ => panic!("unexpected error variant"),
679 }
680 let err_num = i64::try_from(v.clone()).unwrap_err();
681 match err_num {
682 MetadataConversionError::WrongType { expected, found } => {
683 assert_eq!(expected, "Number");
684 assert_eq!(found, "List");
685 }
686 _ => panic!("unexpected error variant"),
687 }
688 }
689
690 #[test]
691 fn try_from_bool_ok() {
692 let v: MetadataValue = true.into();
693 let b: bool = v.clone().try_into().unwrap();
694 assert!(b);
695 let b_ref: bool = (&v).try_into().unwrap();
696 assert!(b_ref);
697 }
698
699 #[test]
700 fn number_out_of_range_for_i64() {
701 let big = MetadataValue::from(u64::MAX);
702 let err = i64::try_from(big).unwrap_err();
703 match err {
704 MetadataConversionError::NumberOutOfRange { expected, .. } => {
705 assert_eq!(expected, "i64");
706 }
707 _ => panic!("expected NumberOutOfRange"),
708 }
709 }
710
711 #[test]
712 fn extract_list_and_map() {
713 let mut child = MetadataMap::new();
714 child.insert("x", 1i64);
715
716 let list_val: MetadataValue = vec![1i64, 2i64].into();
717 let extracted_list: Vec<MetadataValue> = list_val.clone().try_into().unwrap();
718 assert_eq!(extracted_list.len(), 2);
719
720 let map_val: MetadataValue = child.clone().into();
721 let extracted_map: MetadataMap = map_val.try_into().unwrap();
722 assert_eq!(
723 extracted_map
724 .get("x")
725 .unwrap()
726 .as_number()
727 .unwrap()
728 .as_i64(),
729 Some(1)
730 );
731 }
732
733 #[test]
734 fn accessors_work() {
735 let s: MetadataValue = "abc".into();
736 assert_eq!(s.as_str(), Some("abc"));
737 assert!(s.as_number().is_none());
738
739 let n: MetadataValue = 42i64.into();
740 assert_eq!(n.as_number().unwrap().as_i64(), Some(42));
741 assert!(n.as_list().is_none());
742
743 let b: MetadataValue = true.into();
744 assert_eq!(b.as_bool(), Some(true));
745 assert!(b.as_number().is_none());
746
747 let lst: MetadataValue = vec![1i64, 2i64].into();
748 assert_eq!(lst.as_list().unwrap().len(), 2);
749 assert!(lst.as_map().is_none());
750
751 let mut m = MetadataMap::new();
752 m.insert("k", "v");
753 let mv: MetadataValue = m.clone().into();
754 assert_eq!(mv.as_map().unwrap().get("k").unwrap().as_str(), Some("v"));
755 }
756
757 #[test]
758 fn try_from_borrowed_refs() {
759 let v_num: MetadataValue = 7u64.into();
760 let borrowed_u: u64 = (&v_num).try_into().unwrap();
761 assert_eq!(borrowed_u, 7);
762 let borrowed_i: i64 = (&v_num).try_into().unwrap();
763 assert_eq!(borrowed_i, 7);
764
765 let v_str: MetadataValue = "hello".into();
766 let borrowed_str: &str = (&v_str).try_into().unwrap();
767 assert_eq!(borrowed_str, "hello");
768
769 let v_list: MetadataValue = vec!["a", "b"].into();
770 let borrowed_list: Vec<MetadataValue> = (&v_list).try_into().unwrap();
771 assert_eq!(borrowed_list.len(), 2);
772 }
773
774 #[test]
775 fn nan_fallback_is_string_and_fails_number_conversion() {
776 let v_nan: MetadataValue = f64::NAN.into(); let err = f64::try_from(v_nan.clone()).unwrap_err();
779 match err {
780 MetadataConversionError::WrongType { expected, found } => {
781 assert_eq!(expected, "Number");
782 assert_eq!(found, "String");
783 }
784 _ => panic!("unexpected error variant for NaN fallback"),
785 }
786 }
787
788 #[test]
789 fn negative_i64_not_u64() {
790 let neg: MetadataValue = (-5i64).into();
791 let err = u64::try_from(neg).unwrap_err();
792 match err {
793 MetadataConversionError::NumberOutOfRange { expected, .. } => {
794 assert_eq!(expected, "u64");
795 }
796 _ => panic!("expected NumberOutOfRange for negative to u64"),
797 }
798 }
799
800 #[test]
801 fn round_trip_all_variants() {
802 let s_mv: MetadataValue = "round".into();
804 assert_eq!(String::try_from(s_mv.clone()).unwrap(), "round");
805 let num_mv: MetadataValue = 123i64.into();
807 assert_eq!(i64::try_from(num_mv.clone()).unwrap(), 123);
808 assert_eq!(u64::try_from(num_mv.clone()).unwrap(), 123u64);
809 let list_mv: MetadataValue = vec!["x", "y"].into();
811 let vec_back: Vec<MetadataValue> = list_mv.clone().try_into().unwrap();
812 assert_eq!(vec_back.len(), 2);
813 let mut mm = MetadataMap::new();
815 mm.insert("a", 1i64);
816 let map_mv: MetadataValue = mm.clone().into();
817 let map_back: MetadataMap = map_mv.try_into().unwrap();
818 assert_eq!(
819 map_back
820 .get("a")
821 .unwrap()
822 .as_number()
823 .unwrap()
824 .as_i64()
825 .unwrap(),
826 1
827 );
828 }
829}