ic_storage/adapter/
map.rs1use super::bridge::{self, Backing, Codec};
3use super::error::{CollectionError as Error, Result, ensure};
4use super::{MapIter, Memory, Storable};
5use crate::{DefaultMemoryImpl, RuntimeMemory};
6use std::ops::RangeBounds;
7
8pub struct StableBTreeMap<K: Storable + Ord + Clone, V: Storable, M: Memory = DefaultMemoryImpl> {
15 inner: bridge::Map<K, V, RuntimeMemory<M>>,
16}
17impl<K: Storable + Ord + Clone, V: Storable, M: Memory> StableBTreeMap<K, V, M> {
18 pub fn create(memory: RuntimeMemory<M>) -> Result<Self> {
22 ensure(memory.size() == 0, Error::NotEmpty)?;
23 Self::reset(memory)
24 }
25 pub fn reset(memory: RuntimeMemory<M>) -> Result<Self> {
29 bridge::reserve(&memory)?;
30 #[cfg(not(target_arch = "wasm32"))]
31 let _guard = memory.poison_on_unwind();
32 Ok(Self {
33 inner: bridge::Map::new(Backing(memory)),
34 })
35 }
36 pub fn load(memory: RuntimeMemory<M>) -> Result<Self> {
40 bridge::admit_map(&memory)?;
41 Ok(Self {
42 inner: bridge::Map::load(Backing(memory)),
43 })
44 }
45 pub fn clear(&mut self) -> Result<()> {
49 #[cfg(not(target_arch = "wasm32"))]
50 let _guard = self.inner.memory().0.poison_on_unwind();
51 self.inner.clear_new();
52 Ok(())
53 }
54 pub const fn set_node_cache_budget(&mut self, _bytes: usize) {
57 let _ = &self.inner;
58 }
59 pub fn reserve_pages(
61 self,
62 minimum: u64,
63 ) -> (Self, std::result::Result<(), crate::RuntimeGrowError>) {
64 let additional = minimum.saturating_sub(self.inner.memory().0.size());
65 let result = self.inner.memory().0.grow(additional).map(|_| ());
66 (self, result)
67 }
68 #[must_use]
70 pub fn allocated_pages(self) -> (Self, u64) {
71 let pages = self.inner.memory().0.size();
72 (self, pages)
73 }
74 pub fn insert(&mut self, key: K, value: V) -> Result<Option<V>> {
78 #[cfg(not(target_arch = "wasm32"))]
79 let _guard = self.inner.memory().0.poison_on_unwind();
80 Ok(self.inner.insert(Codec(key), Codec(value)).map(|v| v.0))
81 }
82 pub fn get(&self, key: &K) -> Result<Option<V>> {
86 Ok(self.inner.get(Codec::borrowed(key)).map(|v| v.0))
87 }
88 pub fn contains_key(&self, key: &K) -> Result<bool> {
92 Ok(self.inner.contains_key(Codec::borrowed(key)))
93 }
94 #[must_use]
96 pub const fn is_empty(&self) -> bool {
97 self.inner.is_empty()
98 }
99 #[must_use]
101 pub const fn len(&self) -> u64 {
102 self.inner.len()
103 }
104 pub fn remove(&mut self, key: &K) -> Result<Option<V>> {
108 #[cfg(not(target_arch = "wasm32"))]
109 let _guard = self.inner.memory().0.poison_on_unwind();
110 Ok(self.inner.remove(Codec::borrowed(key)).map(|v| v.0))
111 }
112 pub fn first_key_value(&self) -> Result<Option<(K, V)>> {
116 Ok(self.inner.first_key_value().map(|(k, v)| (k.0, v.0)))
117 }
118 pub fn last_key_value(&self) -> Result<Option<(K, V)>> {
122 Ok(self.inner.last_key_value().map(|(k, v)| (k.0, v.0)))
123 }
124 #[must_use]
126 pub fn iter(&self) -> MapIter<'_, K, V, M> {
127 MapIter(self.inner.iter())
128 }
129 pub fn range(&self, bounds: impl RangeBounds<K>) -> MapIter<'_, K, V, M> {
131 MapIter(self.inner.range(codec_bounds(&bounds)))
132 }
133 pub fn keys(&self) -> impl DoubleEndedIterator<Item = Result<K>> + '_ {
135 self.inner.keys().map(|k| Ok(k.0))
136 }
137 pub fn keys_range(
139 &self,
140 bounds: impl RangeBounds<K>,
141 ) -> impl DoubleEndedIterator<Item = Result<K>> + '_ {
142 self.inner
143 .keys_range(codec_bounds(&bounds))
144 .map(|k| Ok(k.0))
145 }
146 pub fn values(&self) -> impl DoubleEndedIterator<Item = Result<V>> + '_ {
148 self.inner.values().map(|v| Ok(v.0))
149 }
150}
151
152pub(super) fn codec_bounds<K: Clone>(
153 range: &impl RangeBounds<K>,
154) -> (std::ops::Bound<Codec<K>>, std::ops::Bound<Codec<K>>) {
155 (
156 range.start_bound().map(|k| Codec(k.clone())),
157 range.end_bound().map(|k| Codec(k.clone())),
158 )
159}
160impl<'a, K: Storable + Ord + Clone, V: Storable, M: Memory> IntoIterator
161 for &'a StableBTreeMap<K, V, M>
162{
163 type Item = <MapIter<'a, K, V, M> as Iterator>::Item;
164 type IntoIter = MapIter<'a, K, V, M>;
165 fn into_iter(self) -> Self::IntoIter {
166 self.iter()
167 }
168}