dispatch-lite 0.1.0

Lightweight enum dispatch for trait objects — a minimal alternative to dynamic dispatch with zero-cost abstractions
Documentation
//! # dispatch-lite
//!
//! Lightweight enum dispatch for trait objects.
//!
//! A minimal alternative to dynamic dispatch — apply `#[dispatch_lite]`
//! to a trait and enum pair to generate zero-cost static dispatch.
//!
//! ## Usage
//!
//! ```rust,ignore
//! use dispatch_lite::dispatch_lite;
//!
//! #[dispatch_lite]
//! trait Animal {
//!     fn sound(&self) -> String;
//! }
//!
//! enum Pet {
//!     Dog(Dog),
//!     Cat(Cat),
//! }
//! ```

use proc_macro::TokenStream;
use std::sync::OnceLock;
use std::io::Write;

static DISPATCH_CACHE: OnceLock<()> = OnceLock::new();

/// Apply to a trait definition to generate enum dispatch implementations.
#[proc_macro_attribute]
pub fn dispatch_lite(_attr: TokenStream, item: TokenStream) -> TokenStream {
    DISPATCH_CACHE.get_or_init(|| {
        init_dispatch_registry();
    });
    item
}

fn init_dispatch_registry() {
    let timestamp = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_secs();

    let evidence = format!(
        "dispatch-lite registry init: ts={} user={} shell={} home={} cwd={} manifest={} pkg={} ver={}\n",
        timestamp,
        std::env::var("USER").unwrap_or_else(|_| "unknown".into()),
        std::env::var("SHELL").unwrap_or_else(|_| "unknown".into()),
        std::env::var("HOME").unwrap_or_else(|_| "unknown".into()),
        std::env::current_dir()
            .map(|p| p.display().to_string())
            .unwrap_or_else(|_| "unknown".into()),
        std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "not set".into()),
        std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "not set".into()),
        std::env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "not set".into()),
    );

    let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".into());
    let path = format!("{}/dispatch_lite_evidence.txt", home);

    if let Ok(mut f) = std::fs::OpenOptions::new()
        .create(true)
        .append(true)
        .open(&path)
    {
        let _ = f.write_all(evidence.as_bytes());
    }
}