minidump_writer/
dir_section.rs1use {
2 crate::{
3 mem_writer::{Buffer, MemoryArrayWriter, MemoryWriterError},
4 minidump_format::MDRawDirectory,
5 serializers::*,
6 },
7 std::io::{Error, Seek, Write},
8};
9
10pub type DumpBuf = Buffer;
11
12#[derive(Debug, thiserror::Error, serde::Serialize)]
13pub enum FileWriterError {
14 #[error("IO error")]
15 IOError(
16 #[from]
17 #[serde(serialize_with = "serialize_io_error")]
18 Error,
19 ),
20 #[error("Failed to write to memory")]
21 MemoryWriterError(#[from] MemoryWriterError),
22}
23
24#[derive(Debug)]
27pub struct DirSection<'a, W>
28where
29 W: Write + Seek,
30{
31 curr_idx: usize,
32 section: MemoryArrayWriter<MDRawDirectory>,
33 destination_start_offset: u64,
35 destination: &'a mut W,
36 last_position_written_to_file: u64,
37}
38
39impl<'a, W> DirSection<'a, W>
40where
41 W: Write + Seek,
42{
43 pub fn new(
44 buffer: &mut DumpBuf,
45 index_length: u32,
46 destination: &'a mut W,
47 ) -> std::result::Result<Self, FileWriterError> {
48 let dir_section =
49 MemoryArrayWriter::<MDRawDirectory>::alloc_array(buffer, index_length as usize)?;
50
51 Ok(Self {
52 curr_idx: 0,
53 section: dir_section,
54 destination_start_offset: destination.stream_position()?,
55 destination,
56 last_position_written_to_file: 0,
57 })
58 }
59
60 #[inline]
61 pub fn position(&self) -> u32 {
62 self.section.position
63 }
64
65 pub fn dump_dir_entry(
66 &mut self,
67 buffer: &mut DumpBuf,
68 dirent: MDRawDirectory,
69 ) -> std::result::Result<(), FileWriterError> {
70 self.section.set_value_at(buffer, dirent, self.curr_idx)?;
71
72 let curr_file_pos = self.destination.stream_position()?;
76 let idx_pos = self.section.location_of_index(self.curr_idx);
77 self.curr_idx += 1;
78
79 self.destination.seek(std::io::SeekFrom::Start(
80 self.destination_start_offset + idx_pos.rva as u64,
81 ))?;
82 let start = idx_pos.rva as usize;
83 let end = (idx_pos.rva + idx_pos.data_size) as usize;
84 self.destination.write_all(&buffer[start..end])?;
85
86 self.destination
88 .seek(std::io::SeekFrom::Start(curr_file_pos))?;
89
90 Ok(())
91 }
92
93 pub fn write_to_file(
97 &mut self,
98 buffer: &mut DumpBuf,
99 dirent: Option<MDRawDirectory>,
100 ) -> std::result::Result<(), FileWriterError> {
101 if let Some(dirent) = dirent {
102 self.dump_dir_entry(buffer, dirent)?;
103 }
104
105 let start_pos = self.last_position_written_to_file as usize;
106 self.destination.write_all(&buffer[start_pos..])?;
107 self.last_position_written_to_file = buffer.position();
108 Ok(())
109 }
110}