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