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}