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 map;
103
104macro_rules! cfg_std_feature {
105    ($($item:item)*) => {
106        $(
107            #[cfg(feature = "std")]
108            $item
109        )*
110    };
111}
112
113macro_rules! cfg_not_std_feature {
114    ($($item:item)*) => {
115        $(
116            #[cfg(not(feature = "std"))]
117            $item
118        )*
119    };
120}
121
122cfg_std_feature! {
123    extern crate std;
124
125    use std::time::Duration;
126    use std::collections::{BTreeMap, HashMap, BTreeSet};
127    use std::hash::Hash;
128    use std::vec::Vec;
129    use clock::{Clock, StdClock};
130
131    #[cfg(not(feature = "wasm"))]
132    use std::time::Instant;
133
134    #[cfg(feature = "wasm")]
135    use web_time::Instant;
136
137    pub use map::MapKind;
138}
139
140cfg_not_std_feature! {
141    extern crate alloc;
142
143    use core::time::Duration;
144    use alloc::vec::Vec;
145    use alloc::collections::{BTreeMap, BTreeSet};
146
147    pub use clock::Clock;
148}
149
150use entry::EntryStatus;
151use entry::ExpirableEntry;
152
153#[cfg(all(feature = "std", feature = "rustc-hash"))]
154use rustc_hash::FxHashMap;
155
156pub use map::TimedMap;