mobench_sdk/types.rs
1//! Core types for mobench-sdk.
2//!
3//! This module defines the fundamental types used throughout the SDK:
4//!
5//! - [`BenchError`] - Error types for benchmark and build operations
6//! - [`Target`] - Platform selection (Android, iOS, or both)
7//! - [`BuildConfig`] / [`BuildProfile`] - Build configuration options
8//! - [`BuildResult`] - Output from build operations
9//! - [`InitConfig`] - Project initialization settings
10//!
11//! ## Re-exports from timing module
12//!
13//! For convenience, this module also re-exports types from [`crate::timing`]:
14//!
15//! - [`BenchSpec`] - Benchmark specification (name, iterations, warmup)
16//! - [`BenchSample`] - Single timing measurement
17//! - [`RunnerReport`] - Complete benchmark results
18
19// Re-export timing types for convenience
20pub use crate::timing::{
21 BenchReport as RunnerReport, BenchSample, BenchSpec, TimingError as RunnerError,
22};
23
24use std::path::PathBuf;
25
26/// Error types for mobench-sdk operations.
27///
28/// This enum covers all error conditions that can occur during
29/// benchmark registration, execution, and mobile app building.
30///
31/// # Example
32///
33/// ```ignore
34/// use mobench_sdk::{run_benchmark, BenchSpec, BenchError};
35///
36/// let spec = BenchSpec {
37/// name: "nonexistent".to_string(),
38/// iterations: 10,
39/// warmup: 1,
40/// };
41///
42/// match run_benchmark(spec) {
43/// Ok(report) => println!("Success!"),
44/// Err(BenchError::UnknownFunction(name)) => {
45/// eprintln!("Benchmark '{}' not found", name);
46/// }
47/// Err(e) => eprintln!("Other error: {}", e),
48/// }
49/// ```
50#[derive(Debug, thiserror::Error)]
51pub enum BenchError {
52 /// Error from the underlying benchmark runner.
53 ///
54 /// This wraps errors from [`crate::timing::TimingError`], such as
55 /// zero iterations or execution failures.
56 #[error("benchmark runner error: {0}")]
57 Runner(#[from] crate::timing::TimingError),
58
59 /// The requested benchmark function was not found in the registry.
60 ///
61 /// This occurs when calling [`run_benchmark`](crate::run_benchmark) with
62 /// a function name that hasn't been registered via `#[benchmark]`.
63 ///
64 /// The error includes a list of available benchmarks to help diagnose the issue.
65 #[error("unknown benchmark function: '{0}'. Available benchmarks: {1:?}\n\nEnsure the function is:\n 1. Annotated with #[benchmark]\n 2. Public (pub fn)\n 3. Takes no parameters and returns ()")]
66 UnknownFunction(String, Vec<String>),
67
68 /// An error occurred during benchmark execution.
69 ///
70 /// This is a catch-all for execution-time errors that don't fit
71 /// other categories.
72 #[error("benchmark execution failed: {0}")]
73 Execution(String),
74
75 /// An I/O error occurred.
76 ///
77 /// Common causes include missing files, permission issues, or
78 /// disk space problems during build operations.
79 #[error("I/O error: {0}. Check file paths and permissions")]
80 Io(#[from] std::io::Error),
81
82 /// JSON serialization or deserialization failed.
83 ///
84 /// This can occur when reading/writing benchmark specifications
85 /// or configuration files.
86 #[error("serialization error: {0}. Check JSON validity or output serializability")]
87 Serialization(#[from] serde_json::Error),
88
89 /// A configuration error occurred.
90 ///
91 /// This indicates invalid or missing configuration, such as
92 /// malformed TOML files or missing required fields.
93 #[error("configuration error: {0}. Check mobench.toml or CLI flags")]
94 Config(String),
95
96 /// A build error occurred.
97 ///
98 /// This covers failures during mobile app building, including:
99 /// - Missing build tools (cargo-ndk, xcodebuild, etc.)
100 /// - Compilation errors
101 /// - Code signing failures
102 /// - Missing dependencies
103 #[error("build error: {0}")]
104 Build(String),
105}
106
107/// Target platform for benchmarks.
108///
109/// Specifies which mobile platform(s) to build for or run benchmarks on.
110///
111/// # Example
112///
113/// ```
114/// use mobench_sdk::Target;
115///
116/// let target = Target::Android;
117/// assert_eq!(target.as_str(), "android");
118///
119/// let both = Target::Both;
120/// assert_eq!(both.as_str(), "both");
121/// ```
122#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub enum Target {
124 /// Android platform (APK with native .so libraries).
125 Android,
126 /// iOS platform (xcframework with static libraries).
127 Ios,
128 /// Both Android and iOS platforms.
129 Both,
130}
131
132impl Target {
133 /// Returns the string representation of the target.
134 ///
135 /// # Returns
136 ///
137 /// - `"android"` for [`Target::Android`]
138 /// - `"ios"` for [`Target::Ios`]
139 /// - `"both"` for [`Target::Both`]
140 pub fn as_str(&self) -> &'static str {
141 match self {
142 Target::Android => "android",
143 Target::Ios => "ios",
144 Target::Both => "both",
145 }
146 }
147}
148
149/// Configuration for initializing a new benchmark project.
150///
151/// Used by the `cargo mobench init` command to generate project scaffolding.
152///
153/// # Example
154///
155/// ```
156/// use mobench_sdk::{InitConfig, Target};
157/// use std::path::PathBuf;
158///
159/// let config = InitConfig {
160/// target: Target::Android,
161/// project_name: "my-benchmarks".to_string(),
162/// output_dir: PathBuf::from("./bench-mobile"),
163/// generate_examples: true,
164/// };
165/// ```
166#[derive(Debug, Clone)]
167pub struct InitConfig {
168 /// Target platform(s) to initialize for.
169 pub target: Target,
170 /// Name of the benchmark project/crate.
171 pub project_name: String,
172 /// Output directory for generated files.
173 pub output_dir: PathBuf,
174 /// Whether to generate example benchmark functions.
175 pub generate_examples: bool,
176}
177
178/// Configuration for building mobile apps.
179///
180/// Controls the build process including target platform, optimization level,
181/// and caching behavior.
182///
183/// # Example
184///
185/// ```
186/// use mobench_sdk::{BuildConfig, BuildProfile, Target};
187///
188/// // Release build for Android
189/// let config = BuildConfig {
190/// target: Target::Android,
191/// profile: BuildProfile::Release,
192/// incremental: true,
193/// };
194///
195/// // Debug build for iOS
196/// let ios_config = BuildConfig {
197/// target: Target::Ios,
198/// profile: BuildProfile::Debug,
199/// incremental: false, // Force rebuild
200/// };
201/// ```
202#[derive(Debug, Clone)]
203pub struct BuildConfig {
204 /// Target platform to build for.
205 pub target: Target,
206 /// Build profile (debug or release).
207 pub profile: BuildProfile,
208 /// If `true`, skip rebuilding if artifacts already exist.
209 pub incremental: bool,
210}
211
212/// Build profile controlling optimization and debug info.
213///
214/// Similar to Cargo's `--release` flag, this controls whether the build
215/// is optimized for debugging or performance.
216///
217/// # Example
218///
219/// ```
220/// use mobench_sdk::BuildProfile;
221///
222/// let debug = BuildProfile::Debug;
223/// assert_eq!(debug.as_str(), "debug");
224///
225/// let release = BuildProfile::Release;
226/// assert_eq!(release.as_str(), "release");
227/// ```
228#[derive(Debug, Clone, Copy, PartialEq, Eq)]
229pub enum BuildProfile {
230 /// Debug build with debug symbols and no optimizations.
231 ///
232 /// Faster compilation but slower runtime. Useful for development
233 /// and troubleshooting.
234 Debug,
235 /// Release build with optimizations enabled.
236 ///
237 /// Slower compilation but faster runtime. Use this for actual
238 /// benchmark measurements.
239 Release,
240}
241
242impl BuildProfile {
243 /// Returns the string representation of the profile.
244 ///
245 /// # Returns
246 ///
247 /// - `"debug"` for [`BuildProfile::Debug`]
248 /// - `"release"` for [`BuildProfile::Release`]
249 pub fn as_str(&self) -> &'static str {
250 match self {
251 BuildProfile::Debug => "debug",
252 BuildProfile::Release => "release",
253 }
254 }
255}
256
257/// Result of a successful build operation.
258///
259/// Contains paths to the built artifacts, which can be used for
260/// deployment to BrowserStack or local testing.
261///
262/// # Example
263///
264/// ```ignore
265/// use mobench_sdk::builders::AndroidBuilder;
266///
267/// let result = builder.build(&config)?;
268///
269/// println!("App built at: {:?}", result.app_path);
270/// if let Some(test_suite) = result.test_suite_path {
271/// println!("Test suite at: {:?}", test_suite);
272/// }
273/// ```
274#[derive(Debug, Clone)]
275pub struct BuildResult {
276 /// Platform that was built.
277 pub platform: Target,
278 /// Path to the main app artifact.
279 ///
280 /// - Android: Path to the APK file
281 /// - iOS: Path to the xcframework directory
282 pub app_path: PathBuf,
283 /// Path to the test suite artifact, if applicable.
284 ///
285 /// - Android: Path to the androidTest APK (for Espresso)
286 /// - iOS: Path to the XCUITest runner zip
287 pub test_suite_path: Option<PathBuf>,
288}