Struct Msf

Source
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>

Source

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>

Source

pub fn open(file_name: &Path) -> Result<Self>

Opens an MSF file for read access, given a file name.

Source

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

pub fn modify(file_name: &Path) -> Result<Self>

Opens an existing MSF file for read/write access, given a file name.

Source§

impl<F: ReadAt> Msf<F>

Source

pub fn open_with_file(file: F) -> Result<Self>

Opens an MSF file for read access, given a File that has already been opened.

Source

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.

Source

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.

Source

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>

Source

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.

Source

pub fn new_stream_data(&mut self, data: &[u8]) -> Result<u32>
where F: ReadAt + WriteAt,

Adds a new stream to the MSF file, given the byte contents. This function returns the stream index of the new stream.

Source

pub fn nil_stream(&mut self) -> Result<u32>

Adds a new nil stream to the MSF file.

Source

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.

Source

pub fn copy_stream<Input: ReadAt>( &mut self, source: &Msf<Input>, source_stream: u32, ) -> Result<u32>
where F: ReadAt + WriteAt,

Copies a stream from another PDB/MSF into this one.

Source

pub fn copy_stream_read<Input: Read>( &mut self, source: &mut Input, ) -> Result<u32>
where F: ReadAt + WriteAt,

Copies a stream that implements Read into this PDB/MSF file.

Source

pub fn copy_stream_read_at<Input: ReadAt>( &mut self, source: &Input, ) -> Result<u32>
where F: ReadAt + WriteAt,

Copies a stream that implements ReadAt into this PDB/MSF file.

Source§

impl<F> Msf<F>

Source

pub fn page_size(&self) -> PageSize

Returns the page size used for this file.

Source

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, &[]).

Source

pub fn num_streams(&self) -> u32

The total number of streams in this PDB, including nil streams.

Source

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.

Source

pub fn is_valid_stream_index(&self, stream: u32) -> bool

Indicates whether a given stream index is valid.

Source

pub fn is_stream_valid(&self, stream: u32) -> bool

Indicates that a stream index is valid, and that its length is valid.

Source

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.

Source

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.

Source

pub fn into_file(self) -> F

Extracts the underlying file for this MSF. All pending modifications are dropped.

Source

pub fn file(&self) -> &F

Gets access to the contained file

Source

pub fn file_mut(&mut self) -> &mut F

Gets mutable access to the contained file

Source

pub fn is_writable(&self) -> bool

Indicates whether this Msf was opened for read/write access.

Source§

impl<F: ReadAt> Msf<F>

Source

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.

Source

pub fn read_stream_to_box(&self, stream: u32) -> Result<Box<[u8]>>

Reads the entire stream into a Box<[u8]>.

Source

pub fn read_stream_to_vec(&self, stream: u32) -> Result<Vec<u8>>

Reads an entire stream to a vector.

Source

pub fn read_stream_to_vec_mut( &self, stream: u32, stream_data: &mut Vec<u8>, ) -> Result<()>

Reads an entire stream into an existing vector.

Source

pub fn get_stream_reader(&self, stream: u32) -> Result<StreamReader<'_, F>>
where F: ReadAt,

Returns an object which can read from a given stream. The returned object implements the Read, Seek, and ReadAt traits.

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows 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
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows 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
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .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
where Self: BorrowMut<B>, B: ?Sized,

Calls .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
where Self: AsRef<R>, R: ?Sized,

Calls .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
where Self: AsMut<R>, R: ?Sized,

Calls .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
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more