Skip to main content

cargo_samply/
error.rs

1//! Error handling for cargo-samply.
2//!
3//! This module provides a comprehensive error type using `thiserror` that covers
4//! all the various failure modes that can occur during the build and profiling process.
5//!
6//! # Examples
7//!
8//! ```no_run
9//! use cargo_samply::error::{Error, Result};
10//! use std::path::PathBuf;
11//!
12//! fn example_function() -> Result<()> {
13//!     let path = PathBuf::from("nonexistent");
14//!     if !path.exists() {
15//!         return Err(Error::BinaryNotFound { path });
16//!     }
17//!     Ok(())
18//! }
19//! ```
20
21use std::io;
22use std::path::PathBuf;
23use std::result;
24use std::str::Utf8Error;
25use thiserror::Error;
26
27/// Comprehensive error type for cargo-samply operations.
28///
29/// This enum covers all possible error conditions that can occur during
30/// the build and profiling process, providing detailed error messages
31/// and context where appropriate.
32#[derive(Debug, Error)]
33pub enum Error {
34    /// I/O error with path context for better error reporting
35    #[error("{path}: {source}")]
36    PathIo { source: io::Error, path: PathBuf },
37    /// Generic I/O error
38    #[error(transparent)]
39    Io(#[from] io::Error),
40    /// Logger initialization error
41    #[error(transparent)]
42    Logger(#[from] log::SetLoggerError),
43    /// UTF-8 conversion error
44    #[error(transparent)]
45    Utf8(#[from] Utf8Error),
46    /// TOML deserialization error
47    #[error(transparent)]
48    TomlDeserialization(#[from] toml::de::Error),
49    /// Cargo.toml manifest parsing error
50    #[error(transparent)]
51    TomlManifest(#[from] cargo_toml::Error),
52    /// Target-selection flags (bin/example/bench/test) are mutually exclusive
53    #[error("Target selection flags (--bin, --example, --bench, --test) are mutually exclusive")]
54    MultipleTargetsFlagsSpecified,
55    /// Cargo build process failed
56    #[error("Build failed")]
57    CargoBuildFailed,
58    /// No binary targets found in Cargo.toml
59    #[error("No binary found in 'Cargo.toml'")]
60    NoBinaryFound,
61    /// Multiple binaries found but no default specified
62    #[error("The binary to run can't be determined. Use the `--bin` option to specify a binary, or the `default-run` manifest key.{suggestions}")]
63    BinaryToRunNotDetermined { suggestions: String },
64    /// Failed to locate the cargo project
65    #[error("Failed to locate project")]
66    CargoLocateProjectFailed,
67    /// Built binary not found in target directory
68    #[error("Binary not found: {path}")]
69    BinaryNotFound { path: PathBuf },
70    /// Package not found in workspace
71    #[error("Package '{name}' not found in workspace")]
72    PackageNotFound { name: String },
73    /// Samply binary not installed or not in PATH
74    #[error("samply is not installed or not in PATH")]
75    SamplyNotFound,
76    /// Failed to get Rust sysroot from rustc
77    #[error("Failed to get Rust sysroot: {message}")]
78    RustSysrootFailed { message: String },
79    /// Failed to get Rust host target from rustc
80    #[error("Failed to get Rust host target: {message}")]
81    RustHostTargetFailed { message: String },
82    /// Invalid samply arguments
83    #[error("Invalid samply arguments: {0}")]
84    InvalidSamplyArgs(String),
85    /// Failed to capture cargo stdout
86    #[error("Failed to capture cargo stdout: {0}")]
87    CargoStdoutCaptureFailed(String),
88    /// cargo-metadata execution failed
89    #[error("Cargo metadata failed: {0}")]
90    CargoMetadataFailed(#[from] cargo_metadata::Error),
91}
92
93/// Alias for a `Result` with the error type `cargo_samply::Error`.
94///
95/// This type alias simplifies function signatures throughout the codebase
96/// by providing a default error type.
97pub type Result<T> = result::Result<T, Error>;
98
99/// Extension trait for `io::Result` to add path context to I/O errors.
100///
101/// This trait provides a convenient way to add file path information
102/// to I/O errors, making debugging easier.
103///
104/// # Examples
105///
106/// ```no_run
107/// use cargo_samply::error::{IOResultExt, Result};
108/// use std::fs;
109/// use std::path::Path;
110///
111/// fn read_file(path: &Path) -> Result<String> {
112///     fs::read_to_string(path).path_ctx(path)
113/// }
114/// ```
115pub trait IOResultExt<T> {
116    /// Add path context to an I/O result
117    fn path_ctx<P: Into<PathBuf>>(self, path: P) -> Result<T>;
118}
119
120impl<T> IOResultExt<T> for io::Result<T> {
121    fn path_ctx<P: Into<PathBuf>>(self, path: P) -> Result<T> {
122        self.map_err(|source| Error::PathIo {
123            source,
124            path: path.into(),
125        })
126    }
127}