diff options
Diffstat (limited to 'third_party/rust/minidump-writer/src/dir_section.rs')
-rw-r--r-- | third_party/rust/minidump-writer/src/dir_section.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/third_party/rust/minidump-writer/src/dir_section.rs b/third_party/rust/minidump-writer/src/dir_section.rs new file mode 100644 index 0000000000..ced5a2d156 --- /dev/null +++ b/third_party/rust/minidump-writer/src/dir_section.rs @@ -0,0 +1,103 @@ +use crate::{ + mem_writer::{Buffer, MemoryArrayWriter, MemoryWriterError}, + minidump_format::MDRawDirectory, +}; +use std::io::{Error, Seek, Write}; + +pub type DumpBuf = Buffer; + +#[derive(Debug, thiserror::Error)] +pub enum FileWriterError { + #[error("IO error")] + IOError(#[from] Error), + #[error("Failed to write to memory")] + MemoryWriterError(#[from] MemoryWriterError), +} + +/// Utility that wraps writing minidump directory entries to an I/O stream, generally +/// a [`std::fs::File`]. +#[derive(Debug)] +pub struct DirSection<'a, W> +where + W: Write + Seek, +{ + curr_idx: usize, + section: MemoryArrayWriter<MDRawDirectory>, + /// If we have to append to some file, we have to know where we currently are + destination_start_offset: u64, + destination: &'a mut W, + last_position_written_to_file: u64, +} + +impl<'a, W> DirSection<'a, W> +where + W: Write + Seek, +{ + pub fn new( + buffer: &mut DumpBuf, + index_length: u32, + destination: &'a mut W, + ) -> std::result::Result<Self, FileWriterError> { + let dir_section = + MemoryArrayWriter::<MDRawDirectory>::alloc_array(buffer, index_length as usize)?; + + Ok(Self { + curr_idx: 0, + section: dir_section, + destination_start_offset: destination.stream_position()?, + destination, + last_position_written_to_file: 0, + }) + } + + #[inline] + pub fn position(&self) -> u32 { + self.section.position + } + + pub fn dump_dir_entry( + &mut self, + buffer: &mut DumpBuf, + dirent: MDRawDirectory, + ) -> std::result::Result<(), FileWriterError> { + self.section.set_value_at(buffer, dirent, self.curr_idx)?; + + // Now write it to file + + // First get all the positions + let curr_file_pos = self.destination.stream_position()?; + let idx_pos = self.section.location_of_index(self.curr_idx); + self.curr_idx += 1; + + self.destination.seek(std::io::SeekFrom::Start( + self.destination_start_offset + idx_pos.rva as u64, + ))?; + let start = idx_pos.rva as usize; + let end = (idx_pos.rva + idx_pos.data_size) as usize; + self.destination.write_all(&buffer[start..end])?; + + // Reset file-position + self.destination + .seek(std::io::SeekFrom::Start(curr_file_pos))?; + + Ok(()) + } + + /// Writes 2 things to file: + /// 1. The given dirent into the dir section in the header (if any is given) + /// 2. Everything in the in-memory buffer that was added since the last call to this function + pub fn write_to_file( + &mut self, + buffer: &mut DumpBuf, + dirent: Option<MDRawDirectory>, + ) -> std::result::Result<(), FileWriterError> { + if let Some(dirent) = dirent { + self.dump_dir_entry(buffer, dirent)?; + } + + let start_pos = self.last_position_written_to_file as usize; + self.destination.write_all(&buffer[start_pos..])?; + self.last_position_written_to_file = buffer.position(); + Ok(()) + } +} |