nyar_assembler/formats/nyarc/
reader.rs1use crate::program::types::{
2 NyarChunk, NyarClassInfo, NyarConstant, NyarExportInfo, NyarImplInfo, NyarImportInfo, NyarModule, NyarTraitInfo,
3};
4use gaia_binary::{BinaryReader, Leb128};
5use gaia_types::{GaiaError, QualifiedName};
6use std::io::Cursor;
7
8#[derive(Debug, Clone, Copy)]
10pub struct NyarcReader;
11
12impl NyarcReader {
13 pub fn read(data: &[u8]) -> Result<NyarModule, GaiaError> {
15 let mut cur = BinaryReader::<Cursor<&[u8]>, Leb128>::new(Cursor::new(data));
16
17 let magic = cur.read_u32()?;
19 if magic != 0x4E594152 {
20 return Err(GaiaError::invalid_data("Invalid header"));
21 }
22
23 let version = cur.read_u16()?;
24 let flags = cur.read_u32()?;
25 let timestamp = cur.read_u64()?;
26
27 let name = read_qualified_name(&mut cur)?;
29
30 let const_count = cur.read_u32()?;
32 let mut constants = Vec::with_capacity(const_count as usize);
33 for _ in 0..const_count {
34 let kind = cur.read_u8()?;
35 match kind {
36 0xFF => constants.push(NyarConstant::None),
37 0 => constants.push(NyarConstant::Int(cur.read_i64()?)),
38 1 => constants.push(NyarConstant::Float(cur.read_u64()?)),
39 2 => constants.push(NyarConstant::String(read_string(&mut cur)?)),
40 3 => constants.push(NyarConstant::QualifiedName(read_qualified_name(&mut cur)?)),
41 _ => return Err(GaiaError::invalid_data("Invalid constant kind")),
42 }
43 }
44
45 let effect_count = cur.read_u32()?;
47 let mut effects = Vec::with_capacity(effect_count as usize);
48 for _ in 0..effect_count {
49 effects.push(read_qualified_name(&mut cur)?);
50 }
51
52 let chunk_count = cur.read_u32()?;
54 let mut chunks = Vec::with_capacity(chunk_count as usize);
55 for _ in 0..chunk_count {
56 chunks.push(read_chunk(&mut cur)?);
57 }
58
59 let class_count = cur.read_u32()?;
61 let mut classes = Vec::with_capacity(class_count as usize);
62 for _ in 0..class_count {
63 let name = read_qualified_name(&mut cur)?;
64 let field_count = cur.read_u32()?;
65 let mut fields = Vec::with_capacity(field_count as usize);
66 for _ in 0..field_count {
67 fields.push(read_string(&mut cur)?);
68 }
69 classes.push(NyarClassInfo { name, fields });
70 }
71
72 let trait_count = cur.read_u32()?;
74 let mut traits = Vec::with_capacity(trait_count as usize);
75 for _ in 0..trait_count {
76 let name = read_qualified_name(&mut cur)?;
77 let method_count = cur.read_u32()?;
78 let mut methods = Vec::with_capacity(method_count as usize);
79 for _ in 0..method_count {
80 methods.push(read_string(&mut cur)?);
81 }
82 traits.push(NyarTraitInfo { name, methods });
83 }
84
85 let impl_count = cur.read_u32()?;
87 let mut impls = Vec::with_capacity(impl_count as usize);
88 for _ in 0..impl_count {
89 let class_idx = cur.read_u16()?;
90 let trait_idx = cur.read_u16()?;
91 let method_count = cur.read_u32()?;
92 let mut methods = Vec::with_capacity(method_count as usize);
93 for _ in 0..method_count {
94 methods.push(cur.read_u16()?);
95 }
96 impls.push(NyarImplInfo { class_idx, trait_idx, methods });
97 }
98
99 let import_count = cur.read_u32()?;
101 let mut imports = Vec::with_capacity(import_count as usize);
102 for _ in 0..import_count {
103 let provider = read_string(&mut cur)?;
104 let symbol = read_qualified_name(&mut cur)?;
105 imports.push(NyarImportInfo { provider, symbol });
106 }
107
108 let export_count = cur.read_u32()?;
110 let mut exports = Vec::with_capacity(export_count as usize);
111 for _ in 0..export_count {
112 let symbol = read_qualified_name(&mut cur)?;
113 let chunk_idx = cur.read_u16()?;
114 exports.push(NyarExportInfo { symbol, chunk_idx });
115 }
116
117 Ok(NyarModule { name, version, flags, timestamp, constants, effects, chunks, classes, traits, impls, imports, exports })
118 }
119}
120
121fn read_string(reader: &mut BinaryReader<Cursor<&[u8]>, Leb128>) -> Result<String, GaiaError> {
122 let len = reader.read_u32()? as usize;
123 let bytes = reader.read_bytes(len)?;
124 String::from_utf8(bytes).map_err(|_| GaiaError::invalid_data("Text parse error"))
125}
126
127fn read_qualified_name(reader: &mut BinaryReader<Cursor<&[u8]>, Leb128>) -> Result<QualifiedName, GaiaError> {
128 let part_count = reader.read_u32()? as usize;
129 let mut namespace = Vec::with_capacity(part_count);
130 for _ in 0..part_count {
131 namespace.push(read_string(reader)?);
132 }
133 let name = read_string(reader)?;
134 Ok(QualifiedName { namespace, name })
135}
136
137fn read_chunk(reader: &mut BinaryReader<Cursor<&[u8]>, Leb128>) -> Result<NyarChunk, GaiaError> {
138 let locals = reader.read_u16()?;
139 let upvalues = reader.read_u16()?;
140 let max_stack = reader.read_u16()?;
141 let code_size = reader.read_u32()? as usize;
142 let code = reader.read_bytes(code_size)?;
143
144 let line_count = reader.read_u32()?;
146 let mut lines = Vec::with_capacity(line_count as usize);
147 for _ in 0..line_count {
148 let offset = reader.read_u32()?;
149 let line = reader.read_u32()?;
150 lines.push((offset, line));
151 }
152
153 Ok(NyarChunk { locals, upvalues, max_stack, code, lines, ..Default::default() })
154}