Skip to main content

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 collection;
34pub mod comparator;
35pub mod decorator;
36pub mod item;
37
38use comparator::Comparator;
39use item::{Key, Value};
40
41// ----------------------------------------------------------------------------
42// Traits
43// ----------------------------------------------------------------------------
44
45/// Immutable store.
46///
47/// This trait defines the required methods for an immutable key-value store,
48/// abstracting over implementations like [`HashMap`][] and [`BTreeMap`][]. It
49/// forms the foundation for a set of further traits that define complementary
50/// capabilities for stores, like [`StoreMut`] and [`StoreIterable`].
51///
52/// There are several of those traits, all of which can be composed in trait
53/// bounds to require specific store capabilities. These are:
54///
55/// - [`StoreMut`]: Mutable store
56/// - [`StoreMutRef`]: Mutable store that can return mutable references
57/// - [`StoreIterable`]: Immutable store that is iterable
58/// - [`StoreIterableMut`]: Mutable store that is iterable
59/// - [`StoreKeys`]: Immutable store that is iterable over its keys
60/// - [`StoreValues`]: Immutable store that is iterable over its values
61/// - [`StoreRange`]: Immutable store that is iterable over a range
62///
63/// This trait is implemented for [`HashMap`][] and [`BTreeMap`][], as well as
64/// all of the store [`decorators`][] that allow to wrap stores with additional
65/// capabilities. Note that stores are not thread-safe, so they can't be shared
66/// among worker threads.
67///
68/// All methods deliberately have [`Infallible`] signatures, as stores must be
69/// fast and reliable, and should never fail under normal circumstances. Stores
70/// should not need to serialize data, write to the filesystem, or send data
71/// over the network. They should only have in-memory representations.
72///
73/// [`decorators`]: crate::store::decorator
74/// [`BTreeMap`]: std::collections::BTreeMap
75/// [`HashMap`]: std::collections::HashMap
76/// [`Infallible`]: std::convert::Infallible
77///
78/// # Examples
79///
80/// ```
81/// use std::collections::HashMap;
82/// use zrx_store::StoreMut;
83///
84/// // Create store and initial state
85/// let mut store = HashMap::new();
86/// store.insert("key", 42);
87///
88/// // Obtain reference to value
89/// let value = store.get(&"key");
90/// assert_eq!(value, Some(&42));
91/// ```
92pub trait Store<K, V>
93where
94    K: Key,
95{
96    /// Returns a reference to the value identified by the key.
97    fn get<Q>(&self, key: &Q) -> Option<&V>
98    where
99        K: Borrow<Q>,
100        Q: Key;
101
102    /// Returns whether the store contains the key.
103    fn contains_key<Q>(&self, key: &Q) -> bool
104    where
105        K: Borrow<Q>,
106        Q: Key;
107
108    /// Returns the number of items in the store.
109    fn len(&self) -> usize;
110
111    /// Returns whether the store is empty.
112    #[inline]
113    fn is_empty(&self) -> bool {
114        self.len() == 0
115    }
116}
117
118/// Mutable store.
119///
120/// This trait extends [`Store`], requiring further additional mutable methods
121/// which can be used to alter the store, like inserting and removing items.
122///
123/// # Examples
124///
125/// ```
126/// use std::collections::HashMap;
127/// use zrx_store::StoreMut;
128///
129/// // Create store and initial state
130/// let mut store = HashMap::new();
131/// store.insert("key", 42);
132///
133/// // Remove value from store
134/// let value = store.remove(&"key");
135/// assert_eq!(value, Some(42));
136/// ```
137pub trait StoreMut<K, V>: Store<K, V>
138where
139    K: Key,
140{
141    /// Inserts the value identified by the key.
142    fn insert(&mut self, key: K, value: V) -> Option<V>;
143
144    /// Inserts the value identified by the key if it changed.
145    fn insert_if_changed(&mut self, key: &K, value: &V) -> bool
146    where
147        V: Clone + Eq,
148    {
149        (self.get(key) != Some(value))
150            .then(|| self.insert(key.clone(), value.clone()))
151            .is_some()
152    }
153
154    /// Removes the value identified by the key.
155    fn remove<Q>(&mut self, key: &Q) -> Option<V>
156    where
157        K: Borrow<Q>,
158        Q: Key;
159
160    /// Removes the value identified by the key and returns both.
161    fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
162    where
163        K: Borrow<Q>,
164        Q: Key;
165
166    /// Clears the store, removing all items.
167    fn clear(&mut self);
168}
169
170/// Mutable store that can return mutable references.
171///
172/// This trait extends [`StoreMut`], adding the possibility to obtain mutable
173/// references as a requirement, so values can be mutated in-place.
174///
175/// # Examples
176///
177/// ```
178/// use std::collections::HashMap;
179/// use zrx_store::{StoreMut, StoreMutRef};
180///
181/// // Create store and initial state
182/// let mut store = HashMap::new();
183/// store.insert("key", 42);
184///
185/// // Obtain mutable reference to value
186/// let mut value = store.get_mut(&"key");
187/// assert_eq!(value, Some(&mut 42));
188/// ```
189pub trait StoreMutRef<K, V>: Store<K, V>
190where
191    K: Key,
192{
193    /// Returns a mutable reference to the value identified by the key.
194    fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
195    where
196        K: Borrow<Q>,
197        Q: Key;
198
199    /// Returns a mutable reference to the value or creates the default.
200    fn get_or_insert_default(&mut self, key: &K) -> &mut V
201    where
202        V: Default;
203}
204
205/// Immutable store that is iterable.
206///
207/// This trait extends [`Store`], adding iteration capabilities as a further
208/// requirement, so a store can enumerate its items.
209///
210/// # Examples
211///
212/// ```
213/// use std::collections::HashMap;
214/// use zrx_store::{StoreIterable, StoreMut};
215///
216/// // Create store and initial state
217/// let mut store = HashMap::new();
218/// store.insert("key", 42);
219///
220/// // Create iterator over the store
221/// for (key, value) in store.iter() {
222///     println!("{key}: {value}");
223/// }
224/// ```
225pub trait StoreIterable<K, V>: Store<K, V>
226where
227    K: Key,
228    V: Value,
229{
230    type Iter<'a>: Iterator<Item = (&'a K, &'a V)>
231    where
232        Self: 'a;
233
234    /// Creates an iterator over the items of the store.
235    fn iter(&self) -> Self::Iter<'_>;
236}
237
238/// Mutable store that is iterable.
239///
240/// This trait extends [`StoreMut`], adding mutable iteration capabilities as a
241/// requirement, so a store can enumerate its items mutably.
242///
243/// # Examples
244///
245/// ```
246/// use std::collections::HashMap;
247/// use zrx_store::{StoreIterableMut, StoreMut};
248///
249/// // Create store and initial state
250/// let mut store = HashMap::new();
251/// store.insert("key", 42);
252///
253/// // Create iterator over the store
254/// for (key, value) in store.iter_mut() {
255///     println!("{key}: {value}");
256/// }
257/// ```
258pub trait StoreIterableMut<K, V>: StoreMut<K, V>
259where
260    K: Key,
261    V: Value,
262{
263    type IterMut<'a>: Iterator<Item = (&'a K, &'a mut V)>
264    where
265        Self: 'a;
266
267    /// Creates a mutable iterator over the items of the 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
299    /// Creates an iterator over the keys of the store.
300    fn keys(&self) -> Self::Keys<'_>;
301}
302
303/// Immutable store that is iterable over its values.
304///
305/// This trait extends [`Store`], adding value iteration capabilities as a
306/// requirement, so a store can enumerate its values.
307///
308/// # Examples
309///
310/// ```
311/// use std::collections::HashMap;
312/// use zrx_store::{StoreMut, StoreValues};
313///
314/// // Create store and initial state
315/// let mut store = HashMap::new();
316/// store.insert("key", 42);
317///
318/// // Create iterator over the store
319/// for value in store.values() {
320///     println!("{value}");
321/// }
322/// ```
323pub trait StoreValues<K, V>: Store<K, V>
324where
325    K: Key,
326    V: Value,
327{
328    type Values<'a>: Iterator<Item = &'a V>
329    where
330        Self: 'a;
331
332    /// Creates an iterator over the values of the store.
333    fn values(&self) -> Self::Values<'_>;
334}
335
336/// Immutable store that is iterable over a range.
337///
338/// This trait extends [`Store`], adding iteration capabilities as a further
339/// requirement, so a store can enumerate its items over a given range.
340///
341/// # Examples
342///
343/// ```
344/// use std::collections::BTreeMap;
345/// use zrx_store::{StoreMut, StoreRange};
346///
347/// // Create store and initial state
348/// let mut store = BTreeMap::new();
349/// store.insert("a", 42);
350/// store.insert("b", 84);
351///
352/// // Create iterator over the store
353/// for (key, value) in store.range("b"..) {
354///     println!("{key}: {value}");
355/// }
356/// ```
357pub trait StoreRange<K, V>: Store<K, V>
358where
359    K: Key,
360    V: Value,
361{
362    type Range<'a>: Iterator<Item = (&'a K, &'a V)>
363    where
364        Self: 'a;
365
366    /// Creates an iterator over a range of items of the store.
367    fn range<R>(&self, range: R) -> Self::Range<'_>
368    where
369        R: RangeBounds<K>;
370}
371
372// ----------------------------------------------------------------------------
373
374/// Creates a store with a comparator.
375///
376/// This trait extends [`Store`], adding the capability to create a store with
377/// a custom comparator, allowing to customize the ordering of values.
378///
379/// # Examples
380///
381/// ```
382/// use std::collections::HashMap;
383/// use zrx_store::comparator::Descending;
384/// use zrx_store::decorator::Ordered;
385/// use zrx_store::{StoreMut, StoreWithComparator};
386///
387/// // Create store
388/// let mut store: Ordered::<_, _, HashMap<_, _>, _> =
389///     Ordered::with_comparator(Descending);
390///
391/// // Insert value
392/// store.insert("key", 42);
393/// ```
394pub trait StoreWithComparator<K, V, C>: Store<K, V>
395where
396    K: Key,
397    C: Comparator<V>,
398{
399    /// Creates a store with the given comparator.
400    fn with_comparator(comparator: C) -> Self;
401}
402
403// ----------------------------------------------------------------------------
404
405/// Creates a store from an iterator.
406pub trait StoreFromIterator<K, V>: FromIterator<(K, V)> {}
407
408/// Creates an iterator over the items of the store.
409pub trait StoreIntoIterator<K, V>: IntoIterator<Item = (K, V)> {}
410
411// ----------------------------------------------------------------------------
412// Blanket implementations
413// ----------------------------------------------------------------------------
414
415#[rustfmt::skip]
416impl<K, V, T> StoreFromIterator<K, V> for T
417where
418    T: FromIterator<(K, V)> {}
419
420#[rustfmt::skip]
421impl<K, V, T> StoreIntoIterator<K, V> for T
422where
423    T: IntoIterator<Item = (K, V)> {}