1use sway_types::SourceId;
2
3use crate::context::Context;
12
13#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
14pub struct MetadataIndex(pub slotmap::DefaultKey);
15
16#[derive(Clone, Debug, Eq, PartialEq, Hash)]
17pub enum Metadatum {
18 Integer(u64),
19 Index(MetadataIndex),
20 String(String),
21 SourceId(SourceId),
22 Struct(String, Vec<Metadatum>),
23 List(Vec<MetadataIndex>),
24}
25
26pub fn combine(
35 context: &mut Context,
36 md_idx_a: &Option<MetadataIndex>,
37 md_idx_b: &Option<MetadataIndex>,
38) -> Option<MetadataIndex> {
39 match (md_idx_a, md_idx_b) {
40 (None, None) => None,
41 (Some(_), None) => *md_idx_a,
42 (None, Some(_)) => *md_idx_b,
43 (Some(idx_a), Some(idx_b)) => {
44 let mut new_list = Vec::new();
47 if let Metadatum::List(lst_a) = &context.metadata[idx_a.0] {
48 new_list.append(&mut lst_a.clone());
49 } else {
50 new_list.push(*idx_a);
51 }
52 if let Metadatum::List(lst_b) = &context.metadata[idx_b.0] {
53 new_list.append(&mut lst_b.clone());
54 } else {
55 new_list.push(*idx_b);
56 }
57 Some(MetadataIndex(
58 context.metadata.insert(Metadatum::List(new_list)),
59 ))
60 }
61 }
62}
63
64impl MetadataIndex {
65 pub fn new_integer(context: &mut Context, int: u64) -> Self {
66 MetadataIndex(context.metadata.insert(Metadatum::Integer(int)))
67 }
68
69 pub fn new_index(context: &mut Context, idx: MetadataIndex) -> Self {
70 MetadataIndex(context.metadata.insert(Metadatum::Index(idx)))
71 }
72
73 pub fn new_source_id(context: &mut Context, id: SourceId) -> Self {
74 MetadataIndex(context.metadata.insert(Metadatum::SourceId(id)))
75 }
76
77 pub fn new_string<S: Into<String>>(context: &mut Context, s: S) -> Self {
78 MetadataIndex(context.metadata.insert(Metadatum::String(s.into())))
79 }
80
81 pub fn new_struct<S: Into<String>>(
82 context: &mut Context,
83 tag: S,
84 fields: Vec<Metadatum>,
85 ) -> Self {
86 MetadataIndex(
87 context
88 .metadata
89 .insert(Metadatum::Struct(tag.into(), fields)),
90 )
91 }
92
93 pub fn new_list(context: &mut Context, els: Vec<MetadataIndex>) -> Self {
94 MetadataIndex(context.metadata.insert(Metadatum::List(els)))
95 }
96
97 pub fn get_content<'a>(&self, context: &'a Context) -> &'a Metadatum {
98 &context.metadata[self.0]
99 }
100}
101
102impl Metadatum {
103 pub fn unwrap_integer(&self) -> Option<u64> {
104 if let Metadatum::Integer(n) = self {
105 Some(*n)
106 } else {
107 None
108 }
109 }
110
111 pub fn unwrap_index(&self) -> Option<MetadataIndex> {
112 if let Metadatum::Index(idx) = self {
113 Some(*idx)
114 } else {
115 None
116 }
117 }
118
119 pub fn unwrap_string(&self) -> Option<&str> {
120 if let Metadatum::String(s) = self {
121 Some(s)
122 } else {
123 None
124 }
125 }
126
127 pub fn unwrap_source_id(&self) -> Option<&SourceId> {
128 if let Metadatum::SourceId(id) = self {
129 Some(id)
130 } else {
131 None
132 }
133 }
134
135 pub fn unwrap_struct<'a>(&'a self, tag: &str, num_fields: usize) -> Option<&'a [Metadatum]> {
136 match self {
137 Metadatum::Struct(t, fs) if t == tag && fs.len() == num_fields => Some(fs),
138 _otherwise => None,
139 }
140 }
141
142 pub fn unwrap_list(&self) -> Option<&[MetadataIndex]> {
143 if let Metadatum::List(els) = self {
144 Some(els)
145 } else {
146 None
147 }
148 }
149}