Expand description
Type definitions and helpers for handling indirection within a file.
§Best practices
Indirections that are not collections (e.g. a single offset to a global file
header) can use FilePtr
to immediately read the offset and then parse the
pointed-to value. However, using FilePtr
inside a collection is
inefficient because it seeks to and reads each pointed-to value immediately
after the offset is read. In these cases, it is faster to read the offset
table into a collection (e.g. Vec<u32>
) and then either pass it to
parse_from_iter
or write a function that is called to lazily load values
as needed.
§Using parse_from_iter
to read an offset table
§With relative offsets
In this example, the offsets in the offset table start counting from the beginning of the values section, and are in a random order.
Since the values section exists immediately after the offset table, no seeking is required before reading the values.
Since the offsets are in a random order, the position of the stream must be
returned to a known state using restore_position
on the values field.
Then, seek_before
is used on the next field to skip past the values data
and continue reading the rest of the object.
use binrw::file_ptr::parse_from_iter;
#[derive(BinRead)]
#[br(big)]
struct Object {
count: u16,
#[br(args { count: count.into() })]
offsets: Vec<u16>,
#[br(parse_with = parse_from_iter(offsets.iter().copied()), restore_position)]
values: Vec<u8>,
#[br(seek_before(SeekFrom::Current(count.into())))]
extra: u16,
}
§With absolute offsets
In this example, the offsets in the offset table start from the beginning of the file, and are in sequential order.
Since the offsets start from the beginning of the file, it is necessary to
use seek_before
to reposition the stream to the beginning of the file
before reading the values.
Since the offsets are in order, no seeking is required after the values are read, since the stream will already be pointed at the end of the values section.
use binrw::file_ptr::parse_from_iter;
#[derive(BinRead)]
#[br(big)]
struct Object {
count: u16,
#[br(args { count: count.into() })]
offsets: Vec<u16>,
#[br(
parse_with = parse_from_iter(offsets.iter().copied()),
seek_before(SeekFrom::Start(0))
)]
values: Vec<u8>,
extra: u16,
}
§Using a function to lazily load values
In this example, only the offset table is parsed. Values pointed to by the
offset table are loaded on demand by calling Object::get
as needed at
runtime.
#[derive(BinRead)]
#[br(big)]
struct Item(u8);
#[derive(BinRead)]
#[br(big, stream = s)]
struct Object {
count: u16,
#[br(args { count: count.into() })]
offsets: Vec<u16>,
#[br(try_calc = s.stream_position())]
data_offset: u64,
}
impl Object {
pub fn get<R: Read + Seek>(&self, source: &mut R, index: usize) -> Option<BinResult<Item>> {
self.offsets.get(index).map(|offset| {
let offset = self.data_offset + u64::from(*offset);
source.seek(SeekFrom::Start(offset))?;
Item::read(source)
})
}
}
Structs§
- A wrapper type which represents a layer of indirection within a file.
- Named arguments for the
BinRead::read_options()
implementation ofFilePtr
. - A builder for
FilePtrArgs
objects. Compatible withbinrw::args!
.
Traits§
- A trait to convert from an integer into
SeekFrom::Current
.
Functions§
- Creates a parser that reads a collection of values from an iterator of file offsets using the
BinRead
implementation ofValue
. - Creates a parser that reads a collection of values from an iterator of file offsets using the given
parser
function.
Type Aliases§
- A type alias for
FilePtr
with 8-bit offsets. - A type alias for
FilePtr
with 16-bit offsets. - A type alias for
FilePtr
with 32-bit offsets. - A type alias for
FilePtr
with 64-bit offsets. - A type alias for
FilePtr
with 128-bit offsets. - A type alias for
FilePtr
with non-zero 8-bit offsets. - A type alias for
FilePtr
with non-zero 16-bit offsets. - A type alias for
FilePtr
with non-zero 32-bit offsets. - A type alias for
FilePtr
with non-zero 64-bit offsets. - A type alias for
FilePtr
with non-zero 128-bit offsets.