Skip to main content

ForwardSearch

Struct ForwardSearch 

Source
pub struct ForwardSearch { /* private fields */ }
Expand description

Reusable scratch for a scanner’s forward search for its next signature (a magic, a checksum-valid block). Reads start at Self::FIRST_CHUNK, or at 2 * sig_len - 1 when that is larger, so the first read always tests sig_len offsets, and double up to Self::MAX_CHUNK, into one buffer kept across calls, so a search whose answer is a few bytes away reads a few bytes: a scan that resumes one byte past a refused candidate costs work proportional to the distance it actually searched, never a fixed 64 KiB per call. That is the property testing::check_scan_is_linear holds every scanner to. O(1) memory however far the next signature is.

The bytes a search read past its answer are kept for the next call (0.10.3 Task 4). A call whose from lies inside what the previous call read tests those bytes again without reading them again, and reads only past them. Without that, every call paid at least its first read afresh, so candidates a few bytes apart — an accepted header every eleven bytes, say — cost a first read EACH: 64 bytes, or 2 * sig_len - 1 for a long signature, per candidate. A scan whose from only moves forward therefore reads each byte about once in its searches, however dense its candidates are.

One ForwardSearch serves one source, whose bytes do not change while it is in use — a scanner owns one per scan. Pass a different source and the kept bytes are that other source’s. A call with a smaller file_len than the last never tests a kept byte at or past it.

Implementations§

Source§

impl ForwardSearch

Source

pub const FIRST_CHUNK: usize = 64

Size of the first read of every search, unless the signature is long enough that 2 * sig_len - 1 is larger — see Self::find.

Source

pub const MAX_CHUNK: usize

Ceiling the read size doubles up to.

Source

pub fn new() -> Self

An empty search; the buffer grows on first use and is then reused.

Source

pub fn find( &mut self, src: &mut dyn SeekRead, from: u64, file_len: u64, sig_len: usize, matches: impl FnMut(&[u8]) -> bool, ) -> Result<Option<u64>>

The first offset >= from at which matches accepts the sig_len bytes starting there, or None when none does before file_len. matches sees exactly sig_len bytes. Every offset is tested once, carrying sig_len - 1 bytes across a chunk boundary. Never reads at or past file_len, and stops at EOF if the source is shorter.

The first read is max(FIRST_CHUNK, 2 * sig_len - 1) bytes, so it tests at least sig_len offsets. A first read of only sig_len bytes tests ONE offset: for tar’s 512-byte block, a header one block on then cost 512 + 1,024 bytes, three times the distance searched.

Source

pub fn find_to_eof( &mut self, src: &mut dyn SeekRead, from: u64, file_len: u64, sig_len: usize, min_len: usize, matches: impl FnMut(&[u8]) -> bool, ) -> Result<Option<u64>>

Self::find for a record whose length is not fixed: offsets with at least sig_len bytes before file_len are offered exactly sig_len bytes, and the last offsets — those with fewer, down to min_len — are offered every byte left before file_len. A record whose longest form is sig_len bytes can then be judged whole inside the search, wherever it starts, without a second read near EOF. min_len is at least 1 and at most sig_len.

Trait Implementations§

Source§

impl Debug for ForwardSearch

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ForwardSearch

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

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> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.