Skip to main content

nyar_assembler/formats/nyarc/
reader.rs

1use 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/// Nyarc 格式读取器
9#[derive(Debug, Clone, Copy)]
10pub struct NyarcReader;
11
12impl NyarcReader {
13    /// 从二进制流中读取 NyarModule
14    pub fn read(data: &[u8]) -> Result<NyarModule, GaiaError> {
15        let mut cur = BinaryReader::<Cursor<&[u8]>, Leb128>::new(Cursor::new(data));
16
17        // 读取头部
18        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        // 读取模块名称
28        let name = read_qualified_name(&mut cur)?;
29
30        // 读取常量池
31        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        // 读取副作用名称
46        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        // 读取代码块
53        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        // 读取类信息
60        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        // 读取特征信息
73        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        // 读取实现信息
86        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        // 读取导入信息
100        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        // 读取导出信息
109        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    // 读取行号信息
145    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}