Skip to main content

pe_assembler/formats/obj/
reader.rs

1use crate::{
2    helpers::{read_coff_header, read_coff_object, read_section_headers, CoffReader},
3    types::coff::{CoffHeader, CoffInfo, CoffObject, SectionHeader},
4};
5use gaia_types::{GaiaDiagnostics, GaiaError};
6use std::io::{Read, Seek};
7
8/// COFF 对象文件 (.obj) 结构,惰性读取器
9#[derive(Debug)]
10pub struct ObjReader<R> {
11    /// 二进制读取器(已定位到对象文件起始位置)
12    reader: R,
13    lazy_header: Option<CoffHeader>,
14    lazy_section_headers: Option<Vec<SectionHeader>>,
15    lazy_object: Option<CoffObject>,
16    lazy_info: Option<CoffInfo>,
17    diagnostics: Vec<GaiaError>,
18}
19
20impl<R> ObjReader<R> {
21    pub fn new(reader: R) -> Self {
22        Self { reader, lazy_header: None, lazy_section_headers: None, lazy_object: None, lazy_info: None, diagnostics: vec![] }
23    }
24}
25
26impl<W: Read + Seek> CoffReader<W> for ObjReader<W> {
27    fn get_viewer(&mut self) -> &mut W {
28        &mut self.reader
29    }
30
31    fn add_diagnostics(&mut self, error: impl Into<GaiaError>) {
32        self.diagnostics.push(error.into());
33    }
34
35    fn get_coff_header(&mut self) -> Result<&CoffHeader, GaiaError> {
36        if self.lazy_header.is_none() {
37            let header = read_coff_header(self)?;
38            self.lazy_header = Some(header);
39        }
40        Ok(self.lazy_header.as_ref().unwrap())
41    }
42
43    fn set_coff_header(&mut self, head: CoffHeader) -> Option<CoffHeader> {
44        self.lazy_header.replace(head)
45    }
46
47    fn get_section_headers(&mut self) -> Result<&[SectionHeader], GaiaError> {
48        if self.lazy_section_headers.is_none() {
49            let headers = read_section_headers(self)?;
50            self.lazy_section_headers = Some(headers);
51        }
52        Ok(self.lazy_section_headers.as_ref().unwrap())
53    }
54
55    fn set_section_headers(&mut self, headers: Vec<SectionHeader>) -> Vec<SectionHeader> {
56        self.lazy_section_headers.replace(headers).unwrap_or_default()
57    }
58
59    fn get_coff_object(&mut self) -> Result<&CoffObject, GaiaError> {
60        if self.lazy_object.is_none() {
61            let object = read_coff_object(self)?;
62            self.lazy_object = Some(object);
63        }
64        Ok(self.lazy_object.as_ref().unwrap())
65    }
66
67    fn set_coff_object(&mut self, object: CoffObject) -> Option<CoffObject> {
68        self.lazy_object.replace(object)
69    }
70
71    fn get_coff_info(&mut self) -> Result<&CoffInfo, GaiaError> {
72        if self.lazy_info.is_none() {
73            let info = self.create_coff_info()?;
74            self.lazy_info = Some(info);
75        }
76        Ok(self.lazy_info.as_ref().unwrap())
77    }
78
79    fn set_coff_info(&mut self, info: CoffInfo) -> Option<CoffInfo> {
80        self.lazy_info.replace(info)
81    }
82}
83
84impl<W: Read + Seek> ObjReader<W> {
85    /// 读取完整的 COFF 对象(惰性读取,会缓存结果)
86    pub fn read_object(mut self) -> GaiaDiagnostics<CoffObject> {
87        match self.get_coff_object() {
88            Ok(_) => match self.lazy_object {
89                Some(object) => GaiaDiagnostics { result: Ok(object), diagnostics: self.diagnostics },
90                None => unreachable!(),
91            },
92            Err(error) => GaiaDiagnostics { result: Err(error), diagnostics: self.diagnostics },
93        }
94    }
95
96    /// 查看 COFF 对象文件信息
97    pub fn view(&mut self) -> Result<CoffInfo, GaiaError> {
98        Ok(self.get_coff_info()?.clone())
99    }
100}