netpulse/
errors.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//! Error types for the netpulse crate.
//!
//! This module provides specialized error types for different components of netpulse:
//! - [`StoreError`] - Errors related to store operations (loading, saving, versioning)
//! - [`CheckError`] - Errors that occur during network checks (HTTP, ICMP)
//! - [`DaemonError`] - Errors specific to daemon operations
//! - [`AnalysisError`] - Errors that occur during analysis and report generation
//!
//! All error types implement the standard Error trait and provide detailed error information.
//!
//! # Examples
//!
//! ```rust,no_run
//! use netpulse::store::Store;
//! use netpulse::errors::StoreError;
//!
//! fn load_store() -> Result<Store, StoreError> {
//!     match Store::load() {
//!         Ok(store) => Ok(store),
//!         Err(StoreError::DoesNotExist) => Store::create(),
//!         Err(e) => Err(e),
//!     }
//! }
//! ```

use flagset::FlagSet;
use thiserror::Error;

use crate::records::CheckFlag;

/// Errors that can occur during store operations.
///
/// These errors handle various failure modes when interacting with the store:
/// - File system operations
/// - Data serialization/deserialization
/// - Version compatibility
#[derive(Error, Debug)]
pub enum StoreError {
    /// The store file does not exist.
    ///
    /// This typically occurs on first run or if the store file was deleted.
    #[error("The store does not exist")]
    DoesNotExist,
    /// An I/O error occurred during store operations.
    ///
    /// This can happen during file reading, writing, or filesystem operations.
    #[error("IO Error: {source}")]
    Io {
        /// Underlying error
        #[from]
        source: std::io::Error,
    },
    /// Failed to load store data from file.
    ///
    /// This typically indicates corruption or an incompatible / outdated store format.
    #[error("Could not load the store from file: {source}")]
    Load {
        /// Underlying error
        #[from]
        source: bincode::Error,
    },
    /// Failed to convert data to UTF-8.
    ///
    /// This can occur when reading store metadata like file hashes.
    #[error("Could not convert data to Utf8")]
    Str {
        /// Underlying error
        #[from]
        source: std::str::Utf8Error,
    },
    /// A subprocess (like sha256sum) exited with non-zero status.
    #[error("A subprocess ended non successfully")]
    ProcessEndedWithoutSuccess,
    /// Attempted to load a store with an unsupported version number.
    ///
    /// This occurs when the store file version is newer or older than what this version
    /// of netpulse supports.
    #[error("Tried to load a store with an unsupported version")]
    UnsupportedVersion,
    /// A [Check](crate::records::Check) has flags that are exclusive to each other.
    ///
    /// This variant contains a [FlagSet] with only the conflicting [CheckFlags](CheckFlag) set.
    #[error("Check has ambiguous flags: {0:?}")]
    AmbiguousFlags(FlagSet<CheckFlag>),
    /// A [Check](crate::records::Check) that does not have the required flags to be valid.
    ///
    /// This variant contains a [FlagSet] with only the flags [CheckFlags](CheckFlag) set that
    /// would make it a valid state. Exactly one of these flags must be set.
    ///
    /// # Example
    ///
    /// Every check should have either [CheckFlag::IPv4] or [CheckFlag::IPv6] set. If none of these
    /// are set, this error will be returned with a [FlagSet] that has both flags set, to indicate
    /// that one of these should be set.
    #[error("Check is missing at least one of these flags: {0:?}")]
    MissingFlag(FlagSet<CheckFlag>),
}

/// Errors that can occur during network checks.
///
/// These errors handle failures during the actual network connectivity tests,
/// whether HTTP, ICMP, or other protocols.
#[derive(Error, Debug)]
pub enum CheckError {
    /// An I/O error occurred during the check.
    ///
    /// This typically indicates network-level failures.
    #[error("IO Error {source}")]
    Io {
        /// Underlying error
        #[from]
        source: std::io::Error,
    },
    /// An error occurred during ICMP ping.
    ///
    /// This variant is only available when the `ping` feature is enabled.
    #[cfg(feature = "ping")]
    #[error("Ping Error: {source}")]
    Ping {
        /// Underlying error
        #[from]
        source: ping::Error,
    },
    /// An error occurred during HTTP check.
    ///
    /// This variant is only available when the `http` feature is enabled.
    #[cfg(feature = "http")]
    #[error("Http Error: {source}")]
    Http {
        /// Underlying error
        #[from]
        source: curl::Error,
    },
}

/// Errors that can occur during daemon operations.
///
/// These errors handle failures in the daemon process, including store
/// operations and process management.
#[derive(Error, Debug)]
pub enum RunError {
    /// An error occurred while operating on the store.
    #[error("Something went wrong with the store: {source}")]
    StoreError {
        /// Underlying error
        #[from]
        source: StoreError,
    },
    /// An I/O error occurred during daemon operations.
    #[error("IO Error: {source}")]
    Io {
        /// Underlying error
        #[from]
        source: std::io::Error,
    },
    /// Failed to format analysis output.
    #[error("Text Formatting error: {source}")]
    Fmt {
        /// Underlying error
        #[from]
        source: std::fmt::Error,
    },
}

/// Errors that can occur during analysis and report generation.
///
/// These errors handle failures when analyzing check results and
/// generating human-readable reports.
#[derive(Error, Debug)]
pub enum AnalysisError {
    /// An error occurred while accessing the store.
    #[error("Something went wrong with the store: {source}")]
    StoreError {
        /// Underlying error
        #[from]
        source: StoreError,
    },
    /// Failed to format analysis output.
    #[error("Text Formatting error: {source}")]
    Fmt {
        /// Underlying error
        #[from]
        source: std::fmt::Error,
    },
    /// An I/O error occurred during analysis operations.
    #[error("IO Error: {source}")]
    Io {
        /// Underlying error
        #[from]
        source: std::io::Error,
    },
}