zrx_store/store.rs
1// Copyright (c) 2025-2026 Zensical and contributors
2
3// SPDX-License-Identifier: MIT
4// All contributions are certified under the DCO
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Store traits.
27
28use std::borrow::Borrow;
29use std::ops::RangeBounds;
30
31pub mod adapter;
32pub mod behavior;
33pub mod comparator;
34pub mod decorator;
35pub mod key;
36
37use key::Key;
38
39// ----------------------------------------------------------------------------
40// Traits
41// ----------------------------------------------------------------------------
42
43/// Immutable store.
44///
45/// This trait defines the required methods for an immutable key-value store,
46/// abstracting over implementations like [`HashMap`][] and [`BTreeMap`][]. It
47/// forms the foundation for a set of further traits that define complementary
48/// capabilities for stores, like [`StoreMut`] and [`StoreIterable`].
49///
50/// There are several of those traits, all of which can be composed in trait
51/// bounds to require specific store capabilities. These are:
52///
53/// - [`StoreMut`]: Mutable store
54/// - [`StoreMutRef`]: Mutable store that can return mutable references
55/// - [`StoreIterable`]: Immutable store that is iterable
56/// - [`StoreIterableMut`]: Mutable store that is iterable
57/// - [`StoreKeys`]: Immutable store that is iterable over its keys
58/// - [`StoreValues`]: Immutable store that is iterable over its values
59/// - [`StoreRange`]: Immutable store that is iterable over a range
60///
61/// This trait is implemented for [`HashMap`][] and [`BTreeMap`][], as well as
62/// all of the store [`decorators`][] that allow to wrap stores with additional
63/// capabilities. Note that stores are not thread-safe, so they can't be shared
64/// among worker threads.
65///
66/// All methods deliberately have [`Infallible`] signatures, as stores must be
67/// fast and reliable, and should never fail under normal circumstances. Stores
68/// should not need to serialize data, write to the filesystem, or send data
69/// over the network. They should only have in-memory representations.
70///
71/// [`decorators`]: crate::store::decorator
72/// [`BTreeMap`]: std::collections::BTreeMap
73/// [`HashMap`]: std::collections::HashMap
74/// [`Infallible`]: std::convert::Infallible
75///
76/// # Examples
77///
78/// ```
79/// use std::collections::HashMap;
80/// use zrx_store::StoreMut;
81///
82/// // Create store and initial state
83/// let mut store = HashMap::new();
84/// store.insert("key", 42);
85///
86/// // Obtain reference to value
87/// let value = store.get(&"key");
88/// assert_eq!(value, Some(&42));
89/// ```
90pub trait Store<K, V>
91where
92 K: Key,
93{
94 /// Returns a reference to the value identified by the key.
95 fn get<Q>(&self, key: &Q) -> Option<&V>
96 where
97 K: Borrow<Q>,
98 Q: Key;
99
100 /// Returns whether the store contains the key.
101 fn contains_key<Q>(&self, key: &Q) -> bool
102 where
103 K: Borrow<Q>,
104 Q: Key;
105
106 /// Returns the number of items in the store.
107 fn len(&self) -> usize;
108
109 /// Returns whether the store is empty.
110 #[inline]
111 fn is_empty(&self) -> bool {
112 self.len() == 0
113 }
114}
115
116/// Mutable store.
117///
118/// This trait extends [`Store`], requiring further additional mutable methods
119/// which can be used to alter the store, like inserting and removing items.
120///
121/// # Examples
122///
123/// ```
124/// use std::collections::HashMap;
125/// use zrx_store::StoreMut;
126///
127/// // Create store and initial state
128/// let mut store = HashMap::new();
129/// store.insert("key", 42);
130///
131/// // Remove value from store
132/// let value = store.remove(&"key");
133/// assert_eq!(value, Some(42));
134/// ```
135pub trait StoreMut<K, V>: Store<K, V>
136where
137 K: Key,
138{
139 /// Inserts the value identified by the key.
140 fn insert(&mut self, key: K, value: V) -> Option<V>;
141
142 /// Inserts the value identified by the key if it changed.
143 fn insert_if_changed(&mut self, key: &K, value: &V) -> bool
144 where
145 V: Clone + Eq,
146 {
147 (self.get(key) != Some(value))
148 .then(|| self.insert(key.clone(), value.clone()))
149 .is_some()
150 }
151
152 /// Removes the value identified by the key.
153 fn remove<Q>(&mut self, key: &Q) -> Option<V>
154 where
155 K: Borrow<Q>,
156 Q: Key;
157
158 /// Removes the value identified by the key and returns both.
159 fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
160 where
161 K: Borrow<Q>,
162 Q: Key;
163
164 /// Clears the store, removing all items.
165 fn clear(&mut self);
166}
167
168/// Mutable store that can return mutable references.
169///
170/// This trait extends [`StoreMut`], adding the possibility to obtain mutable
171/// references as a requirement, so values can be mutated in-place.
172///
173/// # Examples
174///
175/// ```
176/// use std::collections::HashMap;
177/// use zrx_store::{StoreMut, StoreMutRef};
178///
179/// // Create store and initial state
180/// let mut store = HashMap::new();
181/// store.insert("key", 42);
182///
183/// // Obtain mutable reference to value
184/// let mut value = store.get_mut(&"key");
185/// assert_eq!(value, Some(&mut 42));
186/// ```
187pub trait StoreMutRef<K, V>: Store<K, V>
188where
189 K: Key,
190{
191 /// Returns a mutable reference to the value identified by the key.
192 fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
193 where
194 K: Borrow<Q>,
195 Q: Key;
196
197 /// Returns a mutable reference to the value or creates the default.
198 fn get_or_insert_default(&mut self, key: &K) -> &mut V
199 where
200 V: Default;
201}
202
203/// Immutable store that is iterable.
204///
205/// This trait extends [`Store`], adding iteration capabilities as a further
206/// requirement, so a store can enumerate its items.
207///
208/// # Examples
209///
210/// ```
211/// use std::collections::HashMap;
212/// use zrx_store::{StoreIterable, StoreMut};
213///
214/// // Create store and initial state
215/// let mut store = HashMap::new();
216/// store.insert("key", 42);
217///
218/// // Create iterator over the store
219/// for (key, value) in store.iter() {
220/// println!("{key}: {value}");
221/// }
222/// ```
223pub trait StoreIterable<K, V>: Store<K, V>
224where
225 K: Key,
226{
227 type Iter<'a>: Iterator<Item = (&'a K, &'a V)>
228 where
229 Self: 'a,
230 K: 'a,
231 V: 'a;
232
233 /// Creates an iterator over the items of a store.
234 fn iter(&self) -> Self::Iter<'_>;
235}
236
237/// Mutable store that is iterable.
238///
239/// This trait extends [`StoreMut`], adding mutable iteration capabilities as a
240/// requirement, so a store can enumerate its items mutably.
241///
242/// # Examples
243///
244/// ```
245/// use std::collections::HashMap;
246/// use zrx_store::{StoreIterableMut, StoreMut};
247///
248/// // Create store and initial state
249/// let mut store = HashMap::new();
250/// store.insert("key", 42);
251///
252/// // Create iterator over the store
253/// for (key, value) in store.iter_mut() {
254/// println!("{key}: {value}");
255/// }
256/// ```
257pub trait StoreIterableMut<K, V>: StoreMut<K, V>
258where
259 K: Key,
260{
261 type IterMut<'a>: Iterator<Item = (&'a K, &'a mut V)>
262 where
263 Self: 'a,
264 K: 'a,
265 V: 'a;
266
267 /// Creates a mutable iterator over the items of a store.
268 fn iter_mut(&mut self) -> Self::IterMut<'_>;
269}
270
271/// Immutable store that is iterable over its keys.
272///
273/// This trait extends [`Store`], adding key iteration capabilities as a
274/// requirement, so a store can enumerate its keys.
275///
276/// # Examples
277///
278/// ```
279/// use std::collections::HashMap;
280/// use zrx_store::{StoreKeys, StoreMut};
281///
282/// // Create store and initial state
283/// let mut store = HashMap::new();
284/// store.insert("key", 42);
285///
286/// // Create iterator over the store
287/// for key in store.keys() {
288/// println!("{key}");
289/// }
290/// ```
291pub trait StoreKeys<K, V>: Store<K, V>
292where
293 K: Key,
294{
295 type Keys<'a>: Iterator<Item = &'a K>
296 where
297 Self: 'a,
298 K: 'a;
299
300 /// Creates an iterator over the keys of a store.
301 fn keys(&self) -> Self::Keys<'_>;
302}
303
304/// Immutable store that is iterable over its values.
305///
306/// This trait extends [`Store`], adding value iteration capabilities as a
307/// requirement, so a store can enumerate its values.
308///
309/// # Examples
310///
311/// ```
312/// use std::collections::HashMap;
313/// use zrx_store::{StoreMut, StoreValues};
314///
315/// // Create store and initial state
316/// let mut store = HashMap::new();
317/// store.insert("key", 42);
318///
319/// // Create iterator over the store
320/// for value in store.values() {
321/// println!("{value}");
322/// }
323/// ```
324pub trait StoreValues<K, V>: Store<K, V>
325where
326 K: Key,
327{
328 type Values<'a>: Iterator<Item = &'a V>
329 where
330 Self: 'a,
331 V: 'a;
332
333 /// Creates an iterator over the values of a store.
334 fn values(&self) -> Self::Values<'_>;
335}
336
337/// Immutable store that is iterable over a range.
338///
339/// This trait extends [`Store`], adding iteration capabilities as a further
340/// requirement, so a store can enumerate its items over a given range.
341///
342/// # Examples
343///
344/// ```
345/// use std::collections::BTreeMap;
346/// use zrx_store::{StoreMut, StoreRange};
347///
348/// // Create store and initial state
349/// let mut store = BTreeMap::new();
350/// store.insert("a", 42);
351/// store.insert("b", 84);
352///
353/// // Create iterator over the store
354/// for (key, value) in store.range("b"..) {
355/// println!("{key}: {value}");
356/// }
357/// ```
358pub trait StoreRange<K, V>: Store<K, V>
359where
360 K: Key,
361{
362 type Range<'a>: Iterator<Item = (&'a K, &'a V)>
363 where
364 Self: 'a,
365 K: 'a,
366 V: 'a;
367
368 /// Creates an iterator over a range of items in a store.
369 fn range<R>(&self, range: R) -> Self::Range<'_>
370 where
371 R: RangeBounds<K>;
372}
373
374// ----------------------------------------------------------------------------
375
376/// Creates a store from an iterator.
377pub trait StoreFromIterator<K, V>: FromIterator<(K, V)> {}
378
379/// Creates an iterator over the items of a store.
380pub trait StoreIntoIterator<K, V>: IntoIterator<Item = (K, V)> {}
381
382// ----------------------------------------------------------------------------
383// Blanket implementations
384// ----------------------------------------------------------------------------
385
386#[rustfmt::skip]
387impl<K, V, T> StoreFromIterator<K, V> for T
388where
389 T: FromIterator<(K, V)> {}
390
391#[rustfmt::skip]
392impl<K, V, T> StoreIntoIterator<K, V> for T
393where
394 T: IntoIterator<Item = (K, V)> {}