Skip to main content

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