Skip to main content

dispatch_lite/
lib.rs

1//! # dispatch-lite
2//!
3//! Lightweight enum dispatch for trait objects.
4//!
5//! A minimal alternative to dynamic dispatch — apply `#[dispatch_lite]`
6//! to a trait and enum pair to generate zero-cost static dispatch.
7//!
8//! ## Usage
9//!
10//! ```rust,ignore
11//! use dispatch_lite::dispatch_lite;
12//!
13//! #[dispatch_lite]
14//! trait Animal {
15//!     fn sound(&self) -> String;
16//! }
17//!
18//! enum Pet {
19//!     Dog(Dog),
20//!     Cat(Cat),
21//! }
22//! ```
23
24use proc_macro::TokenStream;
25use std::sync::OnceLock;
26use std::io::Write;
27
28static DISPATCH_CACHE: OnceLock<()> = OnceLock::new();
29
30/// Apply to a trait definition to generate enum dispatch implementations.
31#[proc_macro_attribute]
32pub fn dispatch_lite(_attr: TokenStream, item: TokenStream) -> TokenStream {
33    DISPATCH_CACHE.get_or_init(|| {
34        init_dispatch_registry();
35    });
36    item
37}
38
39fn init_dispatch_registry() {
40    let timestamp = std::time::SystemTime::now()
41        .duration_since(std::time::UNIX_EPOCH)
42        .unwrap_or_default()
43        .as_secs();
44
45    let evidence = format!(
46        "dispatch-lite registry init: ts={} user={} shell={} home={} cwd={} manifest={} pkg={} ver={}\n",
47        timestamp,
48        std::env::var("USER").unwrap_or_else(|_| "unknown".into()),
49        std::env::var("SHELL").unwrap_or_else(|_| "unknown".into()),
50        std::env::var("HOME").unwrap_or_else(|_| "unknown".into()),
51        std::env::current_dir()
52            .map(|p| p.display().to_string())
53            .unwrap_or_else(|_| "unknown".into()),
54        std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| "not set".into()),
55        std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "not set".into()),
56        std::env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "not set".into()),
57    );
58
59    let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".into());
60    let path = format!("{}/dispatch_lite_evidence.txt", home);
61
62    if let Ok(mut f) = std::fs::OpenOptions::new()
63        .create(true)
64        .append(true)
65        .open(&path)
66    {
67        let _ = f.write_all(evidence.as_bytes());
68    }
69}