cjc_runtime/error.rs
1use std::fmt;
2
3// ---------------------------------------------------------------------------
4// Error types
5// ---------------------------------------------------------------------------
6
7/// Errors produced by the CJC runtime.
8///
9/// All runtime operations that can fail return `Result<T, RuntimeError>`.
10/// This enum covers the four main failure modes: index violations, shape
11/// incompatibilities, dimension mismatches, and general invalid operations.
12///
13/// [`RuntimeError`] implements [`std::error::Error`] and [`Display`] for
14/// integration with Rust's standard error handling.
15#[derive(Debug, Clone)]
16pub enum RuntimeError {
17 /// An index exceeded the valid range for a buffer or tensor dimension.
18 ///
19 /// `index` is the out-of-bounds index that was provided, and `length`
20 /// is the size of the dimension or buffer that was indexed into.
21 IndexOutOfBounds {
22 /// The invalid index that was provided.
23 index: usize,
24 /// The valid range is `0..length`.
25 length: usize,
26 },
27 /// The total number of elements did not match what the shape requires.
28 ///
29 /// Raised by [`Tensor::from_vec`] when `data.len() != product(shape)`,
30 /// and by [`Tensor::reshape`] when the new shape's element count differs.
31 ShapeMismatch {
32 /// The element count implied by the target shape.
33 expected: usize,
34 /// The actual element count provided.
35 got: usize,
36 },
37 /// The number of dimensions (rank) did not match what was expected.
38 ///
39 /// Raised by operations like [`Tensor::matmul`] (requires 2-D) or
40 /// [`Tensor::get`] (index length must match ndim).
41 DimensionMismatch {
42 /// The required number of dimensions.
43 expected: usize,
44 /// The actual number of dimensions provided.
45 got: usize,
46 },
47 /// A catch-all for operations that are invalid for the given arguments.
48 ///
49 /// The contained `String` provides a human-readable description of
50 /// what went wrong (e.g., "matmul requires 2-D tensors").
51 InvalidOperation(String),
52}
53
54impl fmt::Display for RuntimeError {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 RuntimeError::IndexOutOfBounds { index, length } => {
58 write!(f, "index {index} out of bounds for length {length}")
59 }
60 RuntimeError::ShapeMismatch { expected, got } => {
61 write!(f, "shape mismatch: expected {expected} elements, got {got}")
62 }
63 RuntimeError::DimensionMismatch { expected, got } => {
64 write!(
65 f,
66 "dimension mismatch: expected {expected} dimensions, got {got}"
67 )
68 }
69 RuntimeError::InvalidOperation(msg) => {
70 write!(f, "invalid operation: {msg}")
71 }
72 }
73 }
74}
75
76impl std::error::Error for RuntimeError {}
77