#[non_exhaustive]pub struct ReadOptions {
pub max_bytes: Option<usize>,
pub max_nodes: Option<usize>,
pub max_edges: Option<usize>,
pub max_nested_graphs: Option<usize>,
pub version_policy: VersionPolicy,
}Expand description
Allocation and collection policy for decoding an untrusted .nir file
with read_with.
Defaults are permissive: every field is None, so read stays
unbounded aside from the existing hard cap of 1024 NIRGraph groups
(root plus nested). That cap is a stack/alias safety bound, not a
substitute for a caller-chosen collection budget.
max_bytes is a decoded-allocation budget, not an on-disk file-size
limit and not a bound on the returned graph’s exact resident size. Charging
is monotonic and conservative: temporary allocations stay charged after
they are released. The exact rules are:
- numeric datasets: element count times decoded width;
u64datasets: both the temporaryVec<u64>and convertedVec<i64>;i64extent lists converted toVec<usize>(e.g.Input.shape): both the sourceVec<i64>and the destinationVec<usize>;- fixed strings: fixed-capacity HDF5 buffers, resulting
Stringheaders, and the worst-case copied payload; - variable-length strings: descriptor buffers, payload bytes reported by
H5Dvlen_get_buf_size, resultingStringheaders, and copied payload. Scalar VLEN strings use the containing file size as a payload bound becauseH5Dvlen_get_buf_sizecan abort on scalar VLEN; - scalar metadata: its decoded width;
- missing
v_resetandw_in: the synthesized tensor payload.
max_nodes, max_edges, and max_nested_graphs are global count
budgets for the whole file: nested subgraphs add to the same totals
rather than resetting per group. Counts are charged from HDF5 metadata
(H5Gget_info link counts, edges shape, one charge per NIRGraph
group) before the corresponding Vec / map is materialized. Hard-link
aliases are rejected before they can charge a second time.
All arithmetic is checked; overflow is treated as over budget. Node and
link names, collection bookkeeping, allocator overhead, and libhdf5’s own
caches are not charged against max_bytes.
§Untrusted inputs
Conservative starting points when the file is not from a trusted producer — tighten further for your threat model:
use nir_rs::io::ReadOptions;
let opts = ReadOptions::default()
.with_max_bytes(Some(64 * 1024 * 1024))
.with_max_nodes(Some(10_000))
.with_max_edges(Some(50_000))
.with_max_nested_graphs(Some(64));Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.max_bytes: Option<usize>Maximum total bytes charged by decoded allocations, or None for no
allocation budget.
max_nodes: Option<usize>Maximum total nodes across root and nested graphs, or None for no
node-count budget.
max_edges: Option<usize>Maximum total edges across root and nested graphs, or None for no
edge-count budget.
max_nested_graphs: Option<usize>Maximum total NIRGraph groups decoded from the file (root included),
or None to use only the hard cap of 1024 groups.
version_policy: VersionPolicyHow to treat the root /version dataset. Defaults to
VersionPolicy::Permissive, which is the Python nir.read behaviour
and keeps read byte-for-byte compatible with earlier crate
versions.
Implementations§
Source§impl ReadOptions
impl ReadOptions
Sourcepub fn with_max_bytes(self, max_bytes: Option<usize>) -> Self
pub fn with_max_bytes(self, max_bytes: Option<usize>) -> Self
Set the decoded-allocation budget in bytes; None makes it unbounded.
Sourcepub fn with_max_nodes(self, max_nodes: Option<usize>) -> Self
pub fn with_max_nodes(self, max_nodes: Option<usize>) -> Self
Set the global node-count budget; None makes it unbounded.
Sourcepub fn with_max_edges(self, max_edges: Option<usize>) -> Self
pub fn with_max_edges(self, max_edges: Option<usize>) -> Self
Set the global edge-count budget; None makes it unbounded.
Sourcepub fn with_max_nested_graphs(self, max_nested_graphs: Option<usize>) -> Self
pub fn with_max_nested_graphs(self, max_nested_graphs: Option<usize>) -> Self
Set the global nested-graph budget; None keeps only the hard cap of
1024 groups.
Sourcepub fn with_version_policy(self, version_policy: VersionPolicy) -> Self
pub fn with_version_policy(self, version_policy: VersionPolicy) -> Self
Set the /version compatibility policy.
use nir_rs::io::{ReadOptions, VersionPolicy};
// Permissive tooling (default): accept missing or arbitrary versions.
let tool = ReadOptions::default();
assert_eq!(tool.version_policy, VersionPolicy::Permissive);
// Fail-closed importer: paper 0.x fixtures and 1.x writers.
let importer = ReadOptions::default()
.with_version_policy(VersionPolicy::compatible_major([0, 1]));Trait Implementations§
Source§impl Clone for ReadOptions
impl Clone for ReadOptions
Source§fn clone(&self) -> ReadOptions
fn clone(&self) -> ReadOptions
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ReadOptions
impl Debug for ReadOptions
Source§impl Default for ReadOptions
impl Default for ReadOptions
Source§fn default() -> ReadOptions
fn default() -> ReadOptions
impl Eq for ReadOptions
Source§impl PartialEq for ReadOptions
impl PartialEq for ReadOptions
impl StructuralPartialEq for ReadOptions
Auto Trait Implementations§
impl Freeze for ReadOptions
impl RefUnwindSafe for ReadOptions
impl Send for ReadOptions
impl Sync for ReadOptions
impl Unpin for ReadOptions
impl UnsafeUnpin for ReadOptions
impl UnwindSafe for ReadOptions
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.