rate-guard 0.1.0

Thread-safe rate limiting library with multiple algorithms and Duration-based configuration
Documentation
//! Time source abstraction for rate limiting operations.
//!
//! This module provides the TimeSource trait which abstracts different time
//! sources while maintaining a clean separation of concerns. TimeSource is
//! responsible for providing elapsed Duration since some starting point,
//! while Precision handles the conversion to tick values.
//!
//! # Design Philosophy
//!
//! The TimeSource abstraction enables:
//! - **Testability**: MockTimeSource for deterministic testing
//! - **Flexibility**: Support for different time sources (std::time, tokio, etc.)
//! - **Isolation**: Clean separation between time acquisition and precision conversion
//! - **Performance**: Zero-cost abstractions through static dispatch
//!
//! # Time Model
//!
//! TimeSource implementations follow an "elapsed time" model similar to
//! `std::time::Instant::elapsed()`. Each TimeSource has an implicit starting
//! point and returns the Duration elapsed since that point.
//!
//! This model ensures:
//! - Monotonic time progression
//! - Consistent behavior across different sources
//! - Natural integration with Duration-based APIs
//!
//! # Examples
//!
//! ## Basic Usage
//!
//! ```rust
//! use rate_guard::time_source::{TimeSource, MockTimeSource};
//! use std::time::Duration;
//!
//! let time_source = MockTimeSource::new();
//! let elapsed = time_source.now();
//! assert_eq!(elapsed, Duration::ZERO);
//!
//! time_source.advance(Duration::from_millis(100));
//! let elapsed = time_source.now();
//! assert_eq!(elapsed, Duration::from_millis(100));
//! ```
//!
//! ## Integration with Precision
//!
//! ```rust
//! use rate_guard::time_source::{TimeSource, MockTimeSource};
//! use rate_guard::precision::{Precision, Millis};
//! use std::time::Duration;
//!
//! let time_source = MockTimeSource::new();
//! time_source.advance(Duration::from_millis(250));
//!
//! let elapsed = time_source.now();
//! let ticks = Millis::to_ticks(elapsed);
//! assert_eq!(ticks, 250);
//! ```

use std::time::Duration;

pub mod mock;
pub use mock::MockTimeSource;

#[cfg(feature = "std-time")]
pub mod std_time;
#[cfg(feature = "std-time")]
pub use std_time::StdTimeSource;

#[cfg(feature = "tokio-time")]
pub mod tokio_time;
#[cfg(feature = "tokio-time")]
pub use tokio_time::TokioTimeSource;

/// Trait for providing elapsed time since a starting point.
///
/// TimeSource implementations abstract different sources of time while
/// maintaining consistent "elapsed time" semantics. Each implementation
/// has an implicit starting point and returns the Duration elapsed since
/// that point.
///
/// # Contract
///
/// Implementations must guarantee:
/// - **Monotonicity**: `now()` never decreases between calls
/// - **Zero start**: The first call to `now()` should return `Duration::ZERO`
///   or close to it
/// - **Consistency**: Multiple calls without time progression return the same value
/// - **Reasonable precision**: Should provide precision appropriate for the use case
///
/// # Performance Requirements
///
/// - Methods should be marked `#[inline(always)]` when possible
/// - Implementations should minimize allocation and system calls
/// - The abstraction should compile to efficient machine code
///
/// # Examples
///
/// ## Implementing a Custom TimeSource
///
/// ```rust
/// use rate_guard::time_source::TimeSource;
/// use std::time::{Duration, Instant};
///
/// struct CustomTimeSource {
///     start: Instant,
/// }
///
/// impl CustomTimeSource {
///     fn new() -> Self {
///         Self {
///             start: Instant::now(),
///         }
///     }
/// }
///
/// impl TimeSource for CustomTimeSource {
///     fn now(&self) -> Duration {
///         self.start.elapsed()
///     }
/// }
/// ```
///
/// ## Usage in Rate Limiting
///
/// ```rust
/// use rate_guard::time_source::{TimeSource, MockTimeSource};
/// use rate_guard::precision::{Precision, Millis};
/// use rate_guard::types::Uint;
/// use std::time::Duration;
///
/// fn get_current_ticks<T: TimeSource, P: Precision>(time_source: &T) -> Uint {
///     let elapsed = time_source.now();
///     P::to_ticks(elapsed)
/// }
///
/// let time_source = MockTimeSource::new();
/// time_source.advance(Duration::from_millis(500));
///
/// let ticks = get_current_ticks::<_, Millis>(&time_source);
/// assert_eq!(ticks, 500);
/// ```
pub trait TimeSource {
    /// Returns the elapsed Duration since this TimeSource's starting point.
    ///
    /// This method should return a monotonically increasing Duration that
    /// represents the time elapsed since some fixed starting point. The
    /// starting point is implementation-defined but should remain consistent
    /// for the lifetime of the TimeSource instance.
    ///
    /// # Returns
    ///
    /// A Duration representing elapsed time since the starting point.
    /// The first call should return `Duration::ZERO` or very close to it.
    ///
    /// # Guarantees
    ///
    /// - **Monotonic**: Each call returns a value >= the previous call
    /// - **Consistent**: Multiple calls without time progression return the same value
    /// - **Bounded**: The returned Duration should not exceed reasonable limits
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rate_guard::time_source::{TimeSource, MockTimeSource};
    /// use std::time::Duration;
    ///
    /// let time_source = MockTimeSource::new();
    ///
    /// let t1 = time_source.now();
    /// assert_eq!(t1, Duration::ZERO);
    ///
    /// time_source.advance(Duration::from_millis(100));
    /// let t2 = time_source.now();
    /// assert_eq!(t2, Duration::from_millis(100));
    ///
    /// // Monotonicity guarantee
    /// assert!(t2 >= t1);
    /// ```
    fn now(&self) -> Duration;
}