Skip to main content

path_traits/
error.rs

1//! Error types for path operations.
2//!
3//! This module defines [`PathError<S>`], the canonical error enum for all path-related
4//! fallible operations. Every trait in the hierarchy exposes
5//! `type Error: From<PathError<Self::Scalar>>` so implementers may use their own error type.
6
7use crate::Scalar;
8use core::fmt;
9use core::ops::RangeInclusive;
10
11/// Errors that can occur during path sampling or geometric queries.
12///
13/// The scalar parameter `S` allows the error to carry the exact parameter value
14/// and domain that caused the failure, making diagnostics precise.
15#[non_exhaustive]
16#[derive(Debug, Clone, PartialEq)]
17pub enum PathError<S> {
18    /// Arc-length / parameter outside the valid domain.
19    OutOfDomain {
20        /// The parameter value that was out of domain.
21        param: S,
22        /// The valid domain `[start, end]`.
23        domain: RangeInclusive<S>,
24    },
25    /// The path is not differentiable at `param` (e.g. a cusp or kink).
26    NotDifferentiable {
27        /// The parameter where differentiability fails.
28        param: S,
29        /// Human-readable reason.
30        reason: &'static str,
31    },
32    /// The path is degenerate (e.g. zero-length segment, collinear control points).
33    Degenerate {
34        /// Human-readable reason.
35        reason: &'static str,
36    },
37    /// A custom error with a static description for implementer-specific failures.
38    Custom(&'static str),
39}
40
41impl<S: Scalar> PathError<S> {
42    /// Create an `OutOfDomain` error with the offending parameter and valid domain.
43    pub fn out_of_domain(param: S, domain: RangeInclusive<S>) -> Self {
44        PathError::OutOfDomain { param, domain }
45    }
46
47    /// Create a `NotDifferentiable` error with the parameter and reason.
48    pub fn not_differentiable(param: S, reason: &'static str) -> Self {
49        PathError::NotDifferentiable { param, reason }
50    }
51
52    /// Create a `Degenerate` error with a reason.
53    pub fn degenerate(reason: &'static str) -> Self {
54        PathError::Degenerate { reason }
55    }
56}
57
58impl<S: fmt::Debug> fmt::Display for PathError<S> {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            PathError::OutOfDomain { param, domain } => {
62                write!(
63                    f,
64                    "parameter {:?} is outside the valid domain {:?}",
65                    param, domain
66                )
67            }
68            PathError::NotDifferentiable { param, reason } => {
69                write!(f, "path is not differentiable at {:?}: {}", param, reason)
70            }
71            PathError::Degenerate { reason } => {
72                write!(f, "path is degenerate: {}", reason)
73            }
74            PathError::Custom(msg) => write!(f, "{}", msg),
75        }
76    }
77}
78
79impl<S: fmt::Debug> core::error::Error for PathError<S> {}