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
// Copyright (C) 2024 Christian Mauduit <ufoot@ufoot.org>

//! [HashLRU](https://gitlab.com/liberecofr/hashlru) is a LRU cache.
//!
//! It tries to follow the API exposed by a [standard Rust HashMap](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html)
//! while enforcing a limited memory footprint by limiting the number of keys using the LRU strategy, which is
//! a quite [common cache replacement policy]( https://en.wikipedia.org/wiki/Cache_replacement_policies).
//!
//! ![HashLRU icon](https://gitlab.com/liberecofr/hashlru/raw/main/hashlru.png)
//!
//! # Examples
//!
//! Feels like a hash map:
//!
//! ```
//! use hashlru::Cache;
//!
//! let mut cache = Cache::new(1000);
//!
//! cache.insert("my-key", 123);
//! assert_eq!(Some(&123), cache.get(&"my-key"));
//! ```
//!
//! Drops unused entries:
//!
//! ```
//! use hashlru::Cache;
//!
//! let mut cache = Cache::new(4);
//! cache.insert("key1", 10);
//! cache.insert("key2", 20);
//! cache.insert("key3", 30);
//! cache.insert("key4", 40);
//! cache.insert("key5", 50);
//! // key1 has been dropped, size is limited to 4
//! assert_eq!(Some(&"key2"), cache.lru());
//! assert_eq!(Some(&20), cache.get(&"key2"));
//! // getting key2 has made key3 the least recently used item
//! assert_eq!(Some(&"key3"), cache.lru());
//! assert_eq!(Some(&40), cache.get(&"key4"));
//! // getting key4 makes it the most recently used item
//! assert_eq!("[key3: 30, key5: 50, key2: 20, key4: 40]", format!("{}", cache));
//! ```
//!
//! More complex example:
//!
//! ```
//! use hashlru::Cache;
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Obj {
//!     name: String,
//!     scalar: usize,
//! }
//!
//! impl Obj {
//!     fn new(name: &str, scalar: usize) -> Self {
//!         Obj{name: name.to_string(), scalar}
//!     }
//! }
//!
//! #[derive(Debug, Eq, PartialEq, Hash, Clone)]
//! struct Key {
//!     x: i64,
//!     y: i64,
//! }
//!
//! impl Key {
//!     fn new(x: i64, y: i64) -> Self {
//!         Key{x, y}
//!     }
//! }
//!
//! let mut cache: Cache<Key, Obj> = Cache::new(2);
//! cache.insert(Key::new(1, 2), Obj::new("pim", 123));
//! cache.insert(Key::new(3, 9), Obj::new("pam", 456));
//! cache.insert(Key::new(-4, 0), Obj::new("pom", 789));
//! assert_eq!(2, cache.len());
//! cache.resize(10);
//! cache.insert(Key::new(22, 10), Obj::new("pem", 0));
//! assert_eq!(Some(&Key::new(22, 10)), cache.mru());
//! assert_eq!(Some(&Key::new(3, 9)), cache.lru());
//! assert_eq!(Some(&Obj::new("pom", 789)), cache.get(&Key::new(-4, 0)));
//! assert_eq!(Some(&Key::new(-4, 0)), cache.mru());
//! assert_eq!(Some(&Key::new(3, 9)), cache.lru());
//! assert_eq!(Some(&Obj::new("pam", 456)), cache.get(&Key::new(3, 9)));
//! assert_eq!(Some(&Key::new(3, 9)), cache.mru());
//! assert_eq!(Some(&Key::new(22, 10)), cache.lru());
//! ```
//!
//! Thread-safe cache:
//!
//! ```
//! use hashlru::SyncCache;
//! use std::thread;
//!
//! let cache: SyncCache<usize, usize> = SyncCache::new(50);
//!
//! let cache1 = cache.clone();
//! let handle1 = thread::spawn(move || cache1.insert(1,2));
//! let cache2 = cache.clone();
//! let handle2 = thread::spawn(move || cache2.insert(3,4));
//!
//! handle1.join().unwrap();
//! handle2.join().unwrap();
//!
//! assert_eq!(Some(2), cache.get(&1));
//! assert_eq!(Some(4), cache.get(&3));
//! ```

mod cache;
#[cfg(feature = "serde")]
mod custom_serde;
mod dump;
mod iter;
mod sync_cache;

pub use cache::*;
#[cfg(feature = "serde")]
pub use custom_serde::*;
pub use dump::*;
pub use iter::*;
pub use sync_cache::*;