ic_storage/adapter/
map.rs1use super::bridge::{self, Codec, TreeMemory};
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, 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(TreeMemory::Allocation(memory)),
34 })
35 }
36 pub fn load(memory: RuntimeMemory<M>) -> Result<Self> {
40 Ok(Self {
41 inner: bridge::Map::load(TreeMemory::Allocation(memory)).ok_or(Error::Format)?,
42 })
43 }
44 pub fn clear(&mut self) {
46 #[cfg(not(target_arch = "wasm32"))]
47 let _guard = self.inner.memory().allocation().poison_on_unwind();
48 self.inner.clear();
49 }
50 pub fn reserve_pages(
52 self,
53 minimum: u64,
54 ) -> (Self, std::result::Result<(), crate::RuntimeGrowError>) {
55 let additional = minimum.saturating_sub(self.inner.memory().allocation().size());
56 let result = self
57 .inner
58 .memory()
59 .allocation()
60 .grow(additional)
61 .map(|_| ());
62 (self, result)
63 }
64 #[must_use]
66 pub fn allocated_pages(self) -> (Self, u64) {
67 let pages = self.inner.memory().allocation().size();
68 (self, pages)
69 }
70 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
72 #[cfg(not(target_arch = "wasm32"))]
73 let _guard = self.inner.memory().allocation().poison_on_unwind();
74 self.inner.insert(Codec(key), Codec(value)).map(|v| v.0)
75 }
76 pub fn get(&self, key: &K) -> Option<V> {
78 self.inner.get(Codec::borrowed(key)).map(|v| v.0)
79 }
80 pub fn contains_key(&self, key: &K) -> bool {
82 self.inner.contains_key(Codec::borrowed(key))
83 }
84 #[must_use]
86 pub const fn is_empty(&self) -> bool {
87 self.inner.is_empty()
88 }
89 #[must_use]
91 pub const fn len(&self) -> u64 {
92 self.inner.len()
93 }
94 pub fn remove(&mut self, key: &K) -> Option<V> {
96 #[cfg(not(target_arch = "wasm32"))]
97 let _guard = self.inner.memory().allocation().poison_on_unwind();
98 self.inner.remove(Codec::borrowed(key)).map(|v| v.0)
99 }
100 #[must_use]
102 pub fn first_key_value(&self) -> Option<(K, V)> {
103 self.inner.first_key_value().map(|(k, v)| (k.0, v.0))
104 }
105 #[must_use]
107 pub fn last_key_value(&self) -> Option<(K, V)> {
108 self.inner.last_key_value().map(|(k, v)| (k.0, v.0))
109 }
110 #[must_use]
112 pub fn iter(&self) -> MapIter<'_, K, V, M> {
113 MapIter(self.inner.iter())
114 }
115 pub fn range(&self, bounds: impl RangeBounds<K>) -> MapIter<'_, K, V, M> {
117 MapIter(self.inner.range(codec_bounds(&bounds)))
118 }
119 pub fn keys(&self) -> impl DoubleEndedIterator<Item = K> + '_ {
121 self.inner.keys().map(|k| k.0)
122 }
123 pub fn keys_range(
125 &self,
126 bounds: impl RangeBounds<K>,
127 ) -> impl DoubleEndedIterator<Item = K> + '_ {
128 self.inner.keys_range(codec_bounds(&bounds)).map(|k| k.0)
129 }
130 pub fn values(&self) -> impl DoubleEndedIterator<Item = V> + '_ {
132 self.inner.values().map(|v| v.0)
133 }
134}
135
136pub(super) fn codec_bounds<K: Clone>(
137 range: &impl RangeBounds<K>,
138) -> (std::ops::Bound<Codec<K>>, std::ops::Bound<Codec<K>>) {
139 (
140 range.start_bound().map(|k| Codec(k.clone())),
141 range.end_bound().map(|k| Codec(k.clone())),
142 )
143}
144impl<'a, K: Storable + Ord + Clone, V: Storable, M: Memory> IntoIterator
145 for &'a StableBTreeMap<K, V, M>
146{
147 type Item = <MapIter<'a, K, V, M> as Iterator>::Item;
148 type IntoIter = MapIter<'a, K, V, M>;
149 fn into_iter(self) -> Self::IntoIter {
150 self.iter()
151 }
152}