open_sesame/util/
error.rs

1//! Error types for Open Sesame
2//!
3//! Uses thiserror for typed errors instead of anyhow for better error handling.
4
5use std::path::PathBuf;
6
7/// Main error type for Open Sesame
8#[derive(Debug, thiserror::Error)]
9pub enum Error {
10    /// Failed to establish connection to Wayland compositor
11    #[error("Failed to connect to Wayland compositor")]
12    WaylandConnection(#[source] Box<dyn std::error::Error + Send + Sync>),
13
14    /// Required Wayland protocol extension is not available
15    #[error("Required Wayland protocol not available: {protocol}")]
16    MissingProtocol {
17        /// Name of the missing protocol
18        protocol: &'static str,
19    },
20
21    /// Window with specified identifier was not found
22    #[error("Window not found: {identifier}")]
23    WindowNotFound {
24        /// The identifier that was searched for
25        identifier: String,
26    },
27
28    /// Failed to activate the target window
29    #[error("Failed to activate window: {0}")]
30    ActivationFailed(String),
31
32    /// Failed to parse TOML configuration file
33    #[error("Failed to parse configuration: {0}")]
34    ConfigParse(#[from] toml::de::Error),
35
36    /// Failed to read configuration file from disk
37    #[error("Failed to read configuration file: {path}")]
38    ConfigRead {
39        /// Path to the configuration file
40        path: PathBuf,
41        /// The underlying I/O error
42        #[source]
43        source: std::io::Error,
44    },
45
46    /// Configuration validation failed
47    #[error("Invalid configuration: {message}")]
48    ConfigValidation {
49        /// Description of the validation error
50        message: String,
51    },
52
53    /// Invalid color format in configuration
54    #[error("Invalid color format: {value}")]
55    InvalidColor {
56        /// The invalid color value
57        value: String,
58    },
59
60    /// Failed to create rendering surface
61    #[error("Failed to create rendering surface")]
62    SurfaceCreation,
63
64    /// Surface dimensions are invalid (zero or too large)
65    #[error("Invalid surface dimensions: {width}x{height}")]
66    InvalidDimensions {
67        /// The invalid width
68        width: u32,
69        /// The invalid height
70        height: u32,
71    },
72
73    /// No suitable font could be found on the system
74    #[error("Font not available")]
75    FontNotFound,
76
77    /// Generic I/O error
78    #[error("I/O error: {0}")]
79    Io(#[from] std::io::Error),
80
81    /// Failed to launch an external application
82    #[error("Failed to launch application: {command}")]
83    LaunchFailed {
84        /// The command that failed to execute
85        command: String,
86        /// The underlying I/O error
87        #[source]
88        source: std::io::Error,
89    },
90
91    /// Generic error for wrapping external error types
92    #[error("{0}")]
93    Other(String),
94}
95
96/// Result type alias using our Error
97pub type Result<T> = std::result::Result<T, Error>;
98
99impl Error {
100    /// Creates an error from any error type.
101    pub fn other<E: std::fmt::Display>(error: E) -> Self {
102        Self::Other(error.to_string())
103    }
104
105    /// Returns whether this error is recoverable.
106    pub fn is_recoverable(&self) -> bool {
107        matches!(
108            self,
109            Error::WindowNotFound { .. }
110                | Error::ConfigValidation { .. }
111                | Error::InvalidColor { .. }
112        )
113    }
114}
115
116// Conversion from anyhow for compatibility during migration
117impl From<anyhow::Error> for Error {
118    fn from(err: anyhow::Error) -> Self {
119        Error::Other(err.to_string())
120    }
121}