Skip to main content

eggsearch/core/
error.rs

1//! Error types for eggsearch-core.
2
3use thiserror::Error;
4
5/// Errors produced by eggsearch-core operations.
6#[derive(Debug, Error)]
7pub enum CoreError {
8    /// A URL failed to parse or failed URL-based validation.
9    #[error("invalid URL: {0}")]
10    InvalidUrl(String),
11
12    /// A query failed validation (empty, oversized, or invalid `max_results`).
13    #[error("invalid query: {0}")]
14    InvalidQuery(String),
15
16    /// The configuration file or values are invalid.
17    #[error("config error: {0}")]
18    Config(String),
19
20    /// A specific provider failed during a search.
21    #[error("provider '{provider}' failed: {message}")]
22    Provider {
23        /// Stable provider id (e.g. `"duckduckgo"`).
24        provider: String,
25        /// Human-readable detail.
26        message: String,
27    },
28
29    /// An I/O error.
30    #[error("io error: {0}")]
31    Io(#[from] std::io::Error),
32
33    /// A JSON serialization error.
34    #[error("serialization error: {0}")]
35    Serde(#[from] serde_json::Error),
36
37    /// A TOML deserialization error.
38    #[error("toml parse error: {0}")]
39    TomlDe(#[from] toml::de::Error),
40
41    /// A TOML serialization error.
42    #[error("toml serialization error: {0}")]
43    TomlSer(String),
44
45    /// A catch-all error for anything not covered above.
46    #[error("{0}")]
47    Other(String),
48}
49
50/// Convenience alias for `Result<T, CoreError>`.
51pub type CoreResult<T> = Result<T, CoreError>;
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn invalid_url_message() {
59        let err = CoreError::InvalidUrl("not a url".to_string());
60        assert!(err.to_string().contains("invalid URL"));
61        assert!(err.to_string().contains("not a url"));
62    }
63
64    #[test]
65    fn invalid_query_message() {
66        let err = CoreError::InvalidQuery("query too long".to_string());
67        assert!(err.to_string().contains("invalid query"));
68        assert!(err.to_string().contains("query too long"));
69    }
70
71    #[test]
72    fn config_error_message() {
73        let err = CoreError::Config("missing field".to_string());
74        assert!(err.to_string().contains("config error"));
75        assert!(err.to_string().contains("missing field"));
76    }
77
78    #[test]
79    fn provider_error_message() {
80        let err = CoreError::Provider {
81            provider: "duckduckgo".to_string(),
82            message: "timeout".to_string(),
83        };
84        let s = err.to_string();
85        assert!(s.contains("provider 'duckduckgo'"));
86        assert!(s.contains("timeout"));
87    }
88
89    #[test]
90    fn io_error_from_std() {
91        use std::io;
92        let err = CoreError::Io(io::Error::new(io::ErrorKind::NotFound, "file not found"));
93        assert!(err.to_string().contains("io error"));
94    }
95
96    #[test]
97    fn serde_error_from_json() {
98        let json_err = serde_json::from_str::<()>("invalid json").unwrap_err();
99        let err = CoreError::Serde(json_err);
100        assert!(err.to_string().contains("serialization error"));
101    }
102
103    #[test]
104    fn toml_de_error_from_invalid_toml() {
105        let toml_err = toml::from_str::<()>("invalid = toml").unwrap_err();
106        let err = CoreError::TomlDe(toml_err);
107        assert!(err.to_string().contains("toml parse error"));
108    }
109
110    #[test]
111    fn toml_ser_error_message() {
112        let err = CoreError::TomlSer("serialization failed".to_string());
113        assert!(err.to_string().contains("toml serialization error"));
114    }
115
116    #[test]
117    fn other_error_message() {
118        let err = CoreError::Other("something went wrong".to_string());
119        assert!(err.to_string().contains("something went wrong"));
120    }
121}