pub struct Msf<F = RandomAccessFile> { /* private fields */ }Expand description
Allows reading and writing the contents of a PDB/MSF file.
The Msf::open function opens an MSF file for read access, given a file. This is the most
commonly-used way to open a file.
Implementations§
Source§impl<F: ReadAt + WriteAt> Msf<F>
impl<F: ReadAt + WriteAt> Msf<F>
Sourcepub fn commit(&mut self) -> Result<bool>
pub fn commit(&mut self) -> Result<bool>
Commits all changes to the MSF file to disk.
The MSF file format is designed to support a very limited form of transactional commits. A single block write to the first page (located at the start of the file) can atomically commit all outstanding modifications to the MSF file.
This commit design does require that the underlying operating system handle the write to
page 0 in a single operation. Operating systems generally don’t contractually
guarantee atomicity of such writes, but in practice it’s true enough to be reasonably
reliable. The commit functionality of MSF is really designed to guard against application
failures, not failures of the operating system or its storage stack. So don’t rely on
commit() for anything more than best-effort service.
This commit() implementation does not permit multiple concurrent writers (or concurrent
readers and writers) to the underlying MSF/PDB file. If you manage to circumvent this,
you may damage the underlying MSF/PDB file.
This commit() implementation does not buffer modifications to stream contents. All
writes to stream contents are handled by immediately writing the data to the underlying
MSF file. However, these writes do not overwrite the data stored in the stream; instead,
new pages are allocated in the file for the new or modified stream contents. If an
application deletes a range of a stream (by resizing it), then the existing pages are
protected and cannot be overwritten until commit() is called.
Commit operations are moderately expensive. Applications that modify PDBs should generally
perform a single commit operation, not a series of commit operations. Each call to
commit() writes a new copy of the Stream Directory (the list of streams and their page
numbers) to disk. Because the existing Stream Directory cannot be overwritten (until
after the commit() operation completes), this means that all commit() operations
require that two complete copies of the Stream Directory persist on disk.
While it would be possible to reduce the size of an MSF file (after a commit completes) by
trimming the unused pages at the end of the MSF file, in practice this does not help much
because of page fragmentation. For this reason, commit() never reduces the size of the
underlying MSF file.
Returns Ok(true) if this Msf contained uncommitted changes and these changes have now
been committed.
Returns Ok(false) if this Msf did not contain any uncomitted changes. In this case,
no write() calls are issued to the underlying storage.
If this function returns Err, then the underlying MSF file may have had new pages written,
but the existing Stream Directory and header page should be intact. However, if the
underlying operating system did not write Page 0 atomically, then the underlying MSF
file may be irrecoverably damaged.
Also, if this function returns Err, the in-memory data structures that represent the
state of the Msf editor are not guaranteed to be in a consistent state.
Source§impl Msf<RandomAccessFile>
impl Msf<RandomAccessFile>
Sourcepub fn open(file_name: &Path) -> Result<Self>
pub fn open(file_name: &Path) -> Result<Self>
Opens an MSF file for read access, given a file name.
Sourcepub fn create(file_name: &Path, options: CreateOptions) -> Result<Self>
pub fn create(file_name: &Path, options: CreateOptions) -> Result<Self>
Creates a new MSF file on disk (truncating any existing file!) and creates a new
Msf object in-memory object with read/write access.
This function does not write anything to disk until stream data is written or
Self::commit is called.
Source§impl<F: ReadAt> Msf<F>
impl<F: ReadAt> Msf<F>
Sourcepub fn open_with_file(file: F) -> Result<Self>
pub fn open_with_file(file: F) -> Result<Self>
Opens an MSF file for read access, given a File that has already been opened.
Sourcepub fn create_with_file(file: F, options: CreateOptions) -> Result<Self>
pub fn create_with_file(file: F, options: CreateOptions) -> Result<Self>
Creates a new MSF file, given a file handle that has already been opened.
This function destroys the contents of the existing file.
Sourcepub fn modify_with_file(file: F) -> Result<Self>
pub fn modify_with_file(file: F) -> Result<Self>
Opens an existing MSF file for read/write access, given an File that has already
been opened.
The file handle will be used for absolute reads and writes. The caller should never use
this same file handle for reads (and especially not for writes) while also using Msf
because the operating system’s read/write file position may be updated by Msf.
Sourcepub fn create_for(file: F, options: CreateOptions) -> Result<Self>
pub fn create_for(file: F, options: CreateOptions) -> Result<Self>
Creates a new MSF object in memory. The on-disk file is not modified until commit() is
called.
Source§impl<F> Msf<F>
impl<F> Msf<F>
Sourcepub fn new_stream(&mut self) -> Result<(u32, StreamWriter<'_, F>)>
pub fn new_stream(&mut self) -> Result<(u32, StreamWriter<'_, F>)>
Adds a new stream to the MSF file. The stream has a length of zero.
Sourcepub fn new_stream_data(&mut self, data: &[u8]) -> Result<u32>
pub fn new_stream_data(&mut self, data: &[u8]) -> Result<u32>
Adds a new stream to the MSF file, given the byte contents. This function returns the stream index of the new stream.
Sourcepub fn nil_stream(&mut self) -> Result<u32>
pub fn nil_stream(&mut self) -> Result<u32>
Adds a new nil stream to the MSF file.
Sourcepub fn write_stream(&mut self, stream: u32) -> Result<StreamWriter<'_, F>>
pub fn write_stream(&mut self, stream: u32) -> Result<StreamWriter<'_, F>>
Given the stream index for a stream, returns a StreamWriter that allows read/write
for the stream.
If stream is out of range for the current set of streams, then the set of streams is
increased until stream is in range. For example, if a new MSF file is created, then
it is legal to immediately call msf.write_stream(10) on it. This will expand the Stream
Directory so that num_streams() returns 11 (because it must include the new stream index).
All streams lower than stream will be allocated as nil streams.
If stream is currently a nil stream, then this function promotes the stream to a
non-nil stream.
Sourcepub fn copy_stream<Input: ReadAt>(
&mut self,
source: &Msf<Input>,
source_stream: u32,
) -> Result<u32>
pub fn copy_stream<Input: ReadAt>( &mut self, source: &Msf<Input>, source_stream: u32, ) -> Result<u32>
Copies a stream from another PDB/MSF into this one.
Sourcepub fn copy_stream_read<Input: Read>(
&mut self,
source: &mut Input,
) -> Result<u32>
pub fn copy_stream_read<Input: Read>( &mut self, source: &mut Input, ) -> Result<u32>
Copies a stream that implements Read into this PDB/MSF file.
Source§impl<F> Msf<F>
impl<F> Msf<F>
Sourcepub fn stream_size_and_pages(&self, stream: u32) -> Result<(u32, &[u32]), Error>
pub fn stream_size_and_pages(&self, stream: u32) -> Result<(u32, &[u32]), Error>
Gets access to the stream page pointers for a given stream. The stream page pointers provide the mapping from offsets within a stream to offsets within the entire PDB (MSF) file.
If the stream is a NIL stream, then this returns (NIL_STREAM_SIZE, &[]).
Sourcepub fn num_streams(&self) -> u32
pub fn num_streams(&self) -> u32
The total number of streams in this PDB, including nil streams.
Sourcepub fn stream_size(&self, stream: u32) -> u32
pub fn stream_size(&self, stream: u32) -> u32
Gets the size of a given stream, in bytes.
The stream value must be in a valid range of 0..num_streams().
If stream is a NIL stream, this function returns 0.
Sourcepub fn is_valid_stream_index(&self, stream: u32) -> bool
pub fn is_valid_stream_index(&self, stream: u32) -> bool
Indicates whether a given stream index is valid.
Sourcepub fn is_stream_valid(&self, stream: u32) -> bool
pub fn is_stream_valid(&self, stream: u32) -> bool
Indicates that a stream index is valid, and that its length is valid.
Sourcepub fn nominal_size(&self) -> u64
pub fn nominal_size(&self) -> u64
Return the nominal length of this file, in bytes.
This is the number of pages multiplied by the page size. It is not guaranteed to be equal to the on-disk size of the file, but in practice it usually is.
Sourcepub fn num_free_pages(&self) -> u32
pub fn num_free_pages(&self) -> u32
Returns the number of free pages.
This number counts the pages that are less than num_pages. There may be pages assigned
to the MSF file beyond num_pages, but if there are then this does not count that space.
This value does not count Page 0, pages assigned to the FPM, streams, or the current Stream Directory. It does count pages assigned to the old stream directory.
Sourcepub fn into_file(self) -> F
pub fn into_file(self) -> F
Extracts the underlying file for this MSF. All pending modifications are dropped.
Sourcepub fn is_writable(&self) -> bool
pub fn is_writable(&self) -> bool
Indicates whether this Msf was opened for read/write access.
Source§impl<F: ReadAt> Msf<F>
impl<F: ReadAt> Msf<F>
Sourcepub fn read_stream_section_to_box(
&self,
stream: u32,
start: u32,
size: u32,
) -> Result<Box<[u8]>>where
F: ReadAt,
pub fn read_stream_section_to_box(
&self,
stream: u32,
start: u32,
size: u32,
) -> Result<Box<[u8]>>where
F: ReadAt,
Reads a portion of a stream to a vector.
Sourcepub fn read_stream_to_box(&self, stream: u32) -> Result<Box<[u8]>>
pub fn read_stream_to_box(&self, stream: u32) -> Result<Box<[u8]>>
Reads the entire stream into a Box<[u8]>.
Sourcepub fn read_stream_to_vec(&self, stream: u32) -> Result<Vec<u8>>
pub fn read_stream_to_vec(&self, stream: u32) -> Result<Vec<u8>>
Reads an entire stream to a vector.
Sourcepub fn read_stream_to_vec_mut(
&self,
stream: u32,
stream_data: &mut Vec<u8>,
) -> Result<()>
pub fn read_stream_to_vec_mut( &self, stream: u32, stream_data: &mut Vec<u8>, ) -> Result<()>
Reads an entire stream into an existing vector.
Sourcepub fn get_stream_reader(&self, stream: u32) -> Result<StreamReader<'_, F>>where
F: ReadAt,
pub fn get_stream_reader(&self, stream: u32) -> Result<StreamReader<'_, F>>where
F: ReadAt,
Auto Trait Implementations§
impl<F> Freeze for Msf<F>where
F: Freeze,
impl<F> RefUnwindSafe for Msf<F>where
F: RefUnwindSafe,
impl<F> Send for Msf<F>where
F: Send,
impl<F> Sync for Msf<F>where
F: Sync,
impl<F> Unpin for Msf<F>where
F: Unpin,
impl<F> UnwindSafe for Msf<F>where
F: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.