linera_views/views/
collection_view.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{
5    borrow::Borrow,
6    collections::{btree_map, BTreeMap},
7    io::Write,
8    marker::PhantomData,
9    mem,
10    ops::Deref,
11};
12
13use allocative::{Allocative, Key, Visitor};
14use async_lock::{RwLock, RwLockReadGuard};
15#[cfg(with_metrics)]
16use linera_base::prometheus_util::MeasureLatency as _;
17use serde::{de::DeserializeOwned, Serialize};
18
19use crate::{
20    batch::Batch,
21    common::{CustomSerialize, HasherOutput, SliceExt as _, Update},
22    context::{BaseKey, Context},
23    hashable_wrapper::WrappedHashableContainerView,
24    historical_hash_wrapper::HistoricallyHashableView,
25    store::ReadableKeyValueStore as _,
26    views::{ClonableView, HashableView, Hasher, View, ViewError, MIN_VIEW_TAG},
27};
28
29#[cfg(with_metrics)]
30mod metrics {
31    use std::sync::LazyLock;
32
33    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
34    use prometheus::HistogramVec;
35
36    /// The runtime of hash computation
37    pub static COLLECTION_VIEW_HASH_RUNTIME: LazyLock<HistogramVec> = LazyLock::new(|| {
38        register_histogram_vec(
39            "collection_view_hash_runtime",
40            "CollectionView hash runtime",
41            &[],
42            exponential_bucket_latencies(5.0),
43        )
44    });
45}
46
47/// A view that supports accessing a collection of views of the same kind, indexed by a
48/// `Vec<u8>`, one subview at a time.
49#[derive(Debug)]
50pub struct ByteCollectionView<C, W> {
51    /// The view context.
52    context: C,
53    /// Whether to clear storage before applying updates.
54    delete_storage_first: bool,
55    /// Entries that may have staged changes.
56    updates: RwLock<BTreeMap<Vec<u8>, Update<W>>>,
57}
58
59impl<C, W: Allocative> Allocative for ByteCollectionView<C, W> {
60    fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
61        let name = Key::new("ByteCollectionView");
62        let size = mem::size_of::<Self>();
63        let mut visitor = visitor.enter(name, size);
64        if let Some(updates) = self.updates.try_read() {
65            updates.deref().visit(&mut visitor);
66        }
67        visitor.exit();
68    }
69}
70
71/// A read-only accessor for a particular subview in a [`CollectionView`].
72pub enum ReadGuardedView<'a, W> {
73    /// The view is loaded in the updates
74    Loaded {
75        /// The guard for the updates.
76        updates: RwLockReadGuard<'a, BTreeMap<Vec<u8>, Update<W>>>,
77        /// The key in question.
78        short_key: Vec<u8>,
79    },
80    /// The view is not loaded in the updates
81    NotLoaded {
82        /// The guard for the updates. It is needed so that it prevents
83        /// opening the view as write separately.
84        _updates: RwLockReadGuard<'a, BTreeMap<Vec<u8>, Update<W>>>,
85        /// The view obtained from the storage
86        view: W,
87    },
88}
89
90impl<W> std::ops::Deref for ReadGuardedView<'_, W> {
91    type Target = W;
92
93    fn deref(&self) -> &W {
94        match self {
95            ReadGuardedView::Loaded { updates, short_key } => {
96                let Update::Set(view) = updates.get(short_key).unwrap() else {
97                    unreachable!();
98                };
99                view
100            }
101            ReadGuardedView::NotLoaded { _updates, view } => view,
102        }
103    }
104}
105
106/// We need to find new base keys in order to implement `CollectionView`.
107/// We do this by appending a value to the base key.
108///
109/// Sub-views in a collection share a common key prefix, like in other view types. However,
110/// just concatenating the shared prefix with sub-view keys makes it impossible to distinguish if a
111/// given key belongs to child sub-view or a grandchild sub-view (consider for example if a
112/// collection is stored inside the collection).
113#[repr(u8)]
114enum KeyTag {
115    /// Prefix for specifying an index and serves to indicate the existence of an entry in the collection.
116    Index = MIN_VIEW_TAG,
117    /// Prefix for specifying as the prefix for the sub-view.
118    Subview,
119}
120
121impl<W: View> View for ByteCollectionView<W::Context, W> {
122    const NUM_INIT_KEYS: usize = 0;
123
124    type Context = W::Context;
125
126    fn context(&self) -> &Self::Context {
127        &self.context
128    }
129
130    fn pre_load(_context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
131        Ok(vec![])
132    }
133
134    fn post_load(context: Self::Context, _values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
135        Ok(Self {
136            context,
137            delete_storage_first: false,
138            updates: RwLock::new(BTreeMap::new()),
139        })
140    }
141
142    fn rollback(&mut self) {
143        self.delete_storage_first = false;
144        self.updates.get_mut().clear();
145    }
146
147    async fn has_pending_changes(&self) -> bool {
148        if self.delete_storage_first {
149            return true;
150        }
151        let updates = self.updates.read().await;
152        !updates.is_empty()
153    }
154
155    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
156        let mut delete_view = false;
157        let updates = self
158            .updates
159            .try_read()
160            .ok_or_else(|| ViewError::TryLockError(vec![]))?;
161        if self.delete_storage_first {
162            delete_view = true;
163            batch.delete_key_prefix(self.context.base_key().bytes.clone());
164            for (index, update) in updates.iter() {
165                if let Update::Set(view) = update {
166                    view.pre_save(batch)?;
167                    self.add_index(batch, index);
168                    delete_view = false;
169                }
170            }
171        } else {
172            for (index, update) in updates.iter() {
173                match update {
174                    Update::Set(view) => {
175                        view.pre_save(batch)?;
176                        self.add_index(batch, index);
177                    }
178                    Update::Removed => {
179                        let key_subview = self.get_subview_key(index);
180                        let key_index = self.get_index_key(index);
181                        batch.delete_key(key_index);
182                        batch.delete_key_prefix(key_subview);
183                    }
184                }
185            }
186        }
187        Ok(delete_view)
188    }
189
190    fn post_save(&mut self) {
191        for (_, update) in self.updates.get_mut().iter_mut() {
192            if let Update::Set(view) = update {
193                view.post_save();
194            }
195        }
196        self.delete_storage_first = false;
197        self.updates.get_mut().clear();
198    }
199
200    fn clear(&mut self) {
201        self.delete_storage_first = true;
202        self.updates.get_mut().clear();
203    }
204}
205
206impl<W: ClonableView> ClonableView for ByteCollectionView<W::Context, W> {
207    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
208        let cloned_updates = self
209            .updates
210            .get_mut()
211            .iter_mut()
212            .map(|(key, value)| {
213                let cloned_value: Result<_, ViewError> = match value {
214                    Update::Removed => Ok(Update::Removed),
215                    Update::Set(view) => Ok(Update::Set(view.clone_unchecked()?)),
216                };
217                cloned_value.map(|v| (key.clone(), v))
218            })
219            .collect::<Result<_, ViewError>>()?;
220
221        Ok(ByteCollectionView {
222            context: self.context.clone(),
223            delete_storage_first: self.delete_storage_first,
224            updates: RwLock::new(cloned_updates),
225        })
226    }
227}
228
229impl<W: View> ByteCollectionView<W::Context, W> {
230    fn get_index_key(&self, index: &[u8]) -> Vec<u8> {
231        self.context
232            .base_key()
233            .base_tag_index(KeyTag::Index as u8, index)
234    }
235
236    fn get_subview_key(&self, index: &[u8]) -> Vec<u8> {
237        self.context
238            .base_key()
239            .base_tag_index(KeyTag::Subview as u8, index)
240    }
241
242    fn add_index(&self, batch: &mut Batch, index: &[u8]) {
243        let key = self.get_index_key(index);
244        batch.put_key_value_bytes(key, vec![]);
245    }
246
247    /// Loads a subview for the data at the given index in the collection. If an entry
248    /// is absent then a default entry is added to the collection. The resulting view
249    /// can be modified.
250    /// ```rust
251    /// # tokio_test::block_on(async {
252    /// # use linera_views::context::MemoryContext;
253    /// # use linera_views::collection_view::ByteCollectionView;
254    /// # use linera_views::register_view::RegisterView;
255    /// # use linera_views::views::View;
256    /// # let context = MemoryContext::new_for_testing(());
257    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
258    ///     ByteCollectionView::load(context).await.unwrap();
259    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
260    /// let value = subview.get();
261    /// assert_eq!(*value, String::default());
262    /// # })
263    /// ```
264    pub async fn load_entry_mut(&mut self, short_key: &[u8]) -> Result<&mut W, ViewError> {
265        match self.updates.get_mut().entry(short_key.to_vec()) {
266            btree_map::Entry::Occupied(entry) => {
267                let entry = entry.into_mut();
268                match entry {
269                    Update::Set(view) => Ok(view),
270                    Update::Removed => {
271                        let key = self
272                            .context
273                            .base_key()
274                            .base_tag_index(KeyTag::Subview as u8, short_key);
275                        let context = self.context.clone_with_base_key(key);
276                        // Obtain a view and set its pending state to the default (e.g. empty) state
277                        let view = W::new(context)?;
278                        *entry = Update::Set(view);
279                        let Update::Set(view) = entry else {
280                            unreachable!();
281                        };
282                        Ok(view)
283                    }
284                }
285            }
286            btree_map::Entry::Vacant(entry) => {
287                let key = self
288                    .context
289                    .base_key()
290                    .base_tag_index(KeyTag::Subview as u8, short_key);
291                let context = self.context.clone_with_base_key(key);
292                let view = if self.delete_storage_first {
293                    W::new(context)?
294                } else {
295                    W::load(context).await?
296                };
297                let Update::Set(view) = entry.insert(Update::Set(view)) else {
298                    unreachable!();
299                };
300                Ok(view)
301            }
302        }
303    }
304
305    /// Loads a subview for the data at the given index in the collection. If an entry
306    /// is absent then `None` is returned. The resulting view cannot be modified.
307    /// May fail if one subview is already being visited.
308    /// ```rust
309    /// # tokio_test::block_on(async {
310    /// # use linera_views::context::MemoryContext;
311    /// # use linera_views::collection_view::ByteCollectionView;
312    /// # use linera_views::register_view::RegisterView;
313    /// # use linera_views::views::View;
314    /// # let context = MemoryContext::new_for_testing(());
315    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
316    ///     ByteCollectionView::load(context).await.unwrap();
317    /// {
318    ///     let _subview = view.load_entry_mut(&[0, 1]).await.unwrap();
319    /// }
320    /// {
321    ///     let subview = view.try_load_entry(&[0, 1]).await.unwrap().unwrap();
322    ///     let value = subview.get();
323    ///     assert_eq!(*value, String::default());
324    /// }
325    /// assert!(view.try_load_entry(&[0, 2]).await.unwrap().is_none());
326    /// # })
327    /// ```
328    pub async fn try_load_entry(
329        &self,
330        short_key: &[u8],
331    ) -> Result<Option<ReadGuardedView<W>>, ViewError> {
332        let updates = self.updates.read().await;
333        match updates.get(short_key) {
334            Some(update) => match update {
335                Update::Removed => Ok(None),
336                Update::Set(_) => Ok(Some(ReadGuardedView::Loaded {
337                    updates,
338                    short_key: short_key.to_vec(),
339                })),
340            },
341            None => {
342                let key_index = self
343                    .context
344                    .base_key()
345                    .base_tag_index(KeyTag::Index as u8, short_key);
346                if !self.delete_storage_first
347                    && self.context.store().contains_key(&key_index).await?
348                {
349                    let key = self
350                        .context
351                        .base_key()
352                        .base_tag_index(KeyTag::Subview as u8, short_key);
353                    let context = self.context.clone_with_base_key(key);
354                    let view = W::load(context).await?;
355                    Ok(Some(ReadGuardedView::NotLoaded {
356                        _updates: updates,
357                        view,
358                    }))
359                } else {
360                    Ok(None)
361                }
362            }
363        }
364    }
365
366    /// Load multiple entries for reading at once.
367    /// The entries in `short_keys` have to be all distinct.
368    /// ```rust
369    /// # tokio_test::block_on(async {
370    /// # use linera_views::context::MemoryContext;
371    /// # use linera_views::collection_view::ByteCollectionView;
372    /// # use linera_views::register_view::RegisterView;
373    /// # use linera_views::views::View;
374    /// # let context = MemoryContext::new_for_testing(());
375    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
376    ///     ByteCollectionView::load(context).await.unwrap();
377    /// {
378    ///     let _subview = view.load_entry_mut(&[0, 1]).await.unwrap();
379    /// }
380    /// let short_keys = vec![vec![0, 1], vec![2, 3]];
381    /// let subviews = view.try_load_entries(short_keys).await.unwrap();
382    /// let value0 = subviews[0].as_ref().unwrap().get();
383    /// assert_eq!(*value0, String::default());
384    /// # })
385    /// ```
386    pub async fn try_load_entries(
387        &self,
388        short_keys: Vec<Vec<u8>>,
389    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError> {
390        let mut results = Vec::with_capacity(short_keys.len());
391        let mut keys_to_check = Vec::new();
392        let mut keys_to_check_metadata = Vec::new();
393        let updates = self.updates.read().await;
394
395        for (position, short_key) in short_keys.into_iter().enumerate() {
396            match updates.get(&short_key) {
397                Some(update) => match update {
398                    Update::Removed => {
399                        results.push(None);
400                    }
401                    Update::Set(_) => {
402                        let updates = self.updates.read().await;
403                        results.push(Some(ReadGuardedView::Loaded {
404                            updates,
405                            short_key: short_key.clone(),
406                        }));
407                    }
408                },
409                None => {
410                    results.push(None); // Placeholder, may be updated later
411                    if !self.delete_storage_first {
412                        let key = self
413                            .context
414                            .base_key()
415                            .base_tag_index(KeyTag::Subview as u8, &short_key);
416                        let subview_context = self.context.clone_with_base_key(key);
417                        let key = self
418                            .context
419                            .base_key()
420                            .base_tag_index(KeyTag::Index as u8, &short_key);
421                        keys_to_check.push(key);
422                        keys_to_check_metadata.push((position, subview_context));
423                    }
424                }
425            }
426        }
427
428        let found_keys = self.context.store().contains_keys(&keys_to_check).await?;
429        let entries_to_load = keys_to_check_metadata
430            .into_iter()
431            .zip(found_keys)
432            .filter_map(|(metadata, found)| found.then_some(metadata))
433            .collect::<Vec<_>>();
434
435        let mut keys_to_load = Vec::with_capacity(entries_to_load.len() * W::NUM_INIT_KEYS);
436        for (_, context) in &entries_to_load {
437            keys_to_load.extend(W::pre_load(context)?);
438        }
439        let values = self
440            .context
441            .store()
442            .read_multi_values_bytes(&keys_to_load)
443            .await?;
444
445        for (loaded_values, (position, context)) in values
446            .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
447            .zip(entries_to_load)
448        {
449            let view = W::post_load(context, loaded_values)?;
450            let updates = self.updates.read().await;
451            results[position] = Some(ReadGuardedView::NotLoaded {
452                _updates: updates,
453                view,
454            });
455        }
456
457        Ok(results)
458    }
459
460    /// Loads multiple entries for reading at once with their keys.
461    /// ```rust
462    /// # tokio_test::block_on(async {
463    /// # use linera_views::context::MemoryContext;
464    /// # use linera_views::collection_view::ByteCollectionView;
465    /// # use linera_views::register_view::RegisterView;
466    /// # use linera_views::views::View;
467    /// # let context = MemoryContext::new_for_testing(());
468    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
469    ///     ByteCollectionView::load(context).await.unwrap();
470    /// {
471    ///     let subview = view.load_entry_mut(&vec![0, 1]).await.unwrap();
472    ///     subview.set("Bonjour".into());
473    /// }
474    /// let short_keys = vec![vec![0, 1], vec![0, 2]];
475    /// let pairs = view.try_load_entries_pairs(short_keys).await.unwrap();
476    /// assert_eq!(pairs[0].0, vec![0, 1]);
477    /// assert_eq!(pairs[1].0, vec![0, 2]);
478    /// let value0 = pairs[0].1.as_ref().unwrap().get();
479    /// assert_eq!(*value0, "Bonjour".to_string());
480    /// assert!(pairs[1].1.is_none());
481    /// # })
482    /// ```
483    pub async fn try_load_entries_pairs(
484        &self,
485        short_keys: Vec<Vec<u8>>,
486    ) -> Result<Vec<(Vec<u8>, Option<ReadGuardedView<W>>)>, ViewError> {
487        let values = self.try_load_entries(short_keys.clone()).await?;
488        Ok(short_keys.into_iter().zip(values).collect())
489    }
490
491    /// Load all entries for reading at once.
492    /// ```rust
493    /// # tokio_test::block_on(async {
494    /// # use linera_views::context::MemoryContext;
495    /// # use linera_views::collection_view::ByteCollectionView;
496    /// # use linera_views::register_view::RegisterView;
497    /// # use linera_views::views::View;
498    /// # let context = MemoryContext::new_for_testing(());
499    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
500    ///     ByteCollectionView::load(context).await.unwrap();
501    /// {
502    ///     let _subview = view.load_entry_mut(&[0, 1]).await.unwrap();
503    /// }
504    /// let subviews = view.try_load_all_entries().await.unwrap();
505    /// assert_eq!(subviews.len(), 1);
506    /// # })
507    /// ```
508    pub async fn try_load_all_entries(
509        &self,
510    ) -> Result<Vec<(Vec<u8>, ReadGuardedView<W>)>, ViewError> {
511        let updates = self.updates.read().await; // Acquire the read lock to prevent writes.
512        let short_keys = self.keys().await?;
513        let mut results = Vec::with_capacity(short_keys.len());
514
515        let mut keys_to_load = Vec::new();
516        let mut keys_to_load_metadata = Vec::new();
517        for (position, short_key) in short_keys.iter().enumerate() {
518            match updates.get(short_key) {
519                Some(update) => {
520                    let Update::Set(_) = update else {
521                        unreachable!();
522                    };
523                    let updates = self.updates.read().await;
524                    let view = ReadGuardedView::Loaded {
525                        updates,
526                        short_key: short_key.clone(),
527                    };
528                    results.push((short_key.clone(), Some(view)));
529                }
530                None => {
531                    // If a key is not in `updates`, then it is in storage.
532                    // The key exists since otherwise it would not be in `short_keys`.
533                    // Therefore we have `self.delete_storage_first = false`.
534                    assert!(!self.delete_storage_first);
535                    results.push((short_key.clone(), None));
536                    let key = self
537                        .context
538                        .base_key()
539                        .base_tag_index(KeyTag::Subview as u8, short_key);
540                    let subview_context = self.context.clone_with_base_key(key);
541                    keys_to_load.extend(W::pre_load(&subview_context)?);
542                    keys_to_load_metadata.push((position, subview_context, short_key.clone()));
543                }
544            }
545        }
546
547        let values = self
548            .context
549            .store()
550            .read_multi_values_bytes(&keys_to_load)
551            .await?;
552
553        for (loaded_values, (position, context, short_key)) in values
554            .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
555            .zip(keys_to_load_metadata)
556        {
557            let view = W::post_load(context, loaded_values)?;
558            let updates = self.updates.read().await;
559            let guarded_view = ReadGuardedView::NotLoaded {
560                _updates: updates,
561                view,
562            };
563            results[position] = (short_key, Some(guarded_view));
564        }
565
566        Ok(results
567            .into_iter()
568            .map(|(short_key, view)| (short_key, view.unwrap()))
569            .collect::<Vec<_>>())
570    }
571
572    /// Resets an entry to the default value.
573    /// ```rust
574    /// # tokio_test::block_on(async {
575    /// # use linera_views::context::MemoryContext;
576    /// # use linera_views::collection_view::ByteCollectionView;
577    /// # use linera_views::register_view::RegisterView;
578    /// # use linera_views::views::View;
579    /// # let context = MemoryContext::new_for_testing(());
580    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
581    ///     ByteCollectionView::load(context).await.unwrap();
582    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
583    /// let value = subview.get_mut();
584    /// *value = String::from("Hello");
585    /// view.reset_entry_to_default(&[0, 1]).unwrap();
586    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
587    /// let value = subview.get_mut();
588    /// assert_eq!(*value, String::default());
589    /// # })
590    /// ```
591    pub fn reset_entry_to_default(&mut self, short_key: &[u8]) -> Result<(), ViewError> {
592        let key = self
593            .context
594            .base_key()
595            .base_tag_index(KeyTag::Subview as u8, short_key);
596        let context = self.context.clone_with_base_key(key);
597        let view = W::new(context)?;
598        self.updates
599            .get_mut()
600            .insert(short_key.to_vec(), Update::Set(view));
601        Ok(())
602    }
603
604    /// Tests if the collection contains a specified key and returns a boolean.
605    /// ```rust
606    /// # tokio_test::block_on(async {
607    /// # use linera_views::context::MemoryContext;
608    /// # use linera_views::collection_view::ByteCollectionView;
609    /// # use linera_views::register_view::RegisterView;
610    /// # use linera_views::views::View;
611    /// # let context = MemoryContext::new_for_testing(());
612    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
613    ///     ByteCollectionView::load(context).await.unwrap();
614    /// {
615    ///     let _subview = view.load_entry_mut(&[0, 1]).await.unwrap();
616    /// }
617    /// assert!(view.contains_key(&[0, 1]).await.unwrap());
618    /// assert!(!view.contains_key(&[0, 2]).await.unwrap());
619    /// # })
620    /// ```
621    pub async fn contains_key(&self, short_key: &[u8]) -> Result<bool, ViewError> {
622        let updates = self.updates.read().await;
623        Ok(match updates.get(short_key) {
624            Some(entry) => match entry {
625                Update::Set(_view) => true,
626                _entry @ Update::Removed => false,
627            },
628            None => {
629                let key_index = self
630                    .context
631                    .base_key()
632                    .base_tag_index(KeyTag::Index as u8, short_key);
633                !self.delete_storage_first && self.context.store().contains_key(&key_index).await?
634            }
635        })
636    }
637
638    /// Marks the entry as removed. If absent then nothing is done.
639    /// ```rust
640    /// # tokio_test::block_on(async {
641    /// # use linera_views::context::MemoryContext;
642    /// # use linera_views::collection_view::ByteCollectionView;
643    /// # use linera_views::register_view::RegisterView;
644    /// # use linera_views::views::View;
645    /// # let context = MemoryContext::new_for_testing(());
646    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
647    ///     ByteCollectionView::load(context).await.unwrap();
648    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
649    /// let value = subview.get_mut();
650    /// assert_eq!(*value, String::default());
651    /// view.remove_entry(vec![0, 1]);
652    /// let keys = view.keys().await.unwrap();
653    /// assert_eq!(keys.len(), 0);
654    /// # })
655    /// ```
656    pub fn remove_entry(&mut self, short_key: Vec<u8>) {
657        if self.delete_storage_first {
658            // Optimization: No need to mark `short_key` for deletion as we are going to remove all the keys at once.
659            self.updates.get_mut().remove(&short_key);
660        } else {
661            self.updates.get_mut().insert(short_key, Update::Removed);
662        }
663    }
664
665    /// Gets the extra data.
666    pub fn extra(&self) -> &<W::Context as Context>::Extra {
667        self.context.extra()
668    }
669}
670
671impl<W: View> ByteCollectionView<W::Context, W> {
672    /// Applies a function f on each index (aka key). Keys are visited in the
673    /// lexicographic order. If the function returns false, then the loop
674    /// ends prematurely.
675    /// ```rust
676    /// # tokio_test::block_on(async {
677    /// # use linera_views::context::MemoryContext;
678    /// # use linera_views::collection_view::ByteCollectionView;
679    /// # use linera_views::register_view::RegisterView;
680    /// # use linera_views::views::View;
681    /// # let context = MemoryContext::new_for_testing(());
682    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
683    ///     ByteCollectionView::load(context).await.unwrap();
684    /// view.load_entry_mut(&[0, 1]).await.unwrap();
685    /// view.load_entry_mut(&[0, 2]).await.unwrap();
686    /// let mut count = 0;
687    /// view.for_each_key_while(|_key| {
688    ///     count += 1;
689    ///     Ok(count < 1)
690    /// })
691    /// .await
692    /// .unwrap();
693    /// assert_eq!(count, 1);
694    /// # })
695    /// ```
696    pub async fn for_each_key_while<F>(&self, mut f: F) -> Result<(), ViewError>
697    where
698        F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
699    {
700        let updates = self.updates.read().await;
701        let mut updates = updates.iter();
702        let mut update = updates.next();
703        if !self.delete_storage_first {
704            let base = self.get_index_key(&[]);
705            for index in self.context.store().find_keys_by_prefix(&base).await? {
706                loop {
707                    match update {
708                        Some((key, value)) if key <= &index => {
709                            if let Update::Set(_) = value {
710                                if !f(key)? {
711                                    return Ok(());
712                                }
713                            }
714                            update = updates.next();
715                            if key == &index {
716                                break;
717                            }
718                        }
719                        _ => {
720                            if !f(&index)? {
721                                return Ok(());
722                            }
723                            break;
724                        }
725                    }
726                }
727            }
728        }
729        while let Some((key, value)) = update {
730            if let Update::Set(_) = value {
731                if !f(key)? {
732                    return Ok(());
733                }
734            }
735            update = updates.next();
736        }
737        Ok(())
738    }
739
740    /// Applies a function f on each index (aka key). Keys are visited in a
741    /// lexicographic order.
742    /// ```rust
743    /// # tokio_test::block_on(async {
744    /// # use linera_views::context::MemoryContext;
745    /// # use linera_views::collection_view::ByteCollectionView;
746    /// # use linera_views::register_view::RegisterView;
747    /// # use linera_views::views::View;
748    /// # let context = MemoryContext::new_for_testing(());
749    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
750    ///     ByteCollectionView::load(context).await.unwrap();
751    /// view.load_entry_mut(&[0, 1]).await.unwrap();
752    /// view.load_entry_mut(&[0, 2]).await.unwrap();
753    /// let mut count = 0;
754    /// view.for_each_key(|_key| {
755    ///     count += 1;
756    ///     Ok(())
757    /// })
758    /// .await
759    /// .unwrap();
760    /// assert_eq!(count, 2);
761    /// # })
762    /// ```
763    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
764    where
765        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
766    {
767        self.for_each_key_while(|key| {
768            f(key)?;
769            Ok(true)
770        })
771        .await
772    }
773
774    /// Returns the list of keys in the collection. The order is lexicographic.
775    /// ```rust
776    /// # tokio_test::block_on(async {
777    /// # use linera_views::context::MemoryContext;
778    /// # use linera_views::collection_view::ByteCollectionView;
779    /// # use linera_views::register_view::RegisterView;
780    /// # use linera_views::views::View;
781    /// # let context = MemoryContext::new_for_testing(());
782    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
783    ///     ByteCollectionView::load(context).await.unwrap();
784    /// view.load_entry_mut(&[0, 1]).await.unwrap();
785    /// view.load_entry_mut(&[0, 2]).await.unwrap();
786    /// let keys = view.keys().await.unwrap();
787    /// assert_eq!(keys, vec![vec![0, 1], vec![0, 2]]);
788    /// # })
789    /// ```
790    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
791        let mut keys = Vec::new();
792        self.for_each_key(|key| {
793            keys.push(key.to_vec());
794            Ok(())
795        })
796        .await?;
797        Ok(keys)
798    }
799
800    /// Returns the number of entries in the collection.
801    /// ```rust
802    /// # tokio_test::block_on(async {
803    /// # use linera_views::context::MemoryContext;
804    /// # use linera_views::collection_view::ByteCollectionView;
805    /// # use linera_views::register_view::RegisterView;
806    /// # use linera_views::views::View;
807    /// # let context = MemoryContext::new_for_testing(());
808    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
809    ///     ByteCollectionView::load(context).await.unwrap();
810    /// view.load_entry_mut(&[0, 1]).await.unwrap();
811    /// view.load_entry_mut(&[0, 2]).await.unwrap();
812    /// assert_eq!(view.count().await.unwrap(), 2);
813    /// # })
814    /// ```
815    pub async fn count(&self) -> Result<usize, ViewError> {
816        let mut count = 0;
817        self.for_each_key(|_key| {
818            count += 1;
819            Ok(())
820        })
821        .await?;
822        Ok(count)
823    }
824}
825
826impl<W: HashableView> HashableView for ByteCollectionView<W::Context, W> {
827    type Hasher = sha3::Sha3_256;
828
829    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
830        #[cfg(with_metrics)]
831        let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
832        let mut hasher = sha3::Sha3_256::default();
833        let keys = self.keys().await?;
834        let count = keys.len() as u32;
835        hasher.update_with_bcs_bytes(&count)?;
836        let updates = self.updates.get_mut();
837        for key in keys {
838            hasher.update_with_bytes(&key)?;
839            let hash = match updates.get_mut(&key) {
840                Some(entry) => {
841                    let Update::Set(view) = entry else {
842                        unreachable!();
843                    };
844                    view.hash_mut().await?
845                }
846                None => {
847                    let key = self
848                        .context
849                        .base_key()
850                        .base_tag_index(KeyTag::Subview as u8, &key);
851                    let context = self.context.clone_with_base_key(key);
852                    let mut view = W::load(context).await?;
853                    view.hash_mut().await?
854                }
855            };
856            hasher.write_all(hash.as_ref())?;
857        }
858        Ok(hasher.finalize())
859    }
860
861    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
862        #[cfg(with_metrics)]
863        let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
864        let mut hasher = sha3::Sha3_256::default();
865        let updates = self.updates.read().await; // Acquire the lock to prevent writes.
866        let keys = self.keys().await?;
867        let count = keys.len() as u32;
868        hasher.update_with_bcs_bytes(&count)?;
869        for key in keys {
870            hasher.update_with_bytes(&key)?;
871            let hash = match updates.get(&key) {
872                Some(entry) => {
873                    let Update::Set(view) = entry else {
874                        unreachable!();
875                    };
876                    view.hash().await?
877                }
878                None => {
879                    let key = self
880                        .context
881                        .base_key()
882                        .base_tag_index(KeyTag::Subview as u8, &key);
883                    let context = self.context.clone_with_base_key(key);
884                    let view = W::load(context).await?;
885                    view.hash().await?
886                }
887            };
888            hasher.write_all(hash.as_ref())?;
889        }
890        Ok(hasher.finalize())
891    }
892}
893
894/// A view that supports accessing a collection of views of the same kind, indexed by a
895/// key, one subview at a time.
896#[derive(Debug, Allocative)]
897#[allocative(bound = "C, I, W: Allocative")]
898pub struct CollectionView<C, I, W> {
899    collection: ByteCollectionView<C, W>,
900    #[allocative(skip)]
901    _phantom: PhantomData<I>,
902}
903
904impl<W: View, I> View for CollectionView<W::Context, I, W>
905where
906    I: Send + Sync + Serialize + DeserializeOwned,
907{
908    const NUM_INIT_KEYS: usize = ByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
909
910    type Context = W::Context;
911
912    fn context(&self) -> &Self::Context {
913        self.collection.context()
914    }
915
916    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
917        ByteCollectionView::<W::Context, W>::pre_load(context)
918    }
919
920    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
921        let collection = ByteCollectionView::post_load(context, values)?;
922        Ok(CollectionView {
923            collection,
924            _phantom: PhantomData,
925        })
926    }
927
928    fn rollback(&mut self) {
929        self.collection.rollback()
930    }
931
932    async fn has_pending_changes(&self) -> bool {
933        self.collection.has_pending_changes().await
934    }
935
936    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
937        self.collection.pre_save(batch)
938    }
939
940    fn post_save(&mut self) {
941        self.collection.post_save()
942    }
943
944    fn clear(&mut self) {
945        self.collection.clear()
946    }
947}
948
949impl<I, W: ClonableView> ClonableView for CollectionView<W::Context, I, W>
950where
951    I: Send + Sync + Serialize + DeserializeOwned,
952{
953    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
954        Ok(CollectionView {
955            collection: self.collection.clone_unchecked()?,
956            _phantom: PhantomData,
957        })
958    }
959}
960
961impl<I: Serialize, W: View> CollectionView<W::Context, I, W> {
962    /// Loads a subview for the data at the given index in the collection. If an entry
963    /// is absent then a default entry is added to the collection. The resulting view
964    /// can be modified.
965    /// ```rust
966    /// # tokio_test::block_on(async {
967    /// # use linera_views::context::MemoryContext;
968    /// # use linera_views::collection_view::CollectionView;
969    /// # use linera_views::register_view::RegisterView;
970    /// # use linera_views::views::View;
971    /// # let context = MemoryContext::new_for_testing(());
972    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
973    ///     CollectionView::load(context).await.unwrap();
974    /// let subview = view.load_entry_mut(&23).await.unwrap();
975    /// let value = subview.get();
976    /// assert_eq!(*value, String::default());
977    /// # })
978    /// ```
979    pub async fn load_entry_mut<Q>(&mut self, index: &Q) -> Result<&mut W, ViewError>
980    where
981        I: Borrow<Q>,
982        Q: Serialize + ?Sized,
983    {
984        let short_key = BaseKey::derive_short_key(index)?;
985        self.collection.load_entry_mut(&short_key).await
986    }
987
988    /// Loads a subview for the data at the given index in the collection. If an entry
989    /// is absent then `None` is returned. The resulting view cannot be modified.
990    /// May fail if one subview is already being visited.
991    /// ```rust
992    /// # tokio_test::block_on(async {
993    /// # use linera_views::context::MemoryContext;
994    /// # use linera_views::collection_view::CollectionView;
995    /// # use linera_views::register_view::RegisterView;
996    /// # use linera_views::views::View;
997    /// # let context = MemoryContext::new_for_testing(());
998    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
999    ///     CollectionView::load(context).await.unwrap();
1000    /// {
1001    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1002    /// }
1003    /// {
1004    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1005    ///     let value = subview.get();
1006    ///     assert_eq!(*value, String::default());
1007    /// }
1008    /// assert!(view.try_load_entry(&24).await.unwrap().is_none());
1009    /// # })
1010    /// ```
1011    pub async fn try_load_entry<Q>(
1012        &self,
1013        index: &Q,
1014    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1015    where
1016        I: Borrow<Q>,
1017        Q: Serialize + ?Sized,
1018    {
1019        let short_key = BaseKey::derive_short_key(index)?;
1020        self.collection.try_load_entry(&short_key).await
1021    }
1022
1023    /// Load multiple entries for reading at once.
1024    /// The entries in indices have to be all distinct.
1025    /// ```rust
1026    /// # tokio_test::block_on(async {
1027    /// # use linera_views::context::MemoryContext;
1028    /// # use linera_views::collection_view::CollectionView;
1029    /// # use linera_views::register_view::RegisterView;
1030    /// # use linera_views::views::View;
1031    /// # let context = MemoryContext::new_for_testing(());
1032    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1033    ///     CollectionView::load(context).await.unwrap();
1034    /// {
1035    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1036    /// }
1037    /// let indices = vec![23, 24];
1038    /// let subviews = view.try_load_entries(&indices).await.unwrap();
1039    /// let value0 = subviews[0].as_ref().unwrap().get();
1040    /// assert_eq!(*value0, String::default());
1041    /// # })
1042    /// ```
1043    pub async fn try_load_entries<'a, Q>(
1044        &self,
1045        indices: impl IntoIterator<Item = &'a Q>,
1046    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError>
1047    where
1048        I: Borrow<Q>,
1049        Q: Serialize + 'a,
1050    {
1051        let short_keys = indices
1052            .into_iter()
1053            .map(|index| BaseKey::derive_short_key(index))
1054            .collect::<Result<_, _>>()?;
1055        self.collection.try_load_entries(short_keys).await
1056    }
1057
1058    /// Loads multiple entries for reading at once with their keys.
1059    /// The entries in indices have to be all distinct.
1060    /// ```rust
1061    /// # tokio_test::block_on(async {
1062    /// # use linera_views::context::MemoryContext;
1063    /// # use linera_views::collection_view::CollectionView;
1064    /// # use linera_views::register_view::RegisterView;
1065    /// # use linera_views::views::View;
1066    /// # let context = MemoryContext::new_for_testing(());
1067    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1068    ///     CollectionView::load(context).await.unwrap();
1069    /// {
1070    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1071    /// }
1072    /// let indices = [23, 24];
1073    /// let subviews = view.try_load_entries_pairs(indices).await.unwrap();
1074    /// let value0 = subviews[0].1.as_ref().unwrap().get();
1075    /// assert_eq!(*value0, String::default());
1076    /// # })
1077    /// ```
1078    pub async fn try_load_entries_pairs<Q>(
1079        &self,
1080        indices: impl IntoIterator<Item = Q>,
1081    ) -> Result<Vec<(Q, Option<ReadGuardedView<W>>)>, ViewError>
1082    where
1083        I: Borrow<Q>,
1084        Q: Serialize + Clone,
1085    {
1086        let indices_vec: Vec<Q> = indices.into_iter().collect();
1087        let values = self.try_load_entries(indices_vec.iter()).await?;
1088        Ok(indices_vec.into_iter().zip(values).collect())
1089    }
1090
1091    /// Load all entries for reading at once.
1092    /// ```rust
1093    /// # tokio_test::block_on(async {
1094    /// # use linera_views::context::MemoryContext;
1095    /// # use linera_views::collection_view::CollectionView;
1096    /// # use linera_views::register_view::RegisterView;
1097    /// # use linera_views::views::View;
1098    /// # let context = MemoryContext::new_for_testing(());
1099    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1100    ///     CollectionView::load(context).await.unwrap();
1101    /// {
1102    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1103    /// }
1104    /// let subviews = view.try_load_all_entries().await.unwrap();
1105    /// assert_eq!(subviews.len(), 1);
1106    /// # })
1107    /// ```
1108    pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError>
1109    where
1110        I: DeserializeOwned,
1111    {
1112        let results = self.collection.try_load_all_entries().await?;
1113        results
1114            .into_iter()
1115            .map(|(short_key, view)| {
1116                let index = BaseKey::deserialize_value(&short_key)?;
1117                Ok((index, view))
1118            })
1119            .collect()
1120    }
1121
1122    /// Resets an entry to the default value.
1123    /// ```rust
1124    /// # tokio_test::block_on(async {
1125    /// # use linera_views::context::MemoryContext;
1126    /// # use linera_views::collection_view::CollectionView;
1127    /// # use linera_views::register_view::RegisterView;
1128    /// # use linera_views::views::View;
1129    /// # let context = MemoryContext::new_for_testing(());
1130    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1131    ///     CollectionView::load(context).await.unwrap();
1132    /// let subview = view.load_entry_mut(&23).await.unwrap();
1133    /// let value = subview.get_mut();
1134    /// *value = String::from("Hello");
1135    /// view.reset_entry_to_default(&23).unwrap();
1136    /// let subview = view.load_entry_mut(&23).await.unwrap();
1137    /// let value = subview.get_mut();
1138    /// assert_eq!(*value, String::default());
1139    /// # })
1140    /// ```
1141    pub fn reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1142    where
1143        I: Borrow<Q>,
1144        Q: Serialize + ?Sized,
1145    {
1146        let short_key = BaseKey::derive_short_key(index)?;
1147        self.collection.reset_entry_to_default(&short_key)
1148    }
1149
1150    /// Removes an entry from the `CollectionView`. If absent nothing happens.
1151    /// ```rust
1152    /// # tokio_test::block_on(async {
1153    /// # use linera_views::context::MemoryContext;
1154    /// # use linera_views::collection_view::CollectionView;
1155    /// # use linera_views::register_view::RegisterView;
1156    /// # use linera_views::views::View;
1157    /// # let context = MemoryContext::new_for_testing(());
1158    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1159    ///     CollectionView::load(context).await.unwrap();
1160    /// let subview = view.load_entry_mut(&23).await.unwrap();
1161    /// let value = subview.get_mut();
1162    /// assert_eq!(*value, String::default());
1163    /// view.remove_entry(&23);
1164    /// let keys = view.indices().await.unwrap();
1165    /// assert_eq!(keys.len(), 0);
1166    /// # })
1167    /// ```
1168    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1169    where
1170        I: Borrow<Q>,
1171        Q: Serialize + ?Sized,
1172    {
1173        let short_key = BaseKey::derive_short_key(index)?;
1174        self.collection.remove_entry(short_key);
1175        Ok(())
1176    }
1177
1178    /// Gets the extra data.
1179    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1180        self.collection.extra()
1181    }
1182}
1183
1184impl<I, W: View> CollectionView<W::Context, I, W>
1185where
1186    I: Sync + Send + Serialize + DeserializeOwned,
1187{
1188    /// Returns the list of indices in the collection in the order determined by
1189    /// the serialization.
1190    /// ```rust
1191    /// # tokio_test::block_on(async {
1192    /// # use linera_views::context::MemoryContext;
1193    /// # use linera_views::collection_view::CollectionView;
1194    /// # use linera_views::register_view::RegisterView;
1195    /// # use linera_views::views::View;
1196    /// # let context = MemoryContext::new_for_testing(());
1197    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1198    ///     CollectionView::load(context).await.unwrap();
1199    /// view.load_entry_mut(&23).await.unwrap();
1200    /// view.load_entry_mut(&25).await.unwrap();
1201    /// let indices = view.indices().await.unwrap();
1202    /// assert_eq!(indices.len(), 2);
1203    /// # })
1204    /// ```
1205    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
1206        let mut indices = Vec::new();
1207        self.for_each_index(|index| {
1208            indices.push(index);
1209            Ok(())
1210        })
1211        .await?;
1212        Ok(indices)
1213    }
1214
1215    /// Returns the number of entries in the collection.
1216    /// ```rust
1217    /// # tokio_test::block_on(async {
1218    /// # use linera_views::context::MemoryContext;
1219    /// # use linera_views::collection_view::CollectionView;
1220    /// # use linera_views::register_view::RegisterView;
1221    /// # use linera_views::views::View;
1222    /// # let context = MemoryContext::new_for_testing(());
1223    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1224    ///     CollectionView::load(context).await.unwrap();
1225    /// view.load_entry_mut(&23).await.unwrap();
1226    /// view.load_entry_mut(&25).await.unwrap();
1227    /// assert_eq!(view.count().await.unwrap(), 2);
1228    /// # })
1229    /// ```
1230    pub async fn count(&self) -> Result<usize, ViewError> {
1231        self.collection.count().await
1232    }
1233}
1234
1235impl<I: DeserializeOwned, W: View> CollectionView<W::Context, I, W> {
1236    /// Applies a function f on each index. Indices are visited in an order
1237    /// determined by the serialization. If the function returns false then
1238    /// the loop ends prematurely.
1239    /// ```rust
1240    /// # tokio_test::block_on(async {
1241    /// # use linera_views::context::MemoryContext;
1242    /// # use linera_views::collection_view::CollectionView;
1243    /// # use linera_views::register_view::RegisterView;
1244    /// # use linera_views::views::View;
1245    /// # let context = MemoryContext::new_for_testing(());
1246    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1247    ///     CollectionView::load(context).await.unwrap();
1248    /// view.load_entry_mut(&23).await.unwrap();
1249    /// view.load_entry_mut(&24).await.unwrap();
1250    /// let mut count = 0;
1251    /// view.for_each_index_while(|_key| {
1252    ///     count += 1;
1253    ///     Ok(count < 1)
1254    /// })
1255    /// .await
1256    /// .unwrap();
1257    /// assert_eq!(count, 1);
1258    /// # })
1259    /// ```
1260    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1261    where
1262        F: FnMut(I) -> Result<bool, ViewError> + Send,
1263    {
1264        self.collection
1265            .for_each_key_while(|key| {
1266                let index = BaseKey::deserialize_value(key)?;
1267                f(index)
1268            })
1269            .await?;
1270        Ok(())
1271    }
1272
1273    /// Applies a function f on each index. Indices are visited in an order
1274    /// determined by the serialization.
1275    /// ```rust
1276    /// # tokio_test::block_on(async {
1277    /// # use linera_views::context::MemoryContext;
1278    /// # use linera_views::collection_view::CollectionView;
1279    /// # use linera_views::register_view::RegisterView;
1280    /// # use linera_views::views::View;
1281    /// # let context = MemoryContext::new_for_testing(());
1282    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1283    ///     CollectionView::load(context).await.unwrap();
1284    /// view.load_entry_mut(&23).await.unwrap();
1285    /// view.load_entry_mut(&28).await.unwrap();
1286    /// let mut count = 0;
1287    /// view.for_each_index(|_key| {
1288    ///     count += 1;
1289    ///     Ok(())
1290    /// })
1291    /// .await
1292    /// .unwrap();
1293    /// assert_eq!(count, 2);
1294    /// # })
1295    /// ```
1296    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1297    where
1298        F: FnMut(I) -> Result<(), ViewError> + Send,
1299    {
1300        self.collection
1301            .for_each_key(|key| {
1302                let index = BaseKey::deserialize_value(key)?;
1303                f(index)
1304            })
1305            .await?;
1306        Ok(())
1307    }
1308}
1309
1310impl<I, W: HashableView> HashableView for CollectionView<W::Context, I, W>
1311where
1312    I: Send + Sync + Serialize + DeserializeOwned,
1313{
1314    type Hasher = sha3::Sha3_256;
1315
1316    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1317        self.collection.hash_mut().await
1318    }
1319
1320    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1321        self.collection.hash().await
1322    }
1323}
1324
1325/// A map view that serializes the indices.
1326#[derive(Debug, Allocative)]
1327#[allocative(bound = "C, I, W: Allocative")]
1328pub struct CustomCollectionView<C, I, W> {
1329    collection: ByteCollectionView<C, W>,
1330    #[allocative(skip)]
1331    _phantom: PhantomData<I>,
1332}
1333
1334impl<I: Send + Sync, W: View> View for CustomCollectionView<W::Context, I, W> {
1335    const NUM_INIT_KEYS: usize = ByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1336
1337    type Context = W::Context;
1338
1339    fn context(&self) -> &Self::Context {
1340        self.collection.context()
1341    }
1342
1343    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1344        ByteCollectionView::<_, W>::pre_load(context)
1345    }
1346
1347    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1348        let collection = ByteCollectionView::post_load(context, values)?;
1349        Ok(CustomCollectionView {
1350            collection,
1351            _phantom: PhantomData,
1352        })
1353    }
1354
1355    fn rollback(&mut self) {
1356        self.collection.rollback()
1357    }
1358
1359    async fn has_pending_changes(&self) -> bool {
1360        self.collection.has_pending_changes().await
1361    }
1362
1363    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
1364        self.collection.pre_save(batch)
1365    }
1366
1367    fn post_save(&mut self) {
1368        self.collection.post_save()
1369    }
1370
1371    fn clear(&mut self) {
1372        self.collection.clear()
1373    }
1374}
1375
1376impl<I: Send + Sync, W: ClonableView> ClonableView for CustomCollectionView<W::Context, I, W> {
1377    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1378        Ok(CustomCollectionView {
1379            collection: self.collection.clone_unchecked()?,
1380            _phantom: PhantomData,
1381        })
1382    }
1383}
1384
1385impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
1386    /// Loads a subview for the data at the given index in the collection. If an entry
1387    /// is absent then a default entry is added to the collection. The resulting view
1388    /// can be modified.
1389    /// ```rust
1390    /// # tokio_test::block_on(async {
1391    /// # use linera_views::context::MemoryContext;
1392    /// # use linera_views::collection_view::CustomCollectionView;
1393    /// # use linera_views::register_view::RegisterView;
1394    /// # use linera_views::views::View;
1395    /// # let context = MemoryContext::new_for_testing(());
1396    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1397    ///     CustomCollectionView::load(context).await.unwrap();
1398    /// let subview = view.load_entry_mut(&23).await.unwrap();
1399    /// let value = subview.get();
1400    /// assert_eq!(*value, String::default());
1401    /// # })
1402    /// ```
1403    pub async fn load_entry_mut<Q>(&mut self, index: &Q) -> Result<&mut W, ViewError>
1404    where
1405        I: Borrow<Q>,
1406        Q: CustomSerialize,
1407    {
1408        let short_key = index.to_custom_bytes()?;
1409        self.collection.load_entry_mut(&short_key).await
1410    }
1411
1412    /// Loads a subview for the data at the given index in the collection. If an entry
1413    /// is absent then `None` is returned. The resulting view cannot be modified.
1414    /// May fail if one subview is already being visited.
1415    /// ```rust
1416    /// # tokio_test::block_on(async {
1417    /// # use linera_views::context::MemoryContext;
1418    /// # use linera_views::collection_view::CustomCollectionView;
1419    /// # use linera_views::register_view::RegisterView;
1420    /// # use linera_views::views::View;
1421    /// # let context = MemoryContext::new_for_testing(());
1422    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1423    ///     CustomCollectionView::load(context).await.unwrap();
1424    /// {
1425    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1426    /// }
1427    /// {
1428    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1429    ///     let value = subview.get();
1430    ///     assert_eq!(*value, String::default());
1431    /// }
1432    /// assert!(view.try_load_entry(&24).await.unwrap().is_none());
1433    /// # })
1434    /// ```
1435    pub async fn try_load_entry<Q>(
1436        &self,
1437        index: &Q,
1438    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1439    where
1440        I: Borrow<Q>,
1441        Q: CustomSerialize,
1442    {
1443        let short_key = index.to_custom_bytes()?;
1444        self.collection.try_load_entry(&short_key).await
1445    }
1446
1447    /// Load multiple entries for reading at once.
1448    /// The entries in indices have to be all distinct.
1449    /// ```rust
1450    /// # tokio_test::block_on(async {
1451    /// # use linera_views::context::MemoryContext;
1452    /// # use linera_views::collection_view::CustomCollectionView;
1453    /// # use linera_views::register_view::RegisterView;
1454    /// # use linera_views::views::View;
1455    /// # let context = MemoryContext::new_for_testing(());
1456    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1457    ///     CustomCollectionView::load(context).await.unwrap();
1458    /// {
1459    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1460    /// }
1461    /// let subviews = view.try_load_entries(&[23, 42]).await.unwrap();
1462    /// let value0 = subviews[0].as_ref().unwrap().get();
1463    /// assert_eq!(*value0, String::default());
1464    /// # })
1465    /// ```
1466    pub async fn try_load_entries<'a, Q>(
1467        &self,
1468        indices: impl IntoIterator<Item = &'a Q>,
1469    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError>
1470    where
1471        I: Borrow<Q>,
1472        Q: CustomSerialize + 'a,
1473    {
1474        let short_keys = indices
1475            .into_iter()
1476            .map(|index| index.to_custom_bytes())
1477            .collect::<Result<_, _>>()?;
1478        self.collection.try_load_entries(short_keys).await
1479    }
1480
1481    /// Loads multiple entries for reading at once with their keys.
1482    /// The entries in indices have to be all distinct.
1483    /// ```rust
1484    /// # tokio_test::block_on(async {
1485    /// # use linera_views::context::MemoryContext;
1486    /// # use linera_views::collection_view::CustomCollectionView;
1487    /// # use linera_views::register_view::RegisterView;
1488    /// # use linera_views::views::View;
1489    /// # let context = MemoryContext::new_for_testing(());
1490    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1491    ///     CustomCollectionView::load(context).await.unwrap();
1492    /// {
1493    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1494    /// }
1495    /// let indices = [23, 42];
1496    /// let subviews = view.try_load_entries_pairs(indices).await.unwrap();
1497    /// let value0 = subviews[0].1.as_ref().unwrap().get();
1498    /// assert_eq!(*value0, String::default());
1499    /// # })
1500    /// ```
1501    pub async fn try_load_entries_pairs<Q>(
1502        &self,
1503        indices: impl IntoIterator<Item = Q>,
1504    ) -> Result<Vec<(Q, Option<ReadGuardedView<W>>)>, ViewError>
1505    where
1506        I: Borrow<Q>,
1507        Q: CustomSerialize + Clone,
1508    {
1509        let indices_vec: Vec<Q> = indices.into_iter().collect();
1510        let values = self.try_load_entries(indices_vec.iter()).await?;
1511        Ok(indices_vec.into_iter().zip(values).collect())
1512    }
1513
1514    /// Load all entries for reading at once.
1515    /// ```rust
1516    /// # tokio_test::block_on(async {
1517    /// # use linera_views::context::MemoryContext;
1518    /// # use linera_views::collection_view::CustomCollectionView;
1519    /// # use linera_views::register_view::RegisterView;
1520    /// # use linera_views::views::View;
1521    /// # let context = MemoryContext::new_for_testing(());
1522    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1523    ///     CustomCollectionView::load(context).await.unwrap();
1524    /// {
1525    ///     let _subview = view.load_entry_mut(&23).await.unwrap();
1526    /// }
1527    /// let subviews = view.try_load_all_entries().await.unwrap();
1528    /// assert_eq!(subviews.len(), 1);
1529    /// # })
1530    /// ```
1531    pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError>
1532    where
1533        I: CustomSerialize,
1534    {
1535        let results = self.collection.try_load_all_entries().await?;
1536        results
1537            .into_iter()
1538            .map(|(short_key, view)| {
1539                let index = I::from_custom_bytes(&short_key)?;
1540                Ok((index, view))
1541            })
1542            .collect()
1543    }
1544
1545    /// Marks the entry so that it is removed in the next flush.
1546    /// ```rust
1547    /// # tokio_test::block_on(async {
1548    /// # use linera_views::context::MemoryContext;
1549    /// # use linera_views::collection_view::CustomCollectionView;
1550    /// # use linera_views::register_view::RegisterView;
1551    /// # use linera_views::views::View;
1552    /// # let context = MemoryContext::new_for_testing(());
1553    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1554    ///     CustomCollectionView::load(context).await.unwrap();
1555    /// let subview = view.load_entry_mut(&23).await.unwrap();
1556    /// let value = subview.get_mut();
1557    /// *value = String::from("Hello");
1558    /// view.reset_entry_to_default(&23).unwrap();
1559    /// let subview = view.load_entry_mut(&23).await.unwrap();
1560    /// let value = subview.get_mut();
1561    /// assert_eq!(*value, String::default());
1562    /// # })
1563    /// ```
1564    pub fn reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1565    where
1566        I: Borrow<Q>,
1567        Q: CustomSerialize,
1568    {
1569        let short_key = index.to_custom_bytes()?;
1570        self.collection.reset_entry_to_default(&short_key)
1571    }
1572
1573    /// Removes an entry from the `CollectionView`. If absent nothing happens.
1574    /// ```rust
1575    /// # tokio_test::block_on(async {
1576    /// # use linera_views::context::MemoryContext;
1577    /// # use linera_views::collection_view::CustomCollectionView;
1578    /// # use linera_views::register_view::RegisterView;
1579    /// # use linera_views::views::View;
1580    /// # let context = MemoryContext::new_for_testing(());
1581    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1582    ///     CustomCollectionView::load(context).await.unwrap();
1583    /// let subview = view.load_entry_mut(&23).await.unwrap();
1584    /// let value = subview.get_mut();
1585    /// assert_eq!(*value, String::default());
1586    /// view.remove_entry(&23);
1587    /// let keys = view.indices().await.unwrap();
1588    /// assert_eq!(keys.len(), 0);
1589    /// # })
1590    /// ```
1591    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1592    where
1593        I: Borrow<Q>,
1594        Q: CustomSerialize,
1595    {
1596        let short_key = index.to_custom_bytes()?;
1597        self.collection.remove_entry(short_key);
1598        Ok(())
1599    }
1600
1601    /// Gets the extra data.
1602    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1603        self.collection.extra()
1604    }
1605}
1606
1607impl<I: CustomSerialize + Send, W: View> CustomCollectionView<W::Context, I, W> {
1608    /// Returns the list of indices in the collection in the order determined by the custom serialization.
1609    /// ```rust
1610    /// # tokio_test::block_on(async {
1611    /// # use linera_views::context::MemoryContext;
1612    /// # use linera_views::collection_view::CustomCollectionView;
1613    /// # use linera_views::register_view::RegisterView;
1614    /// # use linera_views::views::View;
1615    /// # let context = MemoryContext::new_for_testing(());
1616    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1617    ///     CustomCollectionView::load(context).await.unwrap();
1618    /// view.load_entry_mut(&23).await.unwrap();
1619    /// view.load_entry_mut(&25).await.unwrap();
1620    /// let indices = view.indices().await.unwrap();
1621    /// assert_eq!(indices, vec![23, 25]);
1622    /// # })
1623    /// ```
1624    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
1625        let mut indices = Vec::new();
1626        self.for_each_index(|index| {
1627            indices.push(index);
1628            Ok(())
1629        })
1630        .await?;
1631        Ok(indices)
1632    }
1633
1634    /// Returns the number of entries in the collection.
1635    /// ```rust
1636    /// # tokio_test::block_on(async {
1637    /// # use linera_views::context::MemoryContext;
1638    /// # use linera_views::collection_view::CollectionView;
1639    /// # use linera_views::register_view::RegisterView;
1640    /// # use linera_views::views::View;
1641    /// # let context = MemoryContext::new_for_testing(());
1642    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1643    ///     CollectionView::load(context).await.unwrap();
1644    /// view.load_entry_mut(&23).await.unwrap();
1645    /// view.load_entry_mut(&25).await.unwrap();
1646    /// assert_eq!(view.count().await.unwrap(), 2);
1647    /// # })
1648    /// ```
1649    pub async fn count(&self) -> Result<usize, ViewError> {
1650        self.collection.count().await
1651    }
1652}
1653
1654impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
1655    /// Applies a function f on each index. Indices are visited in an order
1656    /// determined by the custom serialization. If the function f returns false,
1657    /// then the loop ends prematurely.
1658    /// ```rust
1659    /// # tokio_test::block_on(async {
1660    /// # use linera_views::context::MemoryContext;
1661    /// # use linera_views::collection_view::CustomCollectionView;
1662    /// # use linera_views::register_view::RegisterView;
1663    /// # use linera_views::views::View;
1664    /// # let context = MemoryContext::new_for_testing(());
1665    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1666    ///     CustomCollectionView::load(context).await.unwrap();
1667    /// view.load_entry_mut(&28).await.unwrap();
1668    /// view.load_entry_mut(&24).await.unwrap();
1669    /// view.load_entry_mut(&23).await.unwrap();
1670    /// let mut part_indices = Vec::new();
1671    /// view.for_each_index_while(|index| {
1672    ///     part_indices.push(index);
1673    ///     Ok(part_indices.len() < 2)
1674    /// })
1675    /// .await
1676    /// .unwrap();
1677    /// assert_eq!(part_indices, vec![23, 24]);
1678    /// # })
1679    /// ```
1680    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1681    where
1682        F: FnMut(I) -> Result<bool, ViewError> + Send,
1683    {
1684        self.collection
1685            .for_each_key_while(|key| {
1686                let index = I::from_custom_bytes(key)?;
1687                f(index)
1688            })
1689            .await?;
1690        Ok(())
1691    }
1692
1693    /// Applies a function on each index. Indices are visited in an order
1694    /// determined by the custom serialization.
1695    /// ```rust
1696    /// # tokio_test::block_on(async {
1697    /// # use linera_views::context::MemoryContext;
1698    /// # use linera_views::collection_view::CustomCollectionView;
1699    /// # use linera_views::register_view::RegisterView;
1700    /// # use linera_views::views::View;
1701    /// # let context = MemoryContext::new_for_testing(());
1702    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1703    ///     CustomCollectionView::load(context).await.unwrap();
1704    /// view.load_entry_mut(&28).await.unwrap();
1705    /// view.load_entry_mut(&24).await.unwrap();
1706    /// view.load_entry_mut(&23).await.unwrap();
1707    /// let mut indices = Vec::new();
1708    /// view.for_each_index(|index| {
1709    ///     indices.push(index);
1710    ///     Ok(())
1711    /// })
1712    /// .await
1713    /// .unwrap();
1714    /// assert_eq!(indices, vec![23, 24, 28]);
1715    /// # })
1716    /// ```
1717    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1718    where
1719        F: FnMut(I) -> Result<(), ViewError> + Send,
1720    {
1721        self.collection
1722            .for_each_key(|key| {
1723                let index = I::from_custom_bytes(key)?;
1724                f(index)
1725            })
1726            .await?;
1727        Ok(())
1728    }
1729}
1730
1731impl<I, W: HashableView> HashableView for CustomCollectionView<W::Context, I, W>
1732where
1733    Self: View,
1734{
1735    type Hasher = sha3::Sha3_256;
1736
1737    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1738        self.collection.hash_mut().await
1739    }
1740
1741    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1742        self.collection.hash().await
1743    }
1744}
1745
1746/// Type wrapping `ByteCollectionView` while memoizing the hash.
1747pub type HashedByteCollectionView<C, W> =
1748    WrappedHashableContainerView<C, ByteCollectionView<C, W>, HasherOutput>;
1749
1750/// Wrapper around `ByteCollectionView` to compute hashes based on the history of changes.
1751pub type HistoricallyHashedByteCollectionView<C, W> =
1752    HistoricallyHashableView<C, ByteCollectionView<C, W>>;
1753
1754/// Type wrapping `CollectionView` while memoizing the hash.
1755pub type HashedCollectionView<C, I, W> =
1756    WrappedHashableContainerView<C, CollectionView<C, I, W>, HasherOutput>;
1757
1758/// Wrapper around `CollectionView` to compute hashes based on the history of changes.
1759pub type HistoricallyHashedCollectionView<C, I, W> =
1760    HistoricallyHashableView<C, CollectionView<C, I, W>>;
1761
1762/// Type wrapping `CustomCollectionView` while memoizing the hash.
1763pub type HashedCustomCollectionView<C, I, W> =
1764    WrappedHashableContainerView<C, CustomCollectionView<C, I, W>, HasherOutput>;
1765
1766/// Wrapper around `CustomCollectionView` to compute hashes based on the history of changes.
1767pub type HistoricallyHashedCustomCollectionView<C, I, W> =
1768    HistoricallyHashableView<C, CustomCollectionView<C, I, W>>;
1769
1770#[cfg(with_graphql)]
1771mod graphql {
1772    use std::borrow::Cow;
1773
1774    use super::{CollectionView, CustomCollectionView, ReadGuardedView};
1775    use crate::{
1776        graphql::{hash_name, mangle, missing_key_error, Entry, MapInput},
1777        views::View,
1778    };
1779
1780    impl<T: async_graphql::OutputType> async_graphql::OutputType for ReadGuardedView<'_, T> {
1781        fn type_name() -> Cow<'static, str> {
1782            T::type_name()
1783        }
1784
1785        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
1786            T::create_type_info(registry)
1787        }
1788
1789        async fn resolve(
1790            &self,
1791            ctx: &async_graphql::ContextSelectionSet<'_>,
1792            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
1793        ) -> async_graphql::ServerResult<async_graphql::Value> {
1794            (**self).resolve(ctx, field).await
1795        }
1796    }
1797
1798    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
1799        async_graphql::TypeName for CollectionView<C, K, V>
1800    {
1801        fn type_name() -> Cow<'static, str> {
1802            format!(
1803                "CollectionView_{}_{}_{:08x}",
1804                mangle(K::type_name()),
1805                mangle(V::type_name()),
1806                hash_name::<(K, V)>(),
1807            )
1808            .into()
1809        }
1810    }
1811
1812    #[async_graphql::Object(cache_control(no_cache), name_type)]
1813    impl<K, V> CollectionView<V::Context, K, V>
1814    where
1815        K: async_graphql::InputType
1816            + async_graphql::OutputType
1817            + serde::ser::Serialize
1818            + serde::de::DeserializeOwned
1819            + std::fmt::Debug,
1820        V: View + async_graphql::OutputType,
1821    {
1822        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
1823            Ok(self.indices().await?)
1824        }
1825
1826        #[graphql(derived(name = "count"))]
1827        async fn count_(&self) -> Result<u32, async_graphql::Error> {
1828            Ok(self.count().await? as u32)
1829        }
1830
1831        async fn entry(
1832            &self,
1833            key: K,
1834        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
1835            let value = self
1836                .try_load_entry(&key)
1837                .await?
1838                .ok_or_else(|| missing_key_error(&key))?;
1839            Ok(Entry { value, key })
1840        }
1841
1842        async fn entries(
1843            &self,
1844            input: Option<MapInput<K>>,
1845        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
1846            let keys = if let Some(keys) = input
1847                .and_then(|input| input.filters)
1848                .and_then(|filters| filters.keys)
1849            {
1850                keys
1851            } else {
1852                self.indices().await?
1853            };
1854
1855            let values = self.try_load_entries(&keys).await?;
1856            Ok(values
1857                .into_iter()
1858                .zip(keys)
1859                .filter_map(|(value, key)| value.map(|value| Entry { value, key }))
1860                .collect())
1861        }
1862    }
1863
1864    impl<C: Send + Sync, K: async_graphql::InputType, V: async_graphql::OutputType>
1865        async_graphql::TypeName for CustomCollectionView<C, K, V>
1866    {
1867        fn type_name() -> Cow<'static, str> {
1868            format!(
1869                "CustomCollectionView_{}_{}_{:08x}",
1870                mangle(K::type_name()),
1871                mangle(V::type_name()),
1872                hash_name::<(K, V)>(),
1873            )
1874            .into()
1875        }
1876    }
1877
1878    #[async_graphql::Object(cache_control(no_cache), name_type)]
1879    impl<K, V> CustomCollectionView<V::Context, K, V>
1880    where
1881        K: async_graphql::InputType
1882            + async_graphql::OutputType
1883            + crate::common::CustomSerialize
1884            + std::fmt::Debug,
1885        V: View + async_graphql::OutputType,
1886    {
1887        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
1888            Ok(self.indices().await?)
1889        }
1890
1891        #[graphql(derived(name = "count"))]
1892        async fn count_(&self) -> Result<u32, async_graphql::Error> {
1893            Ok(self.count().await? as u32)
1894        }
1895
1896        async fn entry(
1897            &self,
1898            key: K,
1899        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
1900            let value = self
1901                .try_load_entry(&key)
1902                .await?
1903                .ok_or_else(|| missing_key_error(&key))?;
1904            Ok(Entry { value, key })
1905        }
1906
1907        async fn entries(
1908            &self,
1909            input: Option<MapInput<K>>,
1910        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
1911            let keys = if let Some(keys) = input
1912                .and_then(|input| input.filters)
1913                .and_then(|filters| filters.keys)
1914            {
1915                keys
1916            } else {
1917                self.indices().await?
1918            };
1919
1920            let values = self.try_load_entries(&keys).await?;
1921            Ok(values
1922                .into_iter()
1923                .zip(keys)
1924                .filter_map(|(value, key)| value.map(|value| Entry { value, key }))
1925                .collect())
1926        }
1927    }
1928}