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}