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