tiny-counter 0.1.0

Track event counts across time windows with fixed memory and fast queries
Documentation
// Type-safe event IDs with enums.
//
// This example shows how to:
// - Use the EventId trait for type-safe event enums
// - Implement AsRef<str> and EventId for your enum
// - Pass enums directly to record() and query()
// - Get autocomplete and refactoring support from your IDE

use tiny_counter::{EventId, EventStore};

// Define events as an enum for type safety
#[derive(Debug, Clone, Copy)]
enum AppEvent {
    Launch,
    FeatureUsed,
    SettingsOpened,
    PurchaseCompleted,
}

// Implement AsRef<str> to convert enum to event ID string
impl AsRef<str> for AppEvent {
    fn as_ref(&self) -> &str {
        match self {
            AppEvent::Launch => "app:launch",
            AppEvent::FeatureUsed => "app:feature_used",
            AppEvent::SettingsOpened => "app:settings_opened",
            AppEvent::PurchaseCompleted => "app:purchase_completed",
        }
    }
}

// Implement EventId marker trait (enables use with EventStore methods)
impl EventId for AppEvent {}

fn main() {
    println!("=== Type-Safe Events with Enums ===\n");

    let store = EventStore::new();

    // Record events using enum variants directly
    println!("Recording events with enum variants:");
    store.record(AppEvent::Launch);
    store.record(AppEvent::Launch);
    store.record(AppEvent::FeatureUsed);
    store.record(AppEvent::SettingsOpened);
    println!("  Recorded 2 launches, 1 feature use, 1 settings open\n");

    // Query using enum variants directly
    println!("Querying with type safety:");
    let launches = store
        .query(AppEvent::Launch)
        .last_days(7)
        .sum()
        .unwrap_or(0);
    println!("  Launches: {}", launches);

    let feature_uses = store
        .query(AppEvent::FeatureUsed)
        .last_days(7)
        .sum()
        .unwrap_or(0);
    println!("  Feature uses: {}", feature_uses);

    // Compare with string-based approach
    println!("\n=== Why Enums? ===\n");

    println!("With strings (error-prone):");
    println!("  store.record(\"app:launch\");     // Works");
    println!("  store.record(\"app:launhc\");     // Typo! No compile error");
    println!("  store.record(\"app_launch\");     // Wrong format! No error\n");

    println!("With enums + EventId trait (safe):");
    println!("  store.record(AppEvent::Launch);  // Works - clean!");
    println!("  store.record(AppEvent::Launhc);  // Compile error!");
    println!("  // No .event_id() or .to_string() needed");
    println!("  // IDE autocomplete shows all variants\n");

    // Demonstrate pattern matching with enums
    println!("=== Pattern Matching ===\n");

    fn classify_event(event: AppEvent) -> &'static str {
        match event {
            AppEvent::Launch | AppEvent::SettingsOpened => "navigation",
            AppEvent::FeatureUsed => "engagement",
            AppEvent::PurchaseCompleted => "conversion",
        }
    }

    println!("Event categories:");
    println!("  Launch -> {}", classify_event(AppEvent::Launch));
    println!("  FeatureUsed -> {}", classify_event(AppEvent::FeatureUsed));
    println!(
        "  PurchaseCompleted -> {}",
        classify_event(AppEvent::PurchaseCompleted)
    );

    // Refactoring safety
    println!("\n=== Refactoring Benefits ===\n");
    println!("Rename enum variant:");
    println!("  - IDE renames all usages automatically");
    println!("  - Compiler catches any missed spots");
    println!("  - No runtime surprises from missed strings\n");

    println!("Add new event:");
    println!("  - Add variant to enum");
    println!("  - Compiler shows everywhere you need to handle it");
    println!("  - Exhaustive match checking prevents bugs");

    println!("\n✓ Type safety complete!");
}