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
FilePtrArgsobjects. 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
BinReadimplementation ofValue. - Creates a parser that reads a collection of values from an iterator of file offsets using the given
parserfunction.
Type Aliases§
- A type alias for
FilePtrwith 8-bit offsets. - A type alias for
FilePtrwith 16-bit offsets. - A type alias for
FilePtrwith 32-bit offsets. - A type alias for
FilePtrwith 64-bit offsets. - A type alias for
FilePtrwith 128-bit offsets. - A type alias for
FilePtrwith non-zero 8-bit offsets. - A type alias for
FilePtrwith non-zero 16-bit offsets. - A type alias for
FilePtrwith non-zero 32-bit offsets. - A type alias for
FilePtrwith non-zero 64-bit offsets. - A type alias for
FilePtrwith non-zero 128-bit offsets.