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