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