webpage_quality_analyzer 1.0.2

High-performance webpage quality analyzer with 115 comprehensive metrics - Rust library with WASM, C++, and Python bindings
Documentation
//! Async runtime abstraction layer
//!
//! This module provides a unified async interface that works across different platforms:
//! - Native/Server: Uses tokio + reqwest
//! - WASM/Browser: Uses web-sys + browser fetch API
//!
//! This allows the same analyzer code to run in both environments with full async support.

use crate::AnalyzeError;
use std::future::Future;
use std::pin::Pin;

// Platform-specific implementations
#[cfg(not(target_arch = "wasm32"))]
mod tokio_runtime;

#[cfg(target_arch = "wasm32")]
mod wasm_runtime;

// Re-export the appropriate runtime
#[cfg(not(target_arch = "wasm32"))]
pub use tokio_runtime::TokioRuntime;

#[cfg(target_arch = "wasm32")]
pub use wasm_runtime::WasmRuntime;

/// Default runtime type based on target platform
#[cfg(not(target_arch = "wasm32"))]
pub type DefaultRuntime = TokioRuntime;

#[cfg(target_arch = "wasm32")]
pub type DefaultRuntime = WasmRuntime;

/// Result type for HTTP fetch operations
#[derive(Debug, Clone)]
pub struct FetchResult {
    pub url: String,
    pub status: u16,
    pub body: String,
    pub headers: Vec<(String, String)>,
}

/// Trait abstracting async runtime operations
///
/// This allows the same analyzer code to work with different async backends:
/// - tokio (native) for server-side with high concurrency
/// - wasm-bindgen-futures (WASM) for browser with JavaScript Promises
///
/// Note: Send/Sync bounds are only required for native (multi-threaded) targets.
/// WASM is single-threaded so Send is not applicable.
#[cfg(not(target_arch = "wasm32"))]
pub trait AsyncRuntime: Send + Sync + 'static {
    /// Fetch content from a URL
    ///
    /// Native: Uses reqwest with tokio
    /// WASM: Uses browser fetch API via web-sys
    fn fetch_url(
        &self,
        url: &str,
    ) -> Pin<Box<dyn Future<Output = Result<FetchResult, AnalyzeError>> + Send + '_>>;

    /// Check if a URL is accessible (HEAD request)
    ///
    /// Used for link validation
    fn check_url(
        &self,
        url: &str,
    ) -> Pin<Box<dyn Future<Output = Result<bool, AnalyzeError>> + Send + '_>>;

    /// Fetch multiple URLs in parallel
    fn fetch_batch(
        &self,
        urls: Vec<String>,
    ) -> Pin<Box<dyn Future<Output = Vec<Result<FetchResult, AnalyzeError>>> + Send + '_>>;

    /// Spawn a background task
    fn spawn<F>(&self, future: F)
    where
        F: Future<Output = ()> + Send + 'static;

    /// Get the runtime name for debugging
    fn runtime_name(&self) -> &'static str;
}

/// WASM version without Send bounds (single-threaded environment)
#[cfg(target_arch = "wasm32")]
pub trait AsyncRuntime: 'static {
    /// Fetch content from a URL
    ///
    /// Native: Uses reqwest with tokio
    /// WASM: Uses browser fetch API via web-sys
    fn fetch_url(
        &self,
        url: &str,
    ) -> Pin<Box<dyn Future<Output = Result<FetchResult, AnalyzeError>> + '_>>;

    /// Check if a URL is accessible (HEAD request)
    ///
    /// Used for link validation
    fn check_url(
        &self,
        url: &str,
    ) -> Pin<Box<dyn Future<Output = Result<bool, AnalyzeError>> + '_>>;

    /// Fetch multiple URLs in parallel
    fn fetch_batch(
        &self,
        urls: Vec<String>,
    ) -> Pin<Box<dyn Future<Output = Vec<Result<FetchResult, AnalyzeError>>> + '_>>;

    /// Spawn a background task
    fn spawn<F>(&self, future: F)
    where
        F: Future<Output = ()> + 'static;

    /// Get the runtime name for debugging
    fn runtime_name(&self) -> &'static str;
}

/// Create the default runtime for the current platform
pub fn create_default_runtime() -> DefaultRuntime {
    DefaultRuntime::default()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_runtime_creation() {
        let runtime = create_default_runtime();

        #[cfg(not(target_arch = "wasm32"))]
        assert_eq!(runtime.runtime_name(), "tokio");

        #[cfg(target_arch = "wasm32")]
        assert_eq!(runtime.runtime_name(), "wasm");
    }
}