Skip to main content

symbios_shape/
error.rs

1//! Error type returned by the parser and the interpreter.
2//!
3//! Every fallible API in this crate returns `Result<T, ShapeError>`. Variants
4//! cover three broad failure classes:
5//!
6//! - **Parse failures** — `ParseError` carries a human-readable message from
7//!   the nom parser, including the offending input span.
8//! - **Numeric / structural validation** — `InvalidNumericValue`,
9//!   `EmptySplit`, `InvalidFloatingSize`, `SplitOverflow`, `NoFloatingSlots`,
10//!   `UnknownCompSelector`, `OffsetTooLarge`, `InvalidRoofAngle`,
11//!   `InvalidAlignTarget` are raised when a parsed grammar would produce
12//!   geometry that isn't well-defined.
13//! - **DoS safety caps** — `CapacityOverflow` and `DepthLimitExceeded` are
14//!   returned when a grammar exceeds the engine's bounded queue, terminal,
15//!   op-count, identifier, or recursion limits rather than allowing
16//!   unbounded resource use.
17
18use thiserror::Error;
19
20/// All errors produced by the parser and the interpreter.
21///
22/// See the module-level documentation for a categorised overview.
23#[derive(Error, Debug, PartialEq)]
24pub enum ShapeError {
25    #[error("Parse error: {0}")]
26    ParseError(String),
27    #[error("Non-finite numeric value detected (NaN/Inf)")]
28    InvalidNumericValue,
29    #[error("Scope capacity overflow")]
30    CapacityOverflow,
31    #[error("Split sizes are empty")]
32    EmptySplit,
33    #[error("Split floating size must be positive: {0}")]
34    InvalidFloatingSize(f64),
35    #[error("Split absolute sizes exceed scope dimension {0}")]
36    SplitOverflow(f64),
37    #[error("No floating slots to absorb remainder in split")]
38    NoFloatingSlots,
39    #[error("Comp selector '{0}' not recognised")]
40    UnknownCompSelector(String),
41    #[error("Derivation depth limit {0} exceeded")]
42    DepthLimitExceeded(usize),
43    #[error("Internal error: {0}")]
44    Internal(String),
45    #[error("Offset inset distance exceeds scope dimension")]
46    OffsetTooLarge,
47    #[error("Roof angle must be in (0°, 90°): got {0}")]
48    InvalidRoofAngle(f64),
49    #[error("Align target vector must be non-zero")]
50    InvalidAlignTarget,
51    #[error("Unknown identifier '{0}' (not a parameter, attribute, or constant)")]
52    UnknownIdentifier(String),
53    #[error("Rule call arity mismatch: {0}")]
54    ArityMismatch(String),
55    #[error("Expression evaluation failed: {0}")]
56    ExprEval(String),
57}