rate-guard 0.1.0

Thread-safe rate limiting library with multiple algorithms and Duration-based configuration
Documentation
//! Standard library time source implementation using std::time::Instant.
//!
//! This module provides StdTimeSource, a TimeSource implementation that uses
//! std::time::Instant for real-time operation. It follows the "elapsed time"
//! model where time is measured relative to when the TimeSource was created.
//!
//! # Features
//!
//! - **Real Time**: Uses actual system time via std::time::Instant
//! - **Monotonic**: Guaranteed monotonic time progression
//! - **High Precision**: Nanosecond precision from std::time
//! - **Cross Platform**: Works on all platforms supported by std::time
//!
//! # Usage
//!
//! This implementation is only available when the `std-time` feature is enabled.
//! It's designed for production use where real system time is required.
//!
//! # Examples
//!
//! ## Basic Usage
//!
//! ```rust
//! use rate_guard::time_source::{TimeSource, StdTimeSource};
//! use std::time::Duration;
//!
//! let time_source = StdTimeSource::new();
//! let start = time_source.now();
//! 
//! // Some time passes...
//! std::thread::sleep(Duration::from_millis(100));
//! 
//! let elapsed = time_source.now();
//! assert!(elapsed >= start + Duration::from_millis(90)); // Allow some tolerance
//! ```
//!
//! ## Integration with Rate Limiters
//!
//! ```rust
//! use rate_guard::{Nanos, StdTimeSource, RateLimit};
//! use rate_guard::limits::TokenBucketBuilder;
//! use std::time::Duration;
//!
//! let bucket = TokenBucketBuilder::builder()
//!     .capacity(100)
//!     .refill_amount(10)
//!     .refill_every(Duration::from_millis(100))
//!     .with_time(StdTimeSource::new())
//!     .with_precision::<Nanos>()
//!     .build()
//!     .unwrap();
//!
//! // Use with real system time
//! match bucket.try_acquire(10) {
//!     Ok(()) => println!("Request allowed"),
//!     Err(e) => println!("Rate limited: {}", e),
//! }
//! ```

use std::time::{Duration, Instant};
use crate::time_source::TimeSource;

/// Standard library time source using std::time::Instant.
///
/// StdTimeSource provides real-time operation using std::time::Instant.
/// It maintains an internal starting point and returns the elapsed time
/// since that point, following the TimeSource "elapsed time" model.
///
/// # Characteristics
///
/// - **Monotonic**: Time never goes backward
/// - **High Precision**: Nanosecond precision from std::time
/// - **Real Time**: Uses actual system time
/// - **Thread Safe**: Safe to use across multiple threads
///
/// # Time Model
///
/// The time source captures a starting Instant when created and returns
/// the elapsed Duration since that point. This ensures:
/// - Consistent zero point across the lifetime of the time source
/// - Monotonic progression even across system clock adjustments
/// - Predictable behavior for rate limiting calculations
///
/// # Examples
///
/// ## Creating and Using
///
/// ```rust
/// use rate_guard::time_source::{TimeSource, StdTimeSource};
/// use std::time::Duration;
///
/// let time_source = StdTimeSource::new();
/// 
/// // Initially close to zero
/// let start = time_source.now();
/// assert!(start < Duration::from_millis(1));
///
/// // Time progresses naturally
/// std::thread::sleep(Duration::from_millis(50));
/// let later = time_source.now();
/// assert!(later >= Duration::from_millis(45)); // Allow tolerance
/// ```
///
/// ## Precision Demonstration
///
/// ```rust
/// use rate_guard::time_source::{TimeSource, StdTimeSource};
/// use rate_guard::precision::{Precision, Nanos, Millis};
///
/// let time_source = StdTimeSource::new();
/// std::thread::sleep(std::time::Duration::from_millis(10));
/// 
/// let elapsed = time_source.now();
/// let nanos = Nanos::to_ticks(elapsed);
/// let millis = Millis::to_ticks(elapsed);
/// 
/// println!("Elapsed: {} ns, {} ms", nanos, millis);
/// ```
#[derive(Debug, Clone)]
pub struct StdTimeSource {
    /// The starting instant for this time source.
    start: Instant,
}

impl StdTimeSource {
    /// Creates a new StdTimeSource with the current instant as the starting point.
    ///
    /// The starting point is captured immediately and used as the reference
    /// for all subsequent time measurements.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rate_guard::time_source::StdTimeSource;
    ///
    /// let time_source = StdTimeSource::new();
    /// // time_source.now() will return elapsed time from this moment
    /// ```
    #[inline(always)]
    pub fn new() -> Self {
        Self {
            start: Instant::now(),
        }
    }

    /// Returns the elapsed Duration since this time source was created.
    ///
    /// This is equivalent to calling the `now()` method from the TimeSource
    /// trait, but provided as a convenience method with a more descriptive name.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rate_guard::time_source::{TimeSource, StdTimeSource};
    /// use std::time::Duration;
    ///
    /// let time_source = StdTimeSource::new();
    /// std::thread::sleep(Duration::from_millis(10));
    /// 
    /// let elapsed = time_source.elapsed();
    /// assert!(elapsed >= Duration::from_millis(9)); // Allow tolerance
    /// 
    /// // elapsed() and now() should return very similar values
    /// let now_time = time_source.now();
    /// let elapsed_time = time_source.elapsed();
    /// 
    /// // They should be within a small tolerance (microseconds)
    /// let diff = if now_time > elapsed_time {
    ///     now_time - elapsed_time
    /// } else {
    ///     elapsed_time - now_time
    /// };
    /// assert!(diff < Duration::from_micros(100)); // Should be very close
    /// ```
    #[inline(always)]
    pub fn elapsed(&self) -> Duration {
        self.now()
    }

    /// Returns the starting instant for this time source.
    ///
    /// This method provides access to the internal starting point,
    /// which can be useful for debugging or advanced time calculations.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rate_guard::time_source::StdTimeSource;
    /// use std::time::Instant;
    ///
    /// let time_source = StdTimeSource::new();
    /// let start_instant = time_source.start_instant();
    /// 
    /// // The start instant should be very recent
    /// assert!(start_instant.elapsed().as_millis() < 100);
    /// ```
    #[inline(always)]
    pub fn start_instant(&self) -> Instant {
        self.start
    }
}

impl Default for StdTimeSource {
    /// Creates a new StdTimeSource with default settings.
    ///
    /// Equivalent to `StdTimeSource::new()`.
    #[inline(always)]
    fn default() -> Self {
        Self::new()
    }
}

impl TimeSource for StdTimeSource {
    /// Returns the elapsed Duration since this StdTimeSource was created.
    ///
    /// This method returns the time elapsed since the starting instant
    /// captured during construction. The returned Duration is guaranteed
    /// to be monotonic and will never decrease between calls.
    ///
    /// # Performance
    ///
    /// This method is marked `#[inline(always)]` to ensure optimal performance
    /// in high-frequency rate limiting scenarios.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rate_guard::time_source::{TimeSource, StdTimeSource};
    /// use std::time::Duration;
    ///
    /// let time_source = StdTimeSource::new();
    ///
    /// let t1 = time_source.now();
    /// std::thread::sleep(Duration::from_millis(10));
    /// let t2 = time_source.now();
    ///
    /// // Monotonic guarantee
    /// assert!(t2 >= t1);
    /// assert!(t2 - t1 >= Duration::from_millis(8)); // Allow tolerance
    /// ```
    #[inline(always)]
    fn now(&self) -> Duration {
        self.start.elapsed()
    }
}