linreg_core/error.rs
1//! Error types for the linear regression library.
2//!
3//! This module provides a comprehensive error type for all failure modes in
4//! linear regression operations, including matrix operations, statistical
5//! computations, and data parsing.
6
7use std::fmt;
8
9/// Error types for linear regression operations
10///
11/// # Example
12///
13/// ```
14/// # use linreg_core::Error;
15/// let err = Error::InvalidInput("negative value".to_string());
16/// assert!(err.to_string().contains("Invalid input"));
17/// ```
18#[derive(Debug, Clone, PartialEq)]
19pub enum Error {
20 /// Matrix is singular (perfect multicollinearity).
21 ///
22 /// This occurs when one or more predictor variables are linear combinations
23 /// of others, making the matrix non-invertible. Remove redundant variables
24 /// to resolve this error.
25 SingularMatrix,
26
27 /// Insufficient data points for the model.
28 ///
29 /// OLS regression requires more observations than predictor variables.
30 InsufficientData {
31 /// Minimum number of observations required
32 required: usize,
33 /// Actual number of observations available
34 available: usize,
35 },
36
37 /// Invalid input parameter.
38 ///
39 /// Indicates that an input parameter has an invalid value (e.g., negative
40 /// variance, empty data arrays, incompatible dimensions).
41 InvalidInput(String),
42
43 /// Dimension mismatch in matrix/vector operations.
44 ///
45 /// This occurs when the dimensions of matrices or vectors are incompatible
46 /// for the requested operation.
47 DimensionMismatch(String),
48
49 /// Computation failed due to numerical issues.
50 ///
51 /// This occurs when a numerical computation fails due to issues like
52 /// singularity, non-convergence, or overflow/underflow.
53 ComputationFailed(String),
54
55 /// Parse error for JSON/CSV data.
56 ///
57 /// Raised when input data cannot be parsed as JSON or CSV.
58 ParseError(String),
59
60 /// Domain check failed (for WASM with domain restriction enabled).
61 ///
62 /// By default, the WASM module allows all domains. This error is only returned
63 /// when the `LINREG_DOMAIN_RESTRICT` environment variable is set at build time
64 /// and the module is accessed from an unauthorized domain.
65 ///
66 /// To enable domain restriction:
67 /// ```bash
68 /// LINREG_DOMAIN_RESTRICT=example.com,yoursite.com wasm-pack build
69 /// ```
70 DomainCheck(String),
71}
72
73impl fmt::Display for Error {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 Error::SingularMatrix => {
77 write!(f, "Matrix is singular (perfect multicollinearity). Remove redundant variables.")
78 }
79 Error::InsufficientData { required, available } => {
80 write!(f, "Insufficient data: need at least {} observations, have {}", required, available)
81 }
82 Error::InvalidInput(msg) => {
83 write!(f, "Invalid input: {}", msg)
84 }
85 Error::DimensionMismatch(msg) => {
86 write!(f, "Dimension mismatch: {}", msg)
87 }
88 Error::ComputationFailed(msg) => {
89 write!(f, "Computation failed: {}", msg)
90 }
91 Error::ParseError(msg) => {
92 write!(f, "Parse error: {}", msg)
93 }
94 Error::DomainCheck(msg) => {
95 write!(f, "Domain check failed: {}", msg)
96 }
97 }
98 }
99}
100
101impl std::error::Error for Error {}
102
103/// Result type for linear regression operations.
104///
105/// Alias for `std::result::Result<T, Error>`.
106///
107/// # Example
108///
109/// ```
110/// # use linreg_core::{Error, Result};
111/// # fn falls_back() -> Result<f64> {
112/// # Ok(42.0)
113/// # }
114/// let result: Result<f64> = falls_back();
115/// assert_eq!(result.unwrap(), 42.0);
116/// ```
117pub type Result<T> = std::result::Result<T, Error>;
118
119// ============================================================================
120// Helper Functions for WASM Integration
121// ============================================================================
122//
123// These functions convert errors to JSON format for use in WASM bindings,
124// enabling proper error reporting to JavaScript code.
125
126/// Converts an error message to a JSON error string.
127///
128/// Creates a JSON object with a single "error" field containing the message.
129/// Used in WASM bindings to return error information to JavaScript.
130///
131/// # Examples
132///
133/// ```
134/// # use linreg_core::error_json;
135/// let json = error_json("Invalid input");
136/// assert_eq!(json, r#"{"error":"Invalid input"}"#);
137/// ```
138pub fn error_json(msg: &str) -> String {
139 serde_json::json!({ "error": msg }).to_string()
140}
141
142/// Converts an [`Error`] to a JSON error string.
143///
144/// Convenience function that converts any error variant to its display
145/// representation and wraps it in a JSON object.
146///
147/// # Examples
148///
149/// ```
150/// # use linreg_core::Error;
151/// # use linreg_core::error_to_json;
152/// let err = Error::SingularMatrix;
153/// let json = error_to_json(&err);
154/// assert!(json.contains("singular"));
155/// ```
156pub fn error_to_json(err: &Error) -> String {
157 error_json(&err.to_string())
158}