pe_assembler/formats/obj/
reader.rs

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