pe_assembler/formats/obj/
reader.rs1use crate::{
2 helpers::CoffReader,
3 types::coff::{CoffHeader, CoffInfo, CoffObject, SectionHeader},
4};
5use byteorder::LittleEndian;
6use gaia_types::{BinaryReader, GaiaDiagnostics, GaiaError};
7use std::{
8 fs::File,
9 io::{Read, Seek},
10 path::Path,
11};
12
13#[derive(Debug)]
15pub struct ObjReader<R> {
16 viewer: BinaryReader<R, LittleEndian>,
18 lazy_header: Option<CoffHeader>,
19 lazy_section_headers: Option<Vec<SectionHeader>>,
20 lazy_object: Option<CoffObject>,
21 lazy_info: Option<CoffInfo>,
22 diagnostics: Vec<GaiaError>,
23}
24
25impl<R> ObjReader<R> {
26 pub fn new(reader: R) -> Self {
27 Self {
28 viewer: BinaryReader::new(reader),
29 lazy_header: None,
30 lazy_section_headers: None,
31 lazy_object: None,
32 lazy_info: None,
33 diagnostics: vec![],
34 }
35 }
36}
37
38impl<W: Read + Seek> CoffReader<W> for ObjReader<W> {
39 fn get_viewer(&mut self) -> &mut BinaryReader<W, LittleEndian> {
40 &mut self.viewer
41 }
42
43 fn add_diagnostics(&mut self, error: impl Into<GaiaError>) {
44 self.diagnostics.push(error.into());
45 }
46
47 fn get_cached_section_headers(&self) -> Option<&Vec<SectionHeader>> {
48 self.lazy_section_headers.as_ref()
49 }
50
51 fn set_cached_section_headers(&mut self, headers: Vec<SectionHeader>) {
52 self.lazy_section_headers = Some(headers);
53 }
54
55 fn read_header_once(&mut self) -> Result<&CoffHeader, GaiaError> {
56 if self.lazy_header.is_none() {
57 self.lazy_header = Some(self.read_header_force()?);
58 }
59 match self.lazy_header.as_ref() {
60 Some(s) => Ok(s),
61 None => unreachable!(),
62 }
63 }
64
65 fn read_object_once(&mut self) -> Result<&CoffObject, GaiaError> {
66 if self.lazy_object.is_none() {
67 self.lazy_object = Some(self.read_object_force()?);
68 }
69 match self.lazy_object.as_ref() {
70 Some(s) => Ok(s),
71 None => unreachable!(),
72 }
73 }
74}
75
76impl<W: Read + Seek> ObjReader<W> {
77 pub fn read_object(mut self) -> GaiaDiagnostics<CoffObject> {
79 match self.read_object_once() {
80 Ok(_) => match self.lazy_object {
81 Some(object) => GaiaDiagnostics { result: Ok(object), diagnostics: self.diagnostics },
82 None => unreachable!(),
83 },
84 Err(error) => GaiaDiagnostics { result: Err(error), diagnostics: self.diagnostics },
85 }
86 }
87
88 pub fn view(&mut self) -> Result<CoffInfo, GaiaError> {
90 if let Some(ref info) = self.lazy_info {
91 return Ok(info.clone());
92 }
93
94 let info = self.create_coff_info()?;
95 self.lazy_info = Some(info.clone());
96 Ok(info)
97 }
98}
99
100impl ObjReader<File> {
101 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, GaiaError> {
103 let file = File::open(path).map_err(|e| GaiaError::invalid_data(&format!("无法打开文件: {}", e)))?;
104 Ok(Self::new(file))
105 }
106}
107
108pub fn read_coff_from_file<P: AsRef<Path>>(path: P) -> Result<CoffObject, GaiaError> {
110 let reader = ObjReader::<File>::from_file(path)?;
111 let result = reader.read_object();
112 result.result
113}