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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::context::Context;
#[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 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 MetadataIndex {
pub fn new_integer(context: &mut Context, int: u64) -> Self {
MetadataIndex(context.metadata.insert(Metadatum::Integer(int)))
}
pub fn new_index(context: &mut Context, idx: MetadataIndex) -> Self {
MetadataIndex(context.metadata.insert(Metadatum::Index(idx)))
}
pub fn new_string<S: Into<String>>(context: &mut Context, s: S) -> Self {
MetadataIndex(context.metadata.insert(Metadatum::String(s.into())))
}
pub fn new_struct<S: Into<String>>(
context: &mut Context,
tag: S,
fields: Vec<Metadatum>,
) -> Self {
MetadataIndex(
context
.metadata
.insert(Metadatum::Struct(tag.into(), fields)),
)
}
pub fn new_list(context: &mut Context, els: Vec<MetadataIndex>) -> Self {
MetadataIndex(context.metadata.insert(Metadatum::List(els)))
}
pub fn get_content<'a>(&self, context: &'a Context) -> &'a Metadatum {
&context.metadata[self.0]
}
}
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,
}
}
pub fn unwrap_list(&self) -> Option<&[MetadataIndex]> {
if let Metadatum::List(els) = self {
Some(els)
} else {
None
}
}
}