Source code for polyxios.validate

import numpy as np

from polyxios._element_types import MAX_SAFE_CONN, MAX_SAFE_ELEMENTS, MAX_SAFE_VERTICES
from polyxios._types import PolyData
from polyxios.exceptions import ValidationError


[docs] def validate(poly: PolyData) -> PolyData: """Check structural integrity of a PolyData. Raise ValidationError on any violation. Parameters ---------- poly PolyData to validate. Returns ------- PolyData The input unchanged if valid (allows use in pipelines). Raises ------ ValidationError On dtype mismatch, shape mismatch, out-of-bounds indices, or attribute length mismatches. """ if poly.vertices.ndim != 2 or poly.vertices.shape[1] != 3: raise ValidationError( f"vertices must be shape (n, 3), got {poly.vertices.shape}" ) if poly.vertices.dtype != np.float64: raise ValidationError(f"vertices must be float64, got {poly.vertices.dtype}") n_verts = poly.vertices.shape[0] n_elems = poly.element_types.shape[0] if poly.element_types.dtype != np.uint8: raise ValidationError( f"element_types must be uint8, got {poly.element_types.dtype}" ) if poly.element_types.ndim != 1: raise ValidationError("element_types must be 1-D") if poly.offsets.ndim != 1: raise ValidationError("offsets must be 1-D") if poly.offsets.shape[0] != n_elems + 1: raise ValidationError( f"offsets length must be n_elements+1={n_elems + 1}, " f"got {poly.offsets.shape[0]}" ) if poly.offsets.dtype not in (np.int32, np.int64): raise ValidationError( f"offsets must be int32 or int64, got {poly.offsets.dtype}" ) if poly.connectivity.ndim != 1: raise ValidationError("connectivity must be 1-D") if poly.connectivity.dtype not in (np.int32, np.int64): raise ValidationError( f"connectivity must be int32 or int64, got {poly.connectivity.dtype}" ) if n_elems > 0 and poly.connectivity.size > 0: max_idx = int(poly.connectivity.max()) if max_idx >= n_verts: raise ValidationError( f"connectivity contains index {max_idx} but n_verts={n_verts}" ) min_idx = int(poly.connectivity.min()) if min_idx < 0: raise ValidationError(f"connectivity contains negative index {min_idx}") for name, arr in poly.vertex_attrs.items(): if len(arr) != n_verts: raise ValidationError( f"vertex_attrs['{name}'] length {len(arr)} != n_verts {n_verts}" ) for name, arr in poly.element_attrs.items(): if len(arr) != n_elems: raise ValidationError( f"element_attrs['{name}'] length {len(arr)} != n_elements {n_elems}" ) return poly
def validate_header( declared_n_verts: int, declared_n_elems: int, declared_conn_size: int, file_size_bytes: int, *, compressed: bool = False, ) -> None: """Validate header counts against file size before any array allocation. Parameters ---------- declared_n_verts Number of vertices declared in the file header. declared_n_elems Number of elements declared in the file header. declared_conn_size Total connectivity size declared in the file header. file_size_bytes Actual file size in bytes. compressed If True, skip file-size plausibility checks (compressed data is smaller than the raw vertex/connectivity byte estimates). Raises ------ ValidationError If declared counts exceed hard caps or are implausible given file size. """ if declared_n_verts > MAX_SAFE_VERTICES: raise ValidationError( f"declared_n_verts={declared_n_verts} exceeds MAX_SAFE_VERTICES=" f"{MAX_SAFE_VERTICES}. Possible corrupt or malicious file." ) if declared_n_elems > MAX_SAFE_ELEMENTS: raise ValidationError( f"declared_n_elems={declared_n_elems} exceeds MAX_SAFE_ELEMENTS=" f"{MAX_SAFE_ELEMENTS}. Possible corrupt or malicious file." ) if declared_conn_size > MAX_SAFE_CONN: raise ValidationError( f"declared_conn_size={declared_conn_size} exceeds MAX_SAFE_CONN=" f"{MAX_SAFE_CONN}. Possible corrupt or malicious file." ) if compressed: return # coords require 3 * 8 bytes per vertex; allow 4× slack for headers/ASCII overhead if declared_n_verts * 3 * 8 > file_size_bytes * 4: raise ValidationError( f"declared_n_verts={declared_n_verts} implies " f"{declared_n_verts * 24} bytes of vertex data but " f"file_size_bytes={file_size_bytes}. Possible corrupt file." ) # connectivity requires 4 bytes per index; allow 4× slack if declared_conn_size * 4 > file_size_bytes * 4: raise ValidationError( f"declared_conn_size={declared_conn_size} implies " f"{declared_conn_size * 4} bytes of index data but " f"file_size_bytes={file_size_bytes}. Possible corrupt file." )