fpm_rs/error.rs
1//! Error categories returned by validation, numerical, I/O, and bundle operations.
2//!
3//! Public functions return [`Result`], whose error type is [`enum@Error`]. Match variants
4//! when a caller can recover from a specific category; otherwise propagate the error.
5
6use thiserror::Error;
7
8/// Crate-wide result type using [`enum@Error`].
9pub type Result<T> = std::result::Result<T, Error>;
10
11/// Errors produced by fpm-rs public operations.
12#[derive(Debug, Error)]
13pub enum Error {
14 /// A supplied or derived array shape is empty, inconsistent, or unsupported.
15 #[error("invalid shape: {0}")]
16 InvalidShape(String),
17 /// A named scalar or option falls outside its accepted domain.
18 #[error("invalid parameter `{name}`: {reason}")]
19 InvalidParameter {
20 /// Stable parameter name.
21 name: &'static str,
22 /// Explanation of the rejected value or relationship.
23 reason: String,
24 },
25 /// A compiled image-plane model violates a model invariant.
26 #[error("model validation failed: {0}")]
27 InvalidModel(String),
28 /// Measurements or their metadata are incompatible or invalid.
29 #[error("measurement validation failed: {0}")]
30 InvalidMeasurements(String),
31 /// A flat two-dimensional buffer length does not match its `(height, width)` shape.
32 #[error("array length {actual} does not match shape {shape:?} (expected {expected})")]
33 LengthMismatch {
34 /// Number of supplied elements.
35 actual: usize,
36 /// Number of elements required by `shape`.
37 expected: usize,
38 /// Requested `(height, width)` shape.
39 shape: (usize, usize),
40 },
41 /// A flat buffer length does not match a general-dimensional shape.
42 #[error("array length {actual} does not match shape {shape:?} (expected {expected})")]
43 ArrayLengthMismatch {
44 /// Number of supplied elements.
45 actual: usize,
46 /// Number of required elements.
47 expected: usize,
48 /// Requested axis lengths.
49 shape: Vec<usize>,
50 },
51 /// Multiplying the dimensions of an array shape overflowed addressable storage.
52 #[error("array shape {shape:?} overflows addressable storage")]
53 ShapeOverflow {
54 /// Axis lengths whose product overflowed.
55 shape: Vec<usize>,
56 },
57 /// An ndarray input is not C-contiguous standard row-major storage.
58 #[error(
59 "{context} with shape {shape:?} and strides {strides:?} is not C-contiguous standard row-major layout"
60 )]
61 NonStandardLayout {
62 /// User-facing name of the offending value.
63 context: &'static str,
64 /// Logical axis lengths.
65 shape: Vec<usize>,
66 /// Element strides reported by ndarray.
67 strides: Vec<isize>,
68 },
69 /// ndarray rejected a requested shape or storage layout.
70 #[error("ndarray shape construction failed: {0}")]
71 NdarrayShape(#[from] ndarray::ShapeError),
72 /// A requested acquisition-frame index is outside `0..frames`.
73 #[error("frame index {index} is out of range for {frames} frames")]
74 FrameOutOfRange {
75 /// Requested zero-based frame index.
76 index: usize,
77 /// Available frame count.
78 frames: usize,
79 },
80 /// A numerical operation produced an invalid or unusable value.
81 #[error("numerical error: {0}")]
82 Numerical(String),
83 /// The requested operation is not implemented for the supplied input.
84 #[error("unsupported operation: {0}")]
85 Unsupported(String),
86 /// Dataset discovery, download, verification, or loading failed.
87 #[error("dataset error: {0}")]
88 Dataset(String),
89 /// A result or benchmark bundle uses an unsupported manifest version.
90 #[error("unsupported bundle format version {actual}; supported version is {supported}")]
91 UnsupportedBundleVersion {
92 /// Version found in the manifest.
93 actual: u32,
94 /// Version supported by this build.
95 supported: u32,
96 },
97 /// A bundle manifest is malformed or violates the bundle contract.
98 #[error("invalid bundle manifest: {0}")]
99 InvalidManifest(String),
100 /// A manifest-declared bundle artifact is absent.
101 #[error("bundle artifact `{role}` is missing")]
102 MissingArtifact {
103 /// Stable artifact role from the manifest.
104 role: String,
105 },
106 /// A bundle artifact's bytes do not match its declared SHA-256 digest.
107 #[error("bundle artifact `{role}` has an invalid SHA-256 digest")]
108 ArtifactHashMismatch {
109 /// Stable artifact role from the manifest.
110 role: String,
111 },
112 /// A Parquet artifact does not have the schema required for its role.
113 #[error("bundle artifact `{role}` has an invalid Parquet schema: {reason}")]
114 InvalidParquetSchema {
115 /// Stable artifact role from the manifest.
116 role: String,
117 /// Description of the schema mismatch.
118 reason: String,
119 },
120 /// Artifacts within one bundle disagree about the run identifier.
121 #[error("bundle artifact has run ID `{actual}`, expected `{expected}`")]
122 InconsistentRunId {
123 /// Run identifier required by the bundle manifest.
124 expected: String,
125 /// Run identifier found in an artifact.
126 actual: String,
127 },
128 /// A stored NPY array has a shape inconsistent with its artifact role.
129 #[error("bundle array `{role}` has invalid shape: {reason}")]
130 InvalidArrayShape {
131 /// Stable array role from the manifest.
132 role: String,
133 /// Description of the shape mismatch.
134 reason: String,
135 },
136 /// A stored NPY array has the wrong element dtype for its role.
137 #[error("bundle array `{role}` has invalid dtype `{actual}`, expected `{expected}`")]
138 InvalidArrayDtype {
139 /// Stable array role from the manifest.
140 role: String,
141 /// Dtype encoded by the array file.
142 actual: String,
143 /// Dtype required for the artifact role.
144 expected: String,
145 },
146 /// A bundle manifest names an artifact role unknown to this version.
147 #[error("unsupported bundle artifact role `{0}")]
148 UnsupportedArtifactRole(String),
149 /// A bundle artifact path is absolute or escapes the bundle directory.
150 #[error("invalid relative bundle artifact path `{0}")]
151 InvalidRelativePath(String),
152 /// A temporary bundle workspace is missing required output before publication.
153 #[error("bundle workspace is incomplete: {0}")]
154 IncompleteBundle(String),
155 /// An operation delegated to Polars failed.
156 #[cfg(feature = "tabular")]
157 #[error("Polars error: {0}")]
158 Polars(#[from] polars::error::PolarsError),
159 /// A filesystem or stream operation failed.
160 #[error("I/O error: {0}")]
161 Io(#[from] std::io::Error),
162 /// Reading or writing CSV data failed.
163 #[error("CSV error: {0}")]
164 Csv(#[from] csv::Error),
165 /// Decoding or encoding a general image failed.
166 #[error("image error: {0}")]
167 Image(#[from] image::ImageError),
168 /// Reading a TIFF stack failed.
169 #[error("TIFF error: {0}")]
170 Tiff(#[from] tiff::TiffError),
171 /// JSON serialization or deserialization failed.
172 #[error("serialization error: {0}")]
173 Serialization(#[from] serde_json::Error),
174}