1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct MetadataIndex(pub generational_arena::Index);
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Metadatum {
Integer(u64),
Index(MetadataIndex),
String(String),
Struct(String, Vec<Metadatum>),
List(Vec<MetadataIndex>),
}
pub fn combine(
context: &mut crate::context::Context,
md_idx_a: &Option<MetadataIndex>,
md_idx_b: &Option<MetadataIndex>,
) -> Option<MetadataIndex> {
match (md_idx_a, md_idx_b) {
(None, None) => None,
(Some(_), None) => *md_idx_a,
(None, Some(_)) => *md_idx_b,
(Some(idx_a), Some(idx_b)) => {
let mut new_list = Vec::new();
if let Metadatum::List(lst_a) = &context.metadata[idx_a.0] {
new_list.append(&mut lst_a.clone());
} else {
new_list.push(*idx_a);
}
if let Metadatum::List(lst_b) = &context.metadata[idx_b.0] {
new_list.append(&mut lst_b.clone());
} else {
new_list.push(*idx_b);
}
Some(MetadataIndex(
context.metadata.insert(Metadatum::List(new_list)),
))
}
}
}
impl Metadatum {
pub fn unwrap_integer(&self) -> Option<u64> {
if let Metadatum::Integer(n) = self {
Some(*n)
} else {
None
}
}
pub fn unwrap_index(&self) -> Option<MetadataIndex> {
if let Metadatum::Index(idx) = self {
Some(*idx)
} else {
None
}
}
pub fn unwrap_string(&self) -> Option<&str> {
if let Metadatum::String(s) = self {
Some(s)
} else {
None
}
}
pub fn unwrap_struct<'a>(&'a self, tag: &str, num_fields: usize) -> Option<&'a [Metadatum]> {
match self {
Metadatum::Struct(t, fs) if t == tag && fs.len() == num_fields => Some(fs),
_otherwise => None,
}
}
}