1use vermilion_vm::{VirtualMachine, VermilionSection, VermilionSymbol};
4use std::collections::HashMap;
5
6#[derive(Clone)]
8pub enum Symbol {
9
10 External(String),
12
13 Local(String, usize),
15
16}
17
18#[derive(Clone)]
20pub struct Artifact {
21
22 pub data: Vec<u8>,
24
25 pub program: Vec<u8>,
27
28 pub symbols: HashMap<i64, Symbol>,
30
31}
32
33impl Artifact {
34
35 pub fn new() -> Self {
37 Artifact {
38 data: vec![],
39 program: vec![],
40 symbols: HashMap::new(),
41 }
42 }
43
44 pub fn define_function(&mut self, id: i64, name: String, bytes: Vec<u8>) {
46 let start = self.program.len();
47 self.symbols.insert(id, Symbol::Local(name, start));
48 self.program.append(&mut bytes.clone());
49 }
50
51 pub fn declare_function(&mut self, id: i64, name: String) {
53 self.symbols.insert(id, Symbol::External(name));
54 }
55
56 pub fn new_vm(&mut self) -> VirtualMachine {
58 let mut vm = VirtualMachine::new();
59 self.load_vm(&mut vm);
60
61 vm
62 }
63
64 pub fn load_vm(&mut self, vm: &mut VirtualMachine) {
66 let mut program = self.program.clone();
68 let mut data = self.data.clone();
69 vm.heap.append(&mut program);
70 vm.heap.append(&mut data);
71
72 vm.sections.insert(0 as i64, VermilionSection(0, program.len()));
74 vm.sections.insert(1 as i64, VermilionSection(program.len(), program.len() + data.len()));
75
76 for symbol in self.symbols.clone() {
78 match symbol.1 {
79 Symbol::Local(name, home) => {
80 vm.symbols.insert(symbol.0, VermilionSymbol::Internal(name, home as i64));
81 },
82 Symbol::External(name) => {
83 vm.symbols.insert(symbol.0, VermilionSymbol::UndefinedExternal(name));
84 }
85 }
86 }
87 }
88
89 pub fn from_bytes(bytes: Vec<u8>) -> Result<Artifact, String> {
91 if bytes.len() < 5 {
92 return Err("Invalid magic word.".to_string());
93 }
94
95 if bytes.len() < 14 {
96 return Err("Invalid symbol count.".to_string());
97 }
98
99 let s = bytes[0..4].to_vec();
100 let expected = vec![
101 '_' as u8,
102 '_' as u8,
103 'v' as u8,
104 'r' as u8,
105 'm' as u8,
106 ];
107
108 if s != expected {
109 return Err("Invalid magic word.".to_string());
110 }
111
112 let st_length_bytes = &bytes[5..13];
113 let st_length = i64::from_le_bytes([
114 st_length_bytes[0],
115 st_length_bytes[1],
116 st_length_bytes[2],
117 st_length_bytes[3],
118 st_length_bytes[4],
119 st_length_bytes[5],
120 st_length_bytes[6],
121 st_length_bytes[7],
122 ]);
123
124 let mut start_byte = 14;
125 let mut i = 0;
126
127 let mut artifact = Artifact::new();
128
129 while i < st_length {
130 if bytes.len() < st_length as usize + 8 {
131 return Err("Invalid symbol id.".to_string());
132 }
133
134 let id_bytes = &bytes[start_byte..start_byte + 7];
135 let id = i64::from_le_bytes([
136 id_bytes[0],
137 id_bytes[1],
138 id_bytes[2],
139 id_bytes[3],
140 id_bytes[4],
141 id_bytes[5],
142 id_bytes[6],
143 id_bytes[7],
144 ]);
145
146 start_byte += 8;
147
148 if bytes.len() < st_length as usize + 8 {
149 return Err("Invalid symbol address.".to_string());
150 }
151
152 let home_bytes = &bytes[start_byte..start_byte + 7];
153 let home = i64::from_le_bytes([
154 home_bytes[0],
155 home_bytes[1],
156 home_bytes[2],
157 home_bytes[3],
158 home_bytes[4],
159 home_bytes[5],
160 home_bytes[6],
161 home_bytes[7],
162 ]);
163
164 start_byte += 8;
165
166 if bytes.len() < st_length as usize + 1 {
167 return Err("Invalid symbol address.".to_string());
168 }
169
170 let type_byte = bytes[start_byte];
171
172 start_byte += 1;
173
174 let mut name_bytes = Vec::new();
175 let mut ended = false;
176
177 while start_byte < bytes.len() {
178 if bytes[start_byte] == 0 {
179 ended = true;
180 break;
181 }
182
183 name_bytes.push(bytes[start_byte]);
184
185 start_byte += 1;
186 }
187
188 if !ended {
189 return Err("Unterminated string.".to_string());
190 }
191
192 match std::str::from_utf8(&name_bytes) {
193 Ok(name) => {
194 if type_byte == 0 {
195 artifact.symbols.insert(id, Symbol::Local(name.to_string(), home as usize));
197 } else {
198 artifact.symbols.insert(id, Symbol::External(name.to_string()));
200 }
201 },
202 Err(_) => {
203 return Err("Unable to convert string to utf8.".to_string());
204 }
205 }
206
207 start_byte += 1;
209 i += 1;
210 }
211
212 if bytes.len() < start_byte + 8 {
213 return Err("Unable to get size of data section.".to_string());
214 }
215
216 let data_bytes = &bytes[start_byte..start_byte + 7];
217 let data_size = i64::from_le_bytes([
218 data_bytes[0],
219 data_bytes[1],
220 data_bytes[2],
221 data_bytes[3],
222 data_bytes[4],
223 data_bytes[5],
224 data_bytes[6],
225 data_bytes[7],
226 ]);
227
228 if bytes.len() < (start_byte + data_size as usize + 1) {
229 return Err("File is too small for data section.".to_string());
230 }
231
232 let data = &bytes[start_byte..data_size as usize];
233 artifact.data = data.to_vec();
234
235 start_byte += data_size as usize;
236
237 let program = &bytes[start_byte..bytes.len() - 1];
238 artifact.program = program.to_vec();
239
240 Ok(artifact)
241 }
242
243 pub fn into_bytes(&mut self) -> Vec<u8> {
246 let mut bytes: Vec<u8> = vec![
247 '_' as u8,
248 '_' as u8,
249 'v' as u8,
250 'r' as u8,
251 'm' as u8,
252 ];
253
254 let l = self.symbols.len() as i64;
256 let le_bytes = l.to_le_bytes();
257 bytes.append(&mut le_bytes.to_vec());
258
259 for symbol in self.symbols.clone() {
260 let mut id_bytes = symbol.0.to_le_bytes().to_vec();
261 let mut home_bytes;
262 let type_byte;
263 let mut name_bytes;
264
265 match symbol.1 {
266 Symbol::External(n) => {
267 name_bytes = n.as_bytes().to_vec();
268 name_bytes.append(&mut vec![0]); home_bytes = vec![0, 0, 0, 0, 0, 0, 0, 0];
270 type_byte = 1;
271 },
272 Symbol::Local(n, home) => {
273 name_bytes = n.as_bytes().to_vec();
274 name_bytes.append(&mut vec![0]); home_bytes = home.to_le_bytes().to_vec();
276 type_byte = 0;
277 },
278 }
279
280 bytes.append(&mut id_bytes);
281 bytes.append(&mut home_bytes);
282 bytes.push(type_byte);
283 bytes.append(&mut name_bytes);
284 }
285
286 let mut data_len_bytes = self.data.len().to_le_bytes().to_vec();
287 bytes.append(&mut data_len_bytes);
288 bytes.append(&mut self.data);
289
290 bytes.append(&mut self.program);
291
292 bytes
293 }
294
295}