netpulse/
errors.rs

1//! Error types for the netpulse crate.
2//!
3//! This module provides specialized error types for different components of netpulse:
4//! - [`StoreError`] - Errors related to store operations (loading, saving, versioning)
5//! - [`CheckError`] - Errors that occur during network checks (HTTP, ICMP)
6//! - [`RunError`] - Errors specific to executable operations
7//! - [`AnalysisError`] - Errors that occur during analysis and report generation
8//!
9//! All error types implement the standard Error trait and provide detailed error information.
10//!
11//! # Examples
12//!
13//! ```rust,no_run
14//! use netpulse::store::Store;
15//! use netpulse::errors::StoreError;
16//!
17//! fn load_store() -> Result<Store, StoreError> {
18//!     match Store::load(false) {
19//!         Ok(store) => Ok(store),
20//!         Err(StoreError::DoesNotExist) => Store::create(),
21//!         Err(e) => Err(e),
22//!     }
23//! }
24//! ```
25
26use flagset::FlagSet;
27use thiserror::Error;
28
29use crate::records::CheckFlag;
30
31/// Errors that can occur during store operations.
32///
33/// These errors handle various failure modes when interacting with the store:
34/// - File system operations
35/// - Data serialization/deserialization
36/// - Version compatibility
37#[derive(Error, Debug)]
38pub enum StoreError {
39    /// The store file does not exist.
40    ///
41    /// This typically occurs on first run or if the store file was deleted.
42    #[error("The store does not exist")]
43    DoesNotExist,
44    /// An I/O error occurred during store operations.
45    ///
46    /// This can happen during file reading, writing, or filesystem operations.
47    #[error("IO Error: {source}")]
48    Io {
49        /// Underlying error
50        #[from]
51        source: std::io::Error,
52    },
53    /// Failed to load store data from file.
54    ///
55    /// This typically indicates corruption or an incompatible / outdated store format.
56    #[error("Could not deserialize the store from the loaded data: {source}")]
57    Load {
58        /// Underlying error
59        #[from]
60        source: bincode::Error,
61    },
62    /// Failed to convert data to UTF-8.
63    ///
64    /// This can occur when reading store metadata like file hashes.
65    #[error("Could not convert data to Utf8")]
66    Str {
67        /// Underlying error
68        #[from]
69        source: std::str::Utf8Error,
70    },
71    /// A subprocess (like sha256sum) exited with non-zero status.
72    #[error("A subprocess ended non successfully")]
73    ProcessEndedWithoutSuccess,
74    /// Attempted to load a store with an unsupported version number.
75    ///
76    /// This occurs when the store file version is newer or older than what this version
77    /// of netpulse supports.
78    #[error("Tried to load a store with an unsupported version")]
79    UnsupportedVersion,
80    /// A [Check](crate::records::Check) has flags that are exclusive to each other.
81    ///
82    /// This variant contains a [FlagSet] with only the conflicting [CheckFlags](CheckFlag) set.
83    #[error("Check has ambiguous flags: {0:?}")]
84    AmbiguousFlags(FlagSet<CheckFlag>),
85    /// A [Check](crate::records::Check) that does not have the required flags to be valid.
86    ///
87    /// This variant contains a [FlagSet] with only the flags [CheckFlags](CheckFlag) set that
88    /// would make it a valid state. Exactly one of these flags must be set.
89    #[error("Check is missing at least one of these flags: {0:?}")]
90    MissingFlag(FlagSet<CheckFlag>),
91    /// Occurs when trying to convert an arbitrary [u8] to a [Version](crate::store::Version) that
92    /// is not defined. Only known [Versions][crate::store::Version] are valid.
93    #[error("Tried to load a store version that does not exist: {0}")]
94    BadStoreVersion(u8),
95    /// A store can be loaded as readonly if it's corrupted or there is a version mismatch
96    #[error("Tried to save a readonly store")]
97    IsReadonly,
98}
99
100/// Errors that can occur during network checks.
101///
102/// These errors handle failures during the actual network connectivity tests,
103/// whether HTTP, ICMP, or other protocols.
104#[derive(Error, Debug)]
105pub enum CheckError {
106    /// An I/O error occurred during the check.
107    ///
108    /// This typically indicates network-level failures.
109    #[error("IO Error {source}")]
110    Io {
111        /// Underlying error
112        #[from]
113        source: std::io::Error,
114    },
115    /// An error occurred during ICMP ping.
116    ///
117    /// This variant is only available when the `ping` feature is enabled.
118    #[cfg(feature = "ping")]
119    #[error("Ping Error: {source}")]
120    Ping {
121        /// Underlying error
122        #[from]
123        source: ping::Error,
124    },
125    /// An error occurred during HTTP check.
126    ///
127    /// This variant is only available when the `http` feature is enabled.
128    #[cfg(feature = "http")]
129    #[error("Http Error: {source}")]
130    Http {
131        /// Underlying error
132        #[from]
133        source: curl::Error,
134    },
135}
136
137/// Errors that can occur during daemon operations.
138///
139/// These errors handle failures in the daemon process, including store
140/// operations and process management.
141#[derive(Error, Debug)]
142pub enum RunError {
143    /// An error occurred while operating on the store.
144    #[error("Something went wrong with the store: {source}")]
145    StoreError {
146        /// Underlying error
147        #[from]
148        source: StoreError,
149    },
150    /// An I/O error occurred during daemon operations.
151    #[error("IO Error: {source}")]
152    Io {
153        /// Underlying error
154        #[from]
155        source: std::io::Error,
156    },
157    /// Failed to format analysis output.
158    #[error("Text Formatting error: {source}")]
159    Fmt {
160        /// Underlying error
161        #[from]
162        source: std::fmt::Error,
163    },
164}
165
166/// Errors that can occur during analysis and report generation.
167///
168/// These errors handle failures when analyzing check results and
169/// generating human-readable reports.
170#[derive(Error, Debug)]
171pub enum AnalysisError {
172    /// An error occurred while accessing the store.
173    #[error("Something went wrong with the store: {source}")]
174    StoreError {
175        /// Underlying error
176        #[from]
177        source: StoreError,
178    },
179    /// Failed to format analysis output.
180    #[error("Text Formatting error: {source}")]
181    Fmt {
182        /// Underlying error
183        #[from]
184        source: std::fmt::Error,
185    },
186    /// An I/O error occurred during analysis operations.
187    #[error("IO Error: {source}")]
188    Io {
189        /// Underlying error
190        #[from]
191        source: std::io::Error,
192    },
193}