Skip to main content

ic_storage/adapter/
iteration.rs

1//! Owned entries and iterator views over the copied ICSS engine.
2use super::{
3    Memory, Storable,
4    bridge::{Backing, Codec},
5    error::Result,
6};
7use crate::{DefaultMemoryImpl, RuntimeMemory, engine};
8use std::{borrow::Cow, marker::PhantomData};
9
10///
11/// `MapEntry`
12///
13/// An owned key and encoded value from an ordered scan. Decoding failures trap.
14///
15pub struct MapEntry<K, V> {
16    key: K,
17    bytes: Vec<u8>,
18    value: PhantomData<V>,
19}
20impl<K, V: Storable> MapEntry<K, V> {
21    /// Borrow the decoded key.
22    pub const fn key(&self) -> &K {
23        &self.key
24    }
25    /// Decode the value. Malformed stored bytes trap.
26    /// # Errors
27    /// Engine failures trap instead of returning an ordinary error.
28    pub fn value(&self) -> Result<V> {
29        Ok(<Codec<V> as engine::Storable>::from_bytes(Cow::Borrowed(&self.bytes)).0)
30    }
31    /// Consume the entry and decode its value.
32    /// # Errors
33    /// Engine failures trap instead of returning an ordinary error.
34    pub fn into_pair(self) -> Result<(K, V)> {
35        Ok((
36            self.key,
37            <Codec<V> as engine::Storable>::from_bytes(Cow::Owned(self.bytes)).0,
38        ))
39    }
40    /// Consume only the key without decoding its value.
41    pub fn into_key(self) -> K {
42        self.key
43    }
44    /// Consume and decode only the value.
45    /// # Errors
46    /// Engine failures trap instead of returning an ordinary error.
47    pub fn into_value(self) -> Result<V> {
48        Ok(<Codec<V> as engine::Storable>::from_bytes(Cow::Owned(self.bytes)).0)
49    }
50}
51///
52/// `MapIter`
53///
54/// Bidirectional ICSS traversal retaining its governed map borrow.
55///
56pub struct MapIter<'a, K: Storable + Ord + Clone, V: Storable, M: Memory = DefaultMemoryImpl>(
57    pub(super) engine::btreemap::Iter<'a, Codec<K>, Codec<V>, Backing<RuntimeMemory<M>>>,
58);
59fn entry<K: Storable + Ord + Clone, V: Storable, M: Memory>(
60    entry: engine::btreemap::LazyEntry<'_, Codec<K>, Codec<V>, Backing<RuntimeMemory<M>>>,
61) -> MapEntry<K, V> {
62    let (key, bytes) = entry.into_raw();
63    MapEntry {
64        key: key.0,
65        bytes,
66        value: PhantomData,
67    }
68}
69impl<K: Storable + Ord + Clone, V: Storable, M: Memory> Iterator for MapIter<'_, K, V, M> {
70    type Item = Result<MapEntry<K, V>>;
71    fn next(&mut self) -> Option<Self::Item> {
72        self.0.next().map(|e| Ok(entry(e)))
73    }
74    fn nth(&mut self, n: usize) -> Option<Self::Item> {
75        self.0.nth(n).map(|e| Ok(entry(e)))
76    }
77    #[expect(
78        clippy::double_ended_iterator_last,
79        reason = "Delegate to the ICSS iterator unchanged for the initial engine baseline"
80    )]
81    fn last(self) -> Option<Self::Item> {
82        self.0.last().map(|e| Ok(entry(e)))
83    }
84    fn count(self) -> usize {
85        self.0.count()
86    }
87    fn size_hint(&self) -> (usize, Option<usize>) {
88        self.0.size_hint()
89    }
90}
91impl<K: Storable + Ord + Clone, V: Storable, M: Memory> DoubleEndedIterator
92    for MapIter<'_, K, V, M>
93{
94    fn next_back(&mut self) -> Option<Self::Item> {
95        self.0.next_back().map(|e| Ok(entry(e)))
96    }
97    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
98        self.0.nth_back(n).map(|e| Ok(entry(e)))
99    }
100}