Skip to main content

orrery_parser/error/
source_error.rs

1//! Error type for [`SourceProvider`](crate::source_provider::SourceProvider) operations.
2//!
3//! [`SourceError`] is a lightweight, `Clone`-able error representing failures
4//! in file resolution or reading. It is intentionally decoupled from the
5//! diagnostic system so that the resolver can convert it into a
6//! [`Diagnostic`](super::Diagnostic) with proper span and error-code context.
7
8use std::{
9    fmt,
10    path::{Path, PathBuf},
11};
12
13/// Error returned by [`SourceProvider`](crate::source_provider::SourceProvider) operations.
14///
15/// `SourceError` is intentionally lightweight and `Clone`-able so it can be
16/// stored, duplicated, and later converted into a [`Diagnostic`](super::Diagnostic)
17/// by the resolver with proper span and error-code context.
18///
19/// # Example
20///
21/// ```
22/// # use orrery_parser::error::SourceError;
23/// let err = SourceError::new("shared/styles.orr", "file not found");
24/// assert_eq!(err.path().to_str().unwrap(), "shared/styles.orr");
25/// assert_eq!(err.message(), "file not found");
26/// ```
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct SourceError {
29    /// The path that caused the error.
30    path: PathBuf,
31    /// Human-readable description of what went wrong.
32    message: String,
33}
34
35impl SourceError {
36    /// Creates a new source error.
37    ///
38    /// # Arguments
39    ///
40    /// * `path` - The path that caused the error.
41    /// * `message` - Human-readable description of what went wrong.
42    pub fn new(path: impl Into<PathBuf>, message: impl Into<String>) -> Self {
43        Self {
44            path: path.into(),
45            message: message.into(),
46        }
47    }
48
49    /// Returns the path associated with this error.
50    pub fn path(&self) -> &Path {
51        &self.path
52    }
53
54    /// Returns the human-readable error message.
55    pub fn message(&self) -> &str {
56        &self.message
57    }
58}
59
60impl fmt::Display for SourceError {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        write!(f, "{}: {}", self.path.display(), self.message)
63    }
64}
65
66impl std::error::Error for SourceError {}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn source_error_accessors() {
74        let err = SourceError::new("test.orr", "something went wrong");
75        assert_eq!(err.path(), Path::new("test.orr"));
76        assert_eq!(err.message(), "something went wrong");
77    }
78
79    #[test]
80    fn source_error_display() {
81        let err = SourceError::new("shared/styles.orr", "file not found");
82        assert_eq!(err.to_string(), "shared/styles.orr: file not found");
83    }
84}