Skip to main content

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, BenchSummary, 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(
66        "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 ()"
67    )]
68    UnknownFunction(String, Vec<String>),
69
70    /// An error occurred during benchmark execution.
71    ///
72    /// This is a catch-all for execution-time errors that don't fit
73    /// other categories.
74    #[error("benchmark execution failed: {0}")]
75    Execution(String),
76
77    /// An I/O error occurred.
78    ///
79    /// Common causes include missing files, permission issues, or
80    /// disk space problems during build operations.
81    #[error("I/O error: {0}. Check file paths and permissions")]
82    Io(#[from] std::io::Error),
83
84    /// JSON serialization or deserialization failed.
85    ///
86    /// This can occur when reading/writing benchmark specifications
87    /// or configuration files.
88    #[error("serialization error: {0}. Check JSON validity or output serializability")]
89    Serialization(#[from] serde_json::Error),
90
91    /// A configuration error occurred.
92    ///
93    /// This indicates invalid or missing configuration, such as
94    /// malformed TOML files or missing required fields.
95    #[error("configuration error: {0}. Check mobench.toml or CLI flags")]
96    Config(String),
97
98    /// A build error occurred.
99    ///
100    /// This covers failures during mobile app building, including:
101    /// - Missing build tools (cargo-ndk, xcodebuild, etc.)
102    /// - Compilation errors
103    /// - Code signing failures
104    /// - Missing dependencies
105    #[error("build error: {0}")]
106    Build(String),
107}
108
109/// Target platform for benchmarks.
110///
111/// Specifies which mobile platform(s) to build for or run benchmarks on.
112///
113/// # Example
114///
115/// ```
116/// use mobench_sdk::Target;
117///
118/// let target = Target::Android;
119/// assert_eq!(target.as_str(), "android");
120///
121/// let both = Target::Both;
122/// assert_eq!(both.as_str(), "both");
123/// ```
124#[derive(Debug, Clone, Copy, PartialEq, Eq)]
125pub enum Target {
126    /// Android platform (APK with native .so libraries).
127    Android,
128    /// iOS platform (xcframework with static libraries).
129    Ios,
130    /// Both Android and iOS platforms.
131    Both,
132}
133
134impl Target {
135    /// Returns the string representation of the target.
136    ///
137    /// # Returns
138    ///
139    /// - `"android"` for [`Target::Android`]
140    /// - `"ios"` for [`Target::Ios`]
141    /// - `"both"` for [`Target::Both`]
142    pub fn as_str(&self) -> &'static str {
143        match self {
144            Target::Android => "android",
145            Target::Ios => "ios",
146            Target::Both => "both",
147        }
148    }
149}
150
151/// Configuration for initializing a new benchmark project.
152///
153/// Used by the `cargo mobench init` command to generate project scaffolding.
154///
155/// # Example
156///
157/// ```
158/// use mobench_sdk::{InitConfig, Target};
159/// use std::path::PathBuf;
160///
161/// let config = InitConfig {
162///     target: Target::Android,
163///     project_name: "my-benchmarks".to_string(),
164///     output_dir: PathBuf::from("./bench-mobile"),
165///     generate_examples: true,
166/// };
167/// ```
168#[derive(Debug, Clone)]
169pub struct InitConfig {
170    /// Target platform(s) to initialize for.
171    pub target: Target,
172    /// Name of the benchmark project/crate.
173    pub project_name: String,
174    /// Output directory for generated files.
175    pub output_dir: PathBuf,
176    /// Whether to generate example benchmark functions.
177    pub generate_examples: bool,
178}
179
180/// Configuration for building mobile apps.
181///
182/// Controls the build process including target platform, optimization level,
183/// and caching behavior.
184///
185/// # Example
186///
187/// ```
188/// use mobench_sdk::{BuildConfig, BuildProfile, Target};
189///
190/// // Release build for Android
191/// let config = BuildConfig {
192///     target: Target::Android,
193///     profile: BuildProfile::Release,
194///     incremental: true,
195/// };
196///
197/// // Debug build for iOS
198/// let ios_config = BuildConfig {
199///     target: Target::Ios,
200///     profile: BuildProfile::Debug,
201///     incremental: false,  // Force rebuild
202/// };
203/// ```
204#[derive(Debug, Clone)]
205pub struct BuildConfig {
206    /// Target platform to build for.
207    pub target: Target,
208    /// Build profile (debug or release).
209    pub profile: BuildProfile,
210    /// If `true`, skip rebuilding if artifacts already exist.
211    pub incremental: bool,
212}
213
214/// Build profile controlling optimization and debug info.
215///
216/// Similar to Cargo's `--release` flag, this controls whether the build
217/// is optimized for debugging or performance.
218///
219/// # Example
220///
221/// ```
222/// use mobench_sdk::BuildProfile;
223///
224/// let debug = BuildProfile::Debug;
225/// assert_eq!(debug.as_str(), "debug");
226///
227/// let release = BuildProfile::Release;
228/// assert_eq!(release.as_str(), "release");
229/// ```
230#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231pub enum BuildProfile {
232    /// Debug build with debug symbols and no optimizations.
233    ///
234    /// Faster compilation but slower runtime. Useful for development
235    /// and troubleshooting.
236    Debug,
237    /// Release build with optimizations enabled.
238    ///
239    /// Slower compilation but faster runtime. Use this for actual
240    /// benchmark measurements.
241    Release,
242}
243
244impl BuildProfile {
245    /// Returns the string representation of the profile.
246    ///
247    /// # Returns
248    ///
249    /// - `"debug"` for [`BuildProfile::Debug`]
250    /// - `"release"` for [`BuildProfile::Release`]
251    pub fn as_str(&self) -> &'static str {
252        match self {
253            BuildProfile::Debug => "debug",
254            BuildProfile::Release => "release",
255        }
256    }
257}
258
259/// Result of a successful build operation.
260///
261/// Contains paths to the built artifacts, which can be used for
262/// deployment to BrowserStack or local testing.
263///
264/// # Example
265///
266/// ```ignore
267/// use mobench_sdk::builders::AndroidBuilder;
268///
269/// let result = builder.build(&config)?;
270///
271/// println!("App built at: {:?}", result.app_path);
272/// if let Some(test_suite) = result.test_suite_path {
273///     println!("Test suite at: {:?}", test_suite);
274/// }
275/// ```
276#[derive(Debug, Clone)]
277pub struct BuildResult {
278    /// Platform that was built.
279    pub platform: Target,
280    /// Path to the main app artifact.
281    ///
282    /// - Android: Path to the APK file
283    /// - iOS: Path to the xcframework directory
284    pub app_path: PathBuf,
285    /// Path to the test suite artifact, if applicable.
286    ///
287    /// - Android: Path to the androidTest APK (for Espresso)
288    /// - iOS: Path to the XCUITest runner zip
289    pub test_suite_path: Option<PathBuf>,
290}