waterui-cli 0.1.3

A modern UI framework for Rust
Documentation
//! Platform abstraction for `WaterUI` CLI

use std::path::PathBuf;

use color_eyre::eyre;
use target_lexicon::Triple;

use crate::{
    build::BuildOptions,
    device::{Artifact, Device},
    project::Project,
    toolchain::Toolchain,
};

/// Build options for the platform
#[derive(Debug, Clone)]
/// Configuration options for packaging the application.
///
/// This struct contains settings that control how the application
/// is packaged for distribution across different platforms.
pub struct PackageOptions {
    /// Whether to prepare the package for store distribution.
    ///
    /// When `true`, the package will be configured for submission to
    /// official app stores (App Store for iOS/macOS or Play Store for Android).
    ///
    /// When `false`, the package will be prepared for direct distribution
    /// or development purposes.
    ///
    /// # Warning
    ///
    /// Enable this option only change your packaging format, it does not change your build configuration.
    /// For a real world distribution build, you may also want to disable `debug` in `BuildOptions`.
    distribution: bool,

    /// Whether to enable debug mode in the packaged application.
    ///
    /// When `true`, the application will include additional debug information
    /// and logging capabilities to facilitate troubleshooting during development.
    ///
    /// When `false`, the application will be optimized for release with
    /// minimal debug information.
    ///
    /// This flag is not conflict with `distribution`, since `distribution` decide the package format,
    /// while `debug` decide the build configuration.
    debug: bool,
}

impl PackageOptions {
    /// Create new package options
    #[must_use]
    pub const fn new(distribution: bool, debug: bool) -> Self {
        Self {
            distribution,
            debug,
        }
    }

    /// Whether to package in distribution mode
    #[must_use]
    pub const fn is_distribution(&self) -> bool {
        self.distribution
    }

    /// Whether to package in debug mode
    #[must_use]
    pub const fn is_debug(&self) -> bool {
        self.debug
    }
}

/// Trait representing a specific platform (e.g., Android, iOS, etc.)
///
/// Note: `Platform` would never check toolchain since it is the responsibility of the `Toolchain`.
/// We assume the toolchain is already set up correctly when calling methods of this trait.
pub trait Platform: Send + Sync {
    /// The associated toolchain type for this platform.
    type Toolchain: Toolchain;
    /// The associated device type for this platform.
    type Device: Device;

    /// Clean build artifacts for this platform (not include rust build artifacts)
    fn clean(&self, project: &Project) -> impl Future<Output = eyre::Result<()>> + Send;

    /// Package the project for this platform
    ///
    /// Return the path to the packaged file
    ///
    /// # Warnings
    /// You should call `build` before calling this method to ensure the project is built for the platform.
    fn package(
        &self,
        project: &Project,
        options: PackageOptions,
    ) -> impl Future<Output = eyre::Result<Artifact>> + Send;

    /// Get the toolchain for this platform
    fn toolchain(&self) -> Self::Toolchain;

    /// Scan for connected devices for this platform
    fn scan(&self) -> impl Future<Output = eyre::Result<Vec<Self::Device>>> + Send;

    /// Get the target triple for this platform
    fn triple(&self) -> Triple;

    /// Build the Rust library for this platform
    ///
    /// Warning: This method would build and copy the built library to the appropriate location in the project directory.
    /// However, it does not handle hot reload library building or management.
    ///
    /// Return the target directory path where the built library is located.
    fn build(
        &self,
        project: &Project,
        options: BuildOptions,
    ) -> impl Future<Output = eyre::Result<PathBuf>> + Send;
}