bgpkit_commons/
errors.rs

1//! Error types for bgpkit-commons
2//!
3//! This module defines structured error types using `thiserror` for better error handling
4//! and debugging. Each error type provides specific context about what failed and why.
5
6use thiserror::Error;
7
8/// Main error type for bgpkit-commons operations
9#[derive(Error, Debug)]
10pub enum BgpkitCommonsError {
11    /// Error when trying to access data from a module that hasn't been loaded yet
12    #[error("Module '{module}' data not loaded. Call {load_method}() first")]
13    ModuleNotLoaded {
14        module: &'static str,
15        load_method: &'static str,
16    },
17
18    /// Error when trying to access specific functionality that requires additional configuration
19    #[error(
20        "Module '{module}' not loaded with required configuration: {requirement}. Call {load_method}"
21    )]
22    ModuleNotConfigured {
23        module: &'static str,
24        requirement: &'static str,
25        load_method: &'static str,
26    },
27
28    /// Error when external data sources are unavailable or return invalid data
29    #[error("Failed to load data from {data_source}: {details}")]
30    DataSourceError {
31        data_source: String,
32        details: String,
33    },
34
35    /// Error when input data format is invalid
36    #[error("Invalid {data_type} format '{input}': {reason}")]
37    InvalidFormat {
38        data_type: &'static str,
39        input: String,
40        reason: String,
41    },
42
43    /// Error when required features are not enabled
44    #[error(
45        "Feature '{feature}' is required but not enabled. Add '{feature}' to your Cargo.toml features"
46    )]
47    FeatureNotEnabled { feature: &'static str },
48
49    /// Network or I/O related errors
50    #[error("Network/IO error: {0}")]
51    NetworkError(#[from] std::io::Error),
52
53    /// JSON parsing errors
54    #[cfg(feature = "serde_json")]
55    #[error("JSON parsing error: {0}")]
56    JsonError(#[from] serde_json::Error),
57
58    /// Date/time parsing errors
59    #[cfg(feature = "chrono")]
60    #[error("Date/time parsing error: {0}")]
61    ChronoError(#[from] chrono::ParseError),
62
63    /// IP network parsing errors
64    #[cfg(feature = "ipnet")]
65    #[error("IP network parsing error: {0}")]
66    IpNetError(#[from] ipnet::AddrParseError),
67
68    /// OneIO errors (file/network operations)
69    #[cfg(feature = "oneio")]
70    #[error("OneIO error: {0}")]
71    OneIoError(#[from] oneio::OneIoError),
72
73    /// Parsing errors (int, float, etc.)
74    #[error("Parsing error: {0}")]
75    ParseIntError(#[from] std::num::ParseIntError),
76
77    /// Parsing errors (int, float, etc.)
78    #[error("Parsing error: {0}")]
79    ParseFloatError(#[from] std::num::ParseFloatError),
80
81    /// Generic error for cases not covered by specific error types
82    #[error("Internal error: {0}")]
83    Internal(String),
84}
85
86impl BgpkitCommonsError {
87    /// Create a module not loaded error
88    pub fn module_not_loaded(module: &'static str, load_method: &'static str) -> Self {
89        Self::ModuleNotLoaded {
90            module,
91            load_method,
92        }
93    }
94
95    /// Create a module not configured error
96    pub fn module_not_configured(
97        module: &'static str,
98        requirement: &'static str,
99        load_method: &'static str,
100    ) -> Self {
101        Self::ModuleNotConfigured {
102            module,
103            requirement,
104            load_method,
105        }
106    }
107
108    /// Create a data source error
109    pub fn data_source_error(source: impl Into<String>, details: impl Into<String>) -> Self {
110        Self::DataSourceError {
111            data_source: source.into(),
112            details: details.into(),
113        }
114    }
115
116    /// Create an invalid format error
117    pub fn invalid_format(
118        data_type: &'static str,
119        input: impl Into<String>,
120        reason: impl Into<String>,
121    ) -> Self {
122        Self::InvalidFormat {
123            data_type,
124            input: input.into(),
125            reason: reason.into(),
126        }
127    }
128
129    /// Create a feature not enabled error
130    pub fn feature_not_enabled(feature: &'static str) -> Self {
131        Self::FeatureNotEnabled { feature }
132    }
133}
134
135/// Result type alias for bgpkit-commons operations
136pub type Result<T> = std::result::Result<T, BgpkitCommonsError>;
137
138/// Module-specific error constants for consistent error messages
139pub mod modules {
140    pub const ASINFO: &str = "asinfo";
141    pub const AS2REL: &str = "as2rel";
142    pub const BOGONS: &str = "bogons";
143    pub const COUNTRIES: &str = "countries";
144    pub const MRT_COLLECTORS: &str = "mrt_collectors";
145    pub const MRT_COLLECTOR_PEERS: &str = "mrt_collector_peers";
146    pub const RPKI: &str = "rpki";
147}
148
149/// Load method constants for consistent error messages
150pub mod load_methods {
151    pub const LOAD_ASINFO: &str = "load_asinfo";
152    pub const LOAD_ASINFO_CACHED: &str = "load_asinfo_cached";
153    pub const LOAD_AS2REL: &str = "load_as2rel";
154    pub const LOAD_BOGONS: &str = "load_bogons";
155    pub const LOAD_COUNTRIES: &str = "load_countries";
156    pub const LOAD_MRT_COLLECTORS: &str = "load_mrt_collectors";
157    pub const LOAD_MRT_COLLECTOR_PEERS: &str = "load_mrt_collector_peers";
158    pub const LOAD_RPKI: &str = "load_rpki";
159}
160
161/// Data source constants for consistent error messages
162pub mod data_sources {
163    pub const RIPE_NCC: &str = "RIPE NCC";
164    pub const CLOUDFLARE: &str = "Cloudflare";
165    pub const CAIDA: &str = "CAIDA";
166    pub const BGPKIT: &str = "BGPKIT";
167    pub const GEONAMES: &str = "GeoNames";
168    pub const IANA: &str = "IANA";
169    pub const ROUTEVIEWS: &str = "RouteViews";
170    pub const PEERINGDB: &str = "PeeringDB";
171    pub const APNIC: &str = "APNIC";
172    pub const IIJ_IHR: &str = "IIJ IHR";
173}