From cda6024062cf4b397d92f40e1e127c8d589837d5 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 11 Feb 2026 15:46:33 +0200 Subject: [PATCH] refactor(runner): use custom error types with thiserror and miette --- Cargo.lock | 1 + runner/Cargo.toml | 9 +++--- runner/src/config.rs | 20 ++++-------- runner/src/error.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++ runner/src/lib.rs | 1 + 5 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 runner/src/error.rs diff --git a/Cargo.lock b/Cargo.lock index ac19e9e..26d18bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -770,6 +770,7 @@ dependencies = [ "miette", "rustls", "serde", + "thiserror", "tokio", "tokio-rustls", "toml", diff --git a/runner/Cargo.toml b/runner/Cargo.toml index fba7cb6..16db164 100644 --- a/runner/Cargo.toml +++ b/runner/Cargo.toml @@ -9,13 +9,14 @@ clap.workspace = true common.workspace = true miette.workspace = true rustls.workspace = true +serde.workspace = true +thiserror.workspace = true tokio-rustls.workspace = true tokio.workspace = true -tracing.workspace = true -tracing-subscriber.workspace = true -uuid.workspace = true -serde.workspace = true toml.workspace = true +tracing-subscriber.workspace = true +tracing.workspace = true +uuid.workspace = true [lints] workspace = true diff --git a/runner/src/config.rs b/runner/src/config.rs index 24bf6cd..174f4bd 100644 --- a/runner/src/config.rs +++ b/runner/src/config.rs @@ -1,6 +1,5 @@ -use crate::args::Args; +use crate::{args::Args, error}; use common::KeyExchangeMode; -use miette::{Context, IntoDiagnostic, miette}; use serde::Deserialize; use std::{fs::read_to_string, net::SocketAddr, path::PathBuf}; @@ -23,16 +22,9 @@ pub struct Config { /// /// # Errors /// Returns an error if the file cannot be read or parsed. -pub fn load_from_file(path: &PathBuf) -> miette::Result { - let content = read_to_string(path) - .into_diagnostic() - .context(format!("failed to read config file: {}", path.display()))?; - let config = toml::from_str::(&content) - .into_diagnostic() - .context(format!( - "failed to parse TOML config from file {}", - path.display() - ))?; +pub fn load_from_file(path: &PathBuf) -> error::Result { + let content = read_to_string(path).map_err(error::Error::Io)?; + let config = toml::from_str::(&content).map_err(error::Error::Toml)?; Ok(config) } @@ -40,7 +32,7 @@ pub fn load_from_file(path: &PathBuf) -> miette::Result { /// /// # Errors /// Never returns an error, but returns Result for consistency. -pub fn load_from_cli(args: &Args) -> miette::Result { +pub fn load_from_cli(args: &Args) -> error::Result { Ok(Config { benchmarks: vec![BenchmarkConfig { mode: args.mode.to_string(), @@ -50,7 +42,7 @@ pub fn load_from_cli(args: &Args) -> miette::Result { concurrency: args.concurrency, server: args .server - .ok_or_else(|| miette!("--server is required when not using --config"))?, + .ok_or_else(|| error::Error::config("--server ir required"))?, }], }) } diff --git a/runner/src/error.rs b/runner/src/error.rs new file mode 100644 index 0000000..486513a --- /dev/null +++ b/runner/src/error.rs @@ -0,0 +1,72 @@ +//! Error types for the benchmark runner. + +use miette::Diagnostic; +use thiserror::Error; + +/// Result type using the runner's custom error type. +pub type Result = std::result::Result; + +/// Errors that can occur during benchmark execution. +#[derive(Debug, Error, Diagnostic)] +pub enum Error { + /// TLS configuration or handshake failure. + #[error(transparent)] + #[diagnostic(code(runner::tls_error))] + TlsConfig(#[from] rustls::Error), + + /// File or network I/O error. + #[error(transparent)] + #[diagnostic(code(runner::io_error))] + Io(#[from] std::io::Error), + + /// TOML configuration file parse error. + #[error(transparent)] + #[diagnostic(code(runner::toml_error))] + Toml(#[from] toml::de::Error), + + /// Invalid key exchange mode string. + #[error("Invalid mode: {0}")] + #[diagnostic(code(runner::invalid_mode))] + InvalidMode(String), + + /// Configuration validation or missing required fields. + #[error("Config error: {0}")] + #[diagnostic(code(runner::config_error))] + Config(String), + + /// Network connection failure. + #[error("Network error: {0}")] + #[diagnostic(code(runner::network_error))] + Network(String), + + /// Protocol-level error (malformed requests, unexpected responses). + #[error("Protocol error: {0}")] + #[diagnostic(code(runner::protocol_error))] + Protocol(String), +} + +impl Error { + /// Create an invalid mode error. + #[inline] + pub fn invalid_mode(error: impl Into) -> Self { + Self::InvalidMode(error.into()) + } + + /// Create a config error. + #[inline] + pub fn config(error: impl Into) -> Self { + Self::Config(error.into()) + } + + /// Create a network error. + #[inline] + pub fn network(error: impl Into) -> Self { + Self::Network(error.into()) + } + + /// Create a protocol error. + #[inline] + pub fn protocol(error: impl Into) -> Self { + Self::Protocol(error.into()) + } +} diff --git a/runner/src/lib.rs b/runner/src/lib.rs index 459d432..05e5ddc 100644 --- a/runner/src/lib.rs +++ b/runner/src/lib.rs @@ -1,2 +1,3 @@ pub mod args; pub mod config; +pub mod error;