timed_map/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
//! Lightweight map implementation that supports expiring entries and fully
//! compatible with both `std` and `no_std` environments.
//!
//! `TimedMap` allows storing key-value pairs with optional expiration times. Expiration is
//! handled by an implementation of the `Clock` trait, which abstracts time handling for
//! `no_std` environments.
//!
//! When `std` feature is enabled (which is the default case), `Clock` trait is handled
//! automatically from the crate internals with `std::time::SystemTime`.
//!
//! ### Basic Usage:
//!
//! #### In `std` environments:
//! ```rs
//! use timed_map::{TimedMap, StdClock};
//! use std::time::Duration;
//!
//! let mut map: TimedMap<StdClock, _, _> = TimedMap::new();
//!
//! map.insert_expirable(1, "expirable value", Duration::from_secs(60));
//! assert_eq!(map.get(&1), Some(&"expirable value"));
//! assert!(map.get_remaining_duration(&1).is_some());
//!
//! map.insert_constant(2, "constant value");
//! assert_eq!(map.get(&2), Some(&"constant value"));
//! assert!(map.get_remaining_duration(&2).is_none());
//! ```
//!
//! #### In `no_std` environments:
//! ```rs
//! use core::time::Duration;
//! use timed_map::{Clock, TimedMap};
//!
//! struct CustomClock;
//!
//! impl Clock for CustomClock {
//! fn elapsed_seconds_since_creation(&self) -> u64 {
//! // Hardware-specific implementation to measure the elapsed time.
//! 0 // placeholder
//! }
//! }
//!
//! let clock = CustomClock;
//! let mut map = TimedMap::new(clock);
//!
//! map.insert_expirable(1, "expirable value", Duration::from_secs(60));
//! assert_eq!(map.get(&1), Some(&"expirable value"));
//! assert!(map.get_remaining_duration(&1).is_some());
//!
//! map.insert_constant(2, "constant value");
//! assert_eq!(map.get(&2), Some(&"constant value"));
//! assert!(map.get_remaining_duration(&2).is_none());
//! ```
//!
//! ### Advanced Usage & Tuning:
//!
//! #### Customizing the Internal Map
//!
//! By default, `TimedMap` uses `BTreeMap` to store data, but you can switch to `FxHashMap` or `HashMap`.
//!
//! This is only available on `std` environments.
//!
//! ```rs
//! use timed_map::{MapKind, StdClock, TimedMap};
//!
//! let mut map: TimedMap<StdClock, _, _> = TimedMap::new_with_map_kind(MapKind::FxHashMap);
//! ```
//!
//! #### Manual Expiration Control
//!
//! To have fully control over expired entries, use the `*_unchecked` functions and `drop_expired_entries` to handle expiration manually.
//! This can boost performance by running expiration logic only when it's necessary to maximize the performance.
//!
//! ```rs
//! let mut map: TimedMap<StdClock, _, _> = TimedMap::new();
//!
//! map.insert_expirable_unchecked(1, "expirable value", Duration::from_secs(60));
//! assert_eq!(map.get_unchecked(&1), Some(&"expirable value"));
//!
//! map.insert_constant_unchecked(2, "constant value");
//! assert_eq!(map.get_unchecked(&2), Some(&"constant value"));
//!
//! map.drop_expired_entries();
//! ```
//!
//! #### Setting Expiration Check Frequency
//!
//! In cases where inserts are frequent, `expiration_tick_cap` can be set to control how often expired entries are removed. For instance,
//! if there are 100 inserts per second, setting `expiration_tick_cap` to 100 will trigger the expiration check every 100 inserts which will
//! reduce the expiration logic overhead significantly.
//!
//! ```rs
//! use timed_map::{TimedMap, StdClock};
//!
//! let mut map: TimedMap<StdClock, _, _> = TimedMap::new().expiration_tick_cap(500);
//! ```
#![no_std]
mod clock;
mod entry;
mod map;
macro_rules! cfg_std_feature {
($($item:item)*) => {
$(
#[cfg(feature = "std")]
$item
)*
};
}
macro_rules! cfg_not_std_feature {
($($item:item)*) => {
$(
#[cfg(not(feature = "std"))]
$item
)*
};
}
cfg_std_feature! {
extern crate std;
use std::marker::PhantomData;
use std::time::Duration;
use std::collections::{BTreeMap, HashMap, BTreeSet};
use std::hash::Hash;
use std::vec::Vec;
use clock::Clock;
#[cfg(not(feature = "wasm"))]
use std::time::Instant;
#[cfg(feature = "wasm")]
use web_time::Instant;
pub use clock::StdClock;
pub use map::MapKind;
}
cfg_not_std_feature! {
extern crate alloc;
use core::time::Duration;
use alloc::vec::Vec;
use alloc::collections::{BTreeMap, BTreeSet};
pub use clock::Clock;
}
use entry::EntryStatus;
use entry::ExpirableEntry;
#[cfg(all(feature = "std", feature = "rustc-hash"))]
use rustc_hash::FxHashMap;
pub use map::TimedMap;