Skip to main content

mago_reporting/
error.rs

1//! Error types for the reporting crate.
2//!
3//! This module defines the error types that can occur during issue reporting,
4//! including database errors, JSON serialization errors, file I/O errors,
5//! and invalid configuration errors.
6
7use codespan_reporting::files::Error as FilesError;
8#[cfg(feature = "serde")]
9use serde_json::Error as JsonError;
10use std::io::Error as IoError;
11
12use mago_database::error::DatabaseError;
13
14/// Errors that can occur during issue reporting.
15#[derive(Debug)]
16pub enum ReportingError {
17    /// An error occurred while accessing the database.
18    DatabaseError(DatabaseError),
19    /// An error occurred while serializing or deserializing JSON.
20    #[cfg(feature = "serde")]
21    JsonError(JsonError),
22    /// An error occurred while accessing source files.
23    FilesError(FilesError),
24    /// An I/O error occurred.
25    IoError(IoError),
26    /// An invalid reporting target was specified.
27    InvalidTarget(String),
28    /// An invalid reporting format was specified.
29    InvalidFormat(String),
30}
31
32impl ReportingError {
33    #[must_use]
34    pub fn is_broken_pipe(&self) -> bool {
35        let err = match self {
36            Self::IoError(err) => err,
37            Self::FilesError(FilesError::Io(err)) => err,
38            _ => return false,
39        };
40
41        err.raw_os_error() == Some(32) || err.kind() == std::io::ErrorKind::BrokenPipe
42    }
43}
44
45impl std::fmt::Display for ReportingError {
46    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47        match self {
48            Self::DatabaseError(error) => write!(f, "{error}"),
49            #[cfg(feature = "serde")]
50            Self::JsonError(error) => write!(f, "Json error: {error}"),
51            Self::FilesError(error) => write!(f, "Files error: {error}"),
52            Self::IoError(error) => write!(f, "IO error: {error}"),
53            Self::InvalidTarget(target) => write!(f, "Invalid target: {target}"),
54            Self::InvalidFormat(format) => write!(f, "Invalid format: {format}"),
55        }
56    }
57}
58
59impl std::error::Error for ReportingError {
60    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
61        match self {
62            Self::DatabaseError(error) => Some(error),
63            #[cfg(feature = "serde")]
64            Self::JsonError(error) => Some(error),
65            Self::FilesError(error) => Some(error),
66            Self::IoError(error) => Some(error),
67            Self::InvalidTarget(_) => None,
68            Self::InvalidFormat(_) => None,
69        }
70    }
71}
72
73impl From<DatabaseError> for ReportingError {
74    fn from(error: DatabaseError) -> Self {
75        Self::DatabaseError(error)
76    }
77}
78
79#[cfg(feature = "serde")]
80impl From<JsonError> for ReportingError {
81    fn from(error: JsonError) -> Self {
82        Self::JsonError(error)
83    }
84}
85
86impl From<FilesError> for ReportingError {
87    fn from(error: FilesError) -> Self {
88        Self::FilesError(error)
89    }
90}
91
92impl From<IoError> for ReportingError {
93    fn from(error: IoError) -> Self {
94        Self::IoError(error)
95    }
96}