Skip to main content

cu_profiler_core/
error.rs

1//! Typed error model for `cu-profiler-core`.
2//!
3//! Errors are actionable: parser failures carry the offending log line index and
4//! the concrete reason, so a caller can render a message like
5//! `Failed to parse compute-unit line at log index 42: expected integer after
6//! "consumed"` rather than a bare `parse failed`.
7
8use std::fmt;
9
10/// The result type used throughout the core crate.
11pub type Result<T> = std::result::Result<T, Error>;
12
13/// All error conditions the core can surface.
14///
15/// Variants map onto the documented CLI exit codes (see the `cu-profiler-cli`
16/// crate) so the boundary layer can translate an [`Error`] into a stable code.
17#[derive(Debug, thiserror::Error)]
18#[non_exhaustive]
19pub enum Error {
20    /// The configuration file was missing, malformed, or semantically invalid.
21    #[error("configuration error: {0}")]
22    Config(String),
23
24    /// A Solana log line could not be parsed. Carries enough context to locate
25    /// and explain the failure.
26    #[error("failed to parse {what} at log index {index}: {reason}")]
27    Parse {
28        /// What the parser was trying to read (e.g. `"compute-unit line"`).
29        what: String,
30        /// Zero-based index of the offending line within the log stream.
31        index: usize,
32        /// Why parsing failed, in plain language.
33        reason: String,
34    },
35
36    /// A simulation backend failed to execute a scenario.
37    #[error("simulation failure: {0}")]
38    Simulation(String),
39
40    /// A baseline could not be read, written, or compared.
41    #[error("baseline error: {0}")]
42    Baseline(String),
43
44    /// A backend exists as an interface but is not implemented in this build.
45    #[error("execution backend `{0}` is not implemented in this build")]
46    BackendUnimplemented(String),
47
48    /// An underlying I/O failure.
49    #[error("i/o error: {0}")]
50    Io(#[from] std::io::Error),
51
52    /// A TOML (de)serialization failure, kept as a string so the error type
53    /// stays independent of the `toml` error representation.
54    #[error("toml error: {0}")]
55    Toml(String),
56
57    /// A JSON (de)serialization failure.
58    #[cfg(feature = "json")]
59    #[error("json error: {0}")]
60    Json(#[from] serde_json::Error),
61}
62
63impl Error {
64    /// Build a [`Error::Parse`] without repeating the field names at call sites.
65    pub fn parse(what: impl fmt::Display, index: usize, reason: impl fmt::Display) -> Self {
66        Self::Parse {
67            what: what.to_string(),
68            index,
69            reason: reason.to_string(),
70        }
71    }
72}
73
74impl From<toml::de::Error> for Error {
75    fn from(e: toml::de::Error) -> Self {
76        Self::Toml(e.to_string())
77    }
78}