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};
11
12use async_lock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
13#[cfg(with_metrics)]
14use linera_base::prometheus_util::MeasureLatency as _;
15use serde::{de::DeserializeOwned, Serialize};
16
17use crate::{
18    batch::Batch,
19    common::{CustomSerialize, HasherOutput, Update},
20    context::{BaseKey, Context},
21    hashable_wrapper::WrappedHashableContainerView,
22    store::{KeyIterable, ReadableKeyValueStore as _},
23    views::{ClonableView, HashableView, Hasher, View, ViewError, MIN_VIEW_TAG},
24};
25
26#[cfg(with_metrics)]
27mod metrics {
28    use std::sync::LazyLock;
29
30    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
31    use prometheus::HistogramVec;
32
33    /// The runtime of hash computation
34    pub static COLLECTION_VIEW_HASH_RUNTIME: LazyLock<HistogramVec> = LazyLock::new(|| {
35        register_histogram_vec(
36            "collection_view_hash_runtime",
37            "CollectionView hash runtime",
38            &[],
39            exponential_bucket_latencies(5.0),
40        )
41    });
42}
43
44/// A view that supports accessing a collection of views of the same kind, indexed by a
45/// `Vec<u8>`, one subview at a time.
46#[derive(Debug)]
47pub struct ByteCollectionView<C, W> {
48    context: C,
49    delete_storage_first: bool,
50    updates: RwLock<BTreeMap<Vec<u8>, Update<W>>>,
51}
52
53/// A read-only accessor for a particular subview in a [`CollectionView`].
54pub struct ReadGuardedView<'a, W> {
55    guard: RwLockReadGuard<'a, BTreeMap<Vec<u8>, Update<W>>>,
56    short_key: Vec<u8>,
57}
58
59impl<W> std::ops::Deref for ReadGuardedView<'_, W> {
60    type Target = W;
61
62    fn deref(&self) -> &W {
63        let Update::Set(view) = self.guard.get(&self.short_key).unwrap() else {
64            unreachable!();
65        };
66        view
67    }
68}
69
70/// We need to find new base keys in order to implement `CollectionView`.
71/// We do this by appending a value to the base key.
72///
73/// Sub-views in a collection share a common key prefix, like in other view types. However,
74/// just concatenating the shared prefix with sub-view keys makes it impossible to distinguish if a
75/// given key belongs to child sub-view or a grandchild sub-view (consider for example if a
76/// collection is stored inside the collection).
77#[repr(u8)]
78enum KeyTag {
79    /// Prefix for specifying an index and serves to indicate the existence of an entry in the collection.
80    Index = MIN_VIEW_TAG,
81    /// Prefix for specifying as the prefix for the sub-view.
82    Subview,
83}
84
85impl<W: View> View for ByteCollectionView<W::Context, W> {
86    const NUM_INIT_KEYS: usize = 0;
87
88    type Context = W::Context;
89
90    fn context(&self) -> &Self::Context {
91        &self.context
92    }
93
94    fn pre_load(_context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
95        Ok(vec![])
96    }
97
98    fn post_load(context: Self::Context, _values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
99        Ok(Self {
100            context,
101            delete_storage_first: false,
102            updates: RwLock::new(BTreeMap::new()),
103        })
104    }
105
106    async fn load(context: Self::Context) -> Result<Self, ViewError> {
107        Self::post_load(context, &[])
108    }
109
110    fn rollback(&mut self) {
111        self.delete_storage_first = false;
112        self.updates.get_mut().clear();
113    }
114
115    async fn has_pending_changes(&self) -> bool {
116        if self.delete_storage_first {
117            return true;
118        }
119        let updates = self.updates.read().await;
120        !updates.is_empty()
121    }
122
123    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
124        let mut delete_view = false;
125        if self.delete_storage_first {
126            delete_view = true;
127            batch.delete_key_prefix(self.context.base_key().bytes.clone());
128            for (index, update) in mem::take(self.updates.get_mut()) {
129                if let Update::Set(mut view) = update {
130                    view.flush(batch)?;
131                    self.add_index(batch, &index);
132                    delete_view = false;
133                }
134            }
135        } else {
136            for (index, update) in mem::take(self.updates.get_mut()) {
137                match update {
138                    Update::Set(mut view) => {
139                        view.flush(batch)?;
140                        self.add_index(batch, &index);
141                    }
142                    Update::Removed => {
143                        let key_subview = self.get_subview_key(&index);
144                        let key_index = self.get_index_key(&index);
145                        batch.delete_key(key_index);
146                        batch.delete_key_prefix(key_subview);
147                    }
148                }
149            }
150        }
151        self.delete_storage_first = false;
152        Ok(delete_view)
153    }
154
155    fn clear(&mut self) {
156        self.delete_storage_first = true;
157        self.updates.get_mut().clear();
158    }
159}
160
161impl<W: ClonableView> ClonableView for ByteCollectionView<W::Context, W> {
162    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
163        let cloned_updates = self
164            .updates
165            .get_mut()
166            .iter_mut()
167            .map(|(key, value)| {
168                let cloned_value = match value {
169                    Update::Removed => Update::Removed,
170                    Update::Set(view) => Update::Set(view.clone_unchecked()?),
171                };
172                Ok((key.clone(), cloned_value))
173            })
174            .collect::<Result<_, ViewError>>()?;
175
176        Ok(ByteCollectionView {
177            context: self.context.clone(),
178            delete_storage_first: self.delete_storage_first,
179            updates: RwLock::new(cloned_updates),
180        })
181    }
182}
183
184impl<W: View> ByteCollectionView<W::Context, W> {
185    fn get_index_key(&self, index: &[u8]) -> Vec<u8> {
186        self.context
187            .base_key()
188            .base_tag_index(KeyTag::Index as u8, index)
189    }
190
191    fn get_subview_key(&self, index: &[u8]) -> Vec<u8> {
192        self.context
193            .base_key()
194            .base_tag_index(KeyTag::Subview as u8, index)
195    }
196
197    fn add_index(&self, batch: &mut Batch, index: &[u8]) {
198        let key = self.get_index_key(index);
199        batch.put_key_value_bytes(key, vec![]);
200    }
201
202    /// Loads a subview for the data at the given index in the collection. If an entry
203    /// is absent then a default entry is added to the collection. The resulting view
204    /// can be modified.
205    /// ```rust
206    /// # tokio_test::block_on(async {
207    /// # use linera_views::context::MemoryContext;
208    /// # use linera_views::collection_view::ByteCollectionView;
209    /// # use linera_views::register_view::RegisterView;
210    /// # use linera_views::views::View;
211    /// # let context = MemoryContext::new_for_testing(());
212    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
213    ///     ByteCollectionView::load(context).await.unwrap();
214    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
215    /// let value = subview.get();
216    /// assert_eq!(*value, String::default());
217    /// # })
218    /// ```
219    pub async fn load_entry_mut(&mut self, short_key: &[u8]) -> Result<&mut W, ViewError> {
220        self.do_load_entry_mut(short_key).await
221    }
222
223    /// Loads a subview for the data at the given index in the collection. If an entry
224    /// is absent then a default entry is added to the collection. The resulting view
225    /// is read-only.
226    /// ```rust
227    /// # tokio_test::block_on(async {
228    /// # use linera_views::context::MemoryContext;
229    /// # use linera_views::collection_view::ByteCollectionView;
230    /// # use linera_views::register_view::RegisterView;
231    /// # use linera_views::views::View;
232    /// # let context = MemoryContext::new_for_testing(());
233    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
234    ///     ByteCollectionView::load(context).await.unwrap();
235    /// view.load_entry_mut(&[0, 1]).await.unwrap();
236    /// let subview = view.load_entry_or_insert(&[0, 1]).await.unwrap();
237    /// let value = subview.get();
238    /// assert_eq!(*value, String::default());
239    /// # })
240    /// ```
241    pub async fn load_entry_or_insert(&mut self, short_key: &[u8]) -> Result<&W, ViewError> {
242        Ok(self.do_load_entry_mut(short_key).await?)
243    }
244
245    /// Loads a subview for the data at the given index in the collection. If an entry
246    /// is absent then `None` is returned. The resulting view cannot be modified.
247    /// May fail if one subview is already being visited.
248    /// ```rust
249    /// # tokio_test::block_on(async {
250    /// # use linera_views::context::MemoryContext;
251    /// # use linera_views::collection_view::ByteCollectionView;
252    /// # use linera_views::register_view::RegisterView;
253    /// # use linera_views::views::View;
254    /// # let context = MemoryContext::new_for_testing(());
255    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
256    ///     ByteCollectionView::load(context).await.unwrap();
257    /// {
258    ///     let _subview = view.load_entry_or_insert(&[0, 1]).await.unwrap();
259    /// }
260    /// {
261    ///     let subview = view.try_load_entry(&[0, 1]).await.unwrap().unwrap();
262    ///     let value = subview.get();
263    ///     assert_eq!(*value, String::default());
264    /// }
265    /// assert!(view.try_load_entry(&[0, 2]).await.unwrap().is_none());
266    /// # })
267    /// ```
268    pub async fn try_load_entry(
269        &self,
270        short_key: &[u8],
271    ) -> Result<Option<ReadGuardedView<W>>, ViewError> {
272        let mut updates = self
273            .updates
274            .try_write()
275            .ok_or(ViewError::CannotAcquireCollectionEntry)?;
276        match updates.entry(short_key.to_vec()) {
277            btree_map::Entry::Occupied(entry) => {
278                let entry = entry.into_mut();
279                match entry {
280                    Update::Set(_) => {
281                        let guard = RwLockWriteGuard::downgrade(updates);
282                        Ok(Some(ReadGuardedView {
283                            guard,
284                            short_key: short_key.to_vec(),
285                        }))
286                    }
287                    Update::Removed => Ok(None),
288                }
289            }
290            btree_map::Entry::Vacant(entry) => {
291                let key_index = self
292                    .context
293                    .base_key()
294                    .base_tag_index(KeyTag::Index as u8, short_key);
295                if !self.delete_storage_first
296                    && self.context.store().contains_key(&key_index).await?
297                {
298                    let key = self
299                        .context
300                        .base_key()
301                        .base_tag_index(KeyTag::Subview as u8, short_key);
302                    let context = self.context.clone_with_base_key(key);
303                    let view = W::load(context).await?;
304                    entry.insert(Update::Set(view));
305                    let guard = RwLockWriteGuard::downgrade(updates);
306                    Ok(Some(ReadGuardedView {
307                        guard,
308                        short_key: short_key.to_vec(),
309                    }))
310                } else {
311                    Ok(None)
312                }
313            }
314        }
315    }
316
317    /// Resets an entry to the default value.
318    /// ```rust
319    /// # tokio_test::block_on(async {
320    /// # use linera_views::context::MemoryContext;
321    /// # use linera_views::collection_view::ByteCollectionView;
322    /// # use linera_views::register_view::RegisterView;
323    /// # use linera_views::views::View;
324    /// # let context = MemoryContext::new_for_testing(());
325    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
326    ///     ByteCollectionView::load(context).await.unwrap();
327    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
328    /// let value = subview.get_mut();
329    /// *value = String::from("Hello");
330    /// view.reset_entry_to_default(&[0, 1]).unwrap();
331    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
332    /// let value = subview.get_mut();
333    /// assert_eq!(*value, String::default());
334    /// # })
335    /// ```
336    pub fn reset_entry_to_default(&mut self, short_key: &[u8]) -> Result<(), ViewError> {
337        let key = self
338            .context
339            .base_key()
340            .base_tag_index(KeyTag::Subview as u8, short_key);
341        let context = self.context.clone_with_base_key(key);
342        let view = W::new(context)?;
343        self.updates
344            .get_mut()
345            .insert(short_key.to_vec(), Update::Set(view));
346        Ok(())
347    }
348
349    /// Tests if the collection contains a specified key and returns a boolean.
350    /// ```rust
351    /// # tokio_test::block_on(async {
352    /// # use linera_views::context::MemoryContext;
353    /// # use linera_views::collection_view::ByteCollectionView;
354    /// # use linera_views::register_view::RegisterView;
355    /// # use linera_views::views::View;
356    /// # let context = MemoryContext::new_for_testing(());
357    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
358    ///     ByteCollectionView::load(context).await.unwrap();
359    /// {
360    ///     let _subview = view.load_entry_mut(&[0, 1]).await.unwrap();
361    /// }
362    /// assert!(view.contains_key(&[0, 1]).await.unwrap());
363    /// assert!(!view.contains_key(&[0, 2]).await.unwrap());
364    /// # })
365    /// ```
366    pub async fn contains_key(&self, short_key: &[u8]) -> Result<bool, ViewError> {
367        let updates = self.updates.write().await;
368        Ok(match updates.get(short_key) {
369            Some(entry) => match entry {
370                Update::Set(_view) => true,
371                _entry @ Update::Removed => false,
372            },
373            None => {
374                let key_index = self
375                    .context
376                    .base_key()
377                    .base_tag_index(KeyTag::Index as u8, short_key);
378                !self.delete_storage_first && self.context.store().contains_key(&key_index).await?
379            }
380        })
381    }
382
383    /// Marks the entry as removed. If absent then nothing is done.
384    /// ```rust
385    /// # tokio_test::block_on(async {
386    /// # use linera_views::context::MemoryContext;
387    /// # use linera_views::collection_view::ByteCollectionView;
388    /// # use linera_views::register_view::RegisterView;
389    /// # use linera_views::views::View;
390    /// # let context = MemoryContext::new_for_testing(());
391    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
392    ///     ByteCollectionView::load(context).await.unwrap();
393    /// let subview = view.load_entry_mut(&[0, 1]).await.unwrap();
394    /// let value = subview.get_mut();
395    /// assert_eq!(*value, String::default());
396    /// view.remove_entry(vec![0, 1]);
397    /// let keys = view.keys().await.unwrap();
398    /// assert_eq!(keys.len(), 0);
399    /// # })
400    /// ```
401    pub fn remove_entry(&mut self, short_key: Vec<u8>) {
402        if self.delete_storage_first {
403            // Optimization: No need to mark `short_key` for deletion as we are going to remove all the keys at once.
404            self.updates.get_mut().remove(&short_key);
405        } else {
406            self.updates.get_mut().insert(short_key, Update::Removed);
407        }
408    }
409
410    /// Gets the extra data.
411    pub fn extra(&self) -> &<W::Context as Context>::Extra {
412        self.context.extra()
413    }
414
415    async fn do_load_entry_mut(&mut self, short_key: &[u8]) -> Result<&mut W, ViewError> {
416        match self.updates.get_mut().entry(short_key.to_vec()) {
417            btree_map::Entry::Occupied(entry) => {
418                let entry = entry.into_mut();
419                match entry {
420                    Update::Set(view) => Ok(view),
421                    Update::Removed => {
422                        let key = self
423                            .context
424                            .base_key()
425                            .base_tag_index(KeyTag::Subview as u8, short_key);
426                        let context = self.context.clone_with_base_key(key);
427                        // Obtain a view and set its pending state to the default (e.g. empty) state
428                        let view = W::new(context)?;
429                        *entry = Update::Set(view);
430                        let Update::Set(view) = entry else {
431                            unreachable!();
432                        };
433                        Ok(view)
434                    }
435                }
436            }
437            btree_map::Entry::Vacant(entry) => {
438                let key = self
439                    .context
440                    .base_key()
441                    .base_tag_index(KeyTag::Subview as u8, short_key);
442                let context = self.context.clone_with_base_key(key);
443                let view = if self.delete_storage_first {
444                    W::new(context)?
445                } else {
446                    W::load(context).await?
447                };
448                let Update::Set(view) = entry.insert(Update::Set(view)) else {
449                    unreachable!();
450                };
451                Ok(view)
452            }
453        }
454    }
455}
456
457impl<W: View> ByteCollectionView<W::Context, W> {
458    /// Applies a function f on each index (aka key). Keys are visited in the
459    /// lexicographic order. If the function returns false, then the loop
460    /// ends prematurely.
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    /// view.load_entry_mut(&[0, 1]).await.unwrap();
471    /// view.load_entry_mut(&[0, 2]).await.unwrap();
472    /// let mut count = 0;
473    /// view.for_each_key_while(|_key| {
474    ///     count += 1;
475    ///     Ok(count < 1)
476    /// })
477    /// .await
478    /// .unwrap();
479    /// assert_eq!(count, 1);
480    /// # })
481    /// ```
482    pub async fn for_each_key_while<F>(&self, mut f: F) -> Result<(), ViewError>
483    where
484        F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
485    {
486        let updates = self.updates.write().await;
487        let mut updates = updates.iter();
488        let mut update = updates.next();
489        if !self.delete_storage_first {
490            let base = self.get_index_key(&[]);
491            for index in self
492                .context
493                .store()
494                .find_keys_by_prefix(&base)
495                .await?
496                .iterator()
497            {
498                let index = index?;
499                loop {
500                    match update {
501                        Some((key, value)) if key.as_slice() <= index => {
502                            if let Update::Set(_) = value {
503                                if !f(key)? {
504                                    return Ok(());
505                                }
506                            }
507                            update = updates.next();
508                            if key == index {
509                                break;
510                            }
511                        }
512                        _ => {
513                            if !f(index)? {
514                                return Ok(());
515                            }
516                            break;
517                        }
518                    }
519                }
520            }
521        }
522        while let Some((key, value)) = update {
523            if let Update::Set(_) = value {
524                if !f(key)? {
525                    return Ok(());
526                }
527            }
528            update = updates.next();
529        }
530        Ok(())
531    }
532
533    /// Applies a function f on each index (aka key). Keys are visited in a
534    /// lexicographic order.
535    /// ```rust
536    /// # tokio_test::block_on(async {
537    /// # use linera_views::context::MemoryContext;
538    /// # use linera_views::collection_view::ByteCollectionView;
539    /// # use linera_views::register_view::RegisterView;
540    /// # use linera_views::views::View;
541    /// # let context = MemoryContext::new_for_testing(());
542    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
543    ///     ByteCollectionView::load(context).await.unwrap();
544    /// view.load_entry_mut(&[0, 1]).await.unwrap();
545    /// view.load_entry_mut(&[0, 2]).await.unwrap();
546    /// let mut count = 0;
547    /// view.for_each_key(|_key| {
548    ///     count += 1;
549    ///     Ok(())
550    /// })
551    /// .await
552    /// .unwrap();
553    /// assert_eq!(count, 2);
554    /// # })
555    /// ```
556    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
557    where
558        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
559    {
560        self.for_each_key_while(|key| {
561            f(key)?;
562            Ok(true)
563        })
564        .await
565    }
566
567    /// Returns the list of keys in the collection. The order is lexicographic.
568    /// ```rust
569    /// # tokio_test::block_on(async {
570    /// # use linera_views::context::MemoryContext;
571    /// # use linera_views::collection_view::ByteCollectionView;
572    /// # use linera_views::register_view::RegisterView;
573    /// # use linera_views::views::View;
574    /// # let context = MemoryContext::new_for_testing(());
575    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
576    ///     ByteCollectionView::load(context).await.unwrap();
577    /// view.load_entry_mut(&[0, 1]).await.unwrap();
578    /// view.load_entry_mut(&[0, 2]).await.unwrap();
579    /// let keys = view.keys().await.unwrap();
580    /// assert_eq!(keys, vec![vec![0, 1], vec![0, 2]]);
581    /// # })
582    /// ```
583    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
584        let mut keys = Vec::new();
585        self.for_each_key(|key| {
586            keys.push(key.to_vec());
587            Ok(())
588        })
589        .await?;
590        Ok(keys)
591    }
592
593    /// Returns the number of entries in the collection.
594    /// ```rust
595    /// # tokio_test::block_on(async {
596    /// # use linera_views::context::MemoryContext;
597    /// # use linera_views::collection_view::ByteCollectionView;
598    /// # use linera_views::register_view::RegisterView;
599    /// # use linera_views::views::View;
600    /// # let context = MemoryContext::new_for_testing(());
601    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
602    ///     ByteCollectionView::load(context).await.unwrap();
603    /// view.load_entry_mut(&[0, 1]).await.unwrap();
604    /// view.load_entry_mut(&[0, 2]).await.unwrap();
605    /// assert_eq!(view.count().await.unwrap(), 2);
606    /// # })
607    /// ```
608    pub async fn count(&self) -> Result<usize, ViewError> {
609        let mut count = 0;
610        self.for_each_key(|_key| {
611            count += 1;
612            Ok(())
613        })
614        .await?;
615        Ok(count)
616    }
617}
618
619impl<W: HashableView> HashableView for ByteCollectionView<W::Context, W> {
620    type Hasher = sha3::Sha3_256;
621
622    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
623        #[cfg(with_metrics)]
624        let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
625        let mut hasher = sha3::Sha3_256::default();
626        let keys = self.keys().await?;
627        let count = keys.len() as u32;
628        hasher.update_with_bcs_bytes(&count)?;
629        let updates = self.updates.get_mut();
630        for key in keys {
631            hasher.update_with_bytes(&key)?;
632            let hash = match updates.get_mut(&key) {
633                Some(entry) => {
634                    let Update::Set(view) = entry else {
635                        unreachable!();
636                    };
637                    view.hash_mut().await?
638                }
639                None => {
640                    let key = self
641                        .context
642                        .base_key()
643                        .base_tag_index(KeyTag::Subview as u8, &key);
644                    let context = self.context.clone_with_base_key(key);
645                    let mut view = W::load(context).await?;
646                    view.hash_mut().await?
647                }
648            };
649            hasher.write_all(hash.as_ref())?;
650        }
651        Ok(hasher.finalize())
652    }
653
654    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
655        #[cfg(with_metrics)]
656        let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
657        let mut hasher = sha3::Sha3_256::default();
658        let keys = self.keys().await?;
659        let count = keys.len() as u32;
660        hasher.update_with_bcs_bytes(&count)?;
661        let updates = self.updates.read().await;
662        for key in keys {
663            hasher.update_with_bytes(&key)?;
664            let hash = match updates.get(&key) {
665                Some(entry) => {
666                    let Update::Set(view) = entry else {
667                        unreachable!();
668                    };
669                    view.hash().await?
670                }
671                None => {
672                    let key = self
673                        .context
674                        .base_key()
675                        .base_tag_index(KeyTag::Subview as u8, &key);
676                    let context = self.context.clone_with_base_key(key);
677                    let view = W::load(context).await?;
678                    view.hash().await?
679                }
680            };
681            hasher.write_all(hash.as_ref())?;
682        }
683        Ok(hasher.finalize())
684    }
685}
686
687/// A view that supports accessing a collection of views of the same kind, indexed by a
688/// key, one subview at a time.
689#[derive(Debug)]
690pub struct CollectionView<C, I, W> {
691    collection: ByteCollectionView<C, W>,
692    _phantom: PhantomData<I>,
693}
694
695impl<W: View, I> View for CollectionView<W::Context, I, W>
696where
697    I: Send + Sync + Serialize + DeserializeOwned,
698{
699    const NUM_INIT_KEYS: usize = ByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
700
701    type Context = W::Context;
702
703    fn context(&self) -> &Self::Context {
704        self.collection.context()
705    }
706
707    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
708        ByteCollectionView::<W::Context, W>::pre_load(context)
709    }
710
711    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
712        let collection = ByteCollectionView::post_load(context, values)?;
713        Ok(CollectionView {
714            collection,
715            _phantom: PhantomData,
716        })
717    }
718
719    async fn load(context: Self::Context) -> Result<Self, ViewError> {
720        Self::post_load(context, &[])
721    }
722
723    fn rollback(&mut self) {
724        self.collection.rollback()
725    }
726
727    async fn has_pending_changes(&self) -> bool {
728        self.collection.has_pending_changes().await
729    }
730
731    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
732        self.collection.flush(batch)
733    }
734
735    fn clear(&mut self) {
736        self.collection.clear()
737    }
738}
739
740impl<I, W: ClonableView> ClonableView for CollectionView<W::Context, I, W>
741where
742    I: Send + Sync + Serialize + DeserializeOwned,
743{
744    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
745        Ok(CollectionView {
746            collection: self.collection.clone_unchecked()?,
747            _phantom: PhantomData,
748        })
749    }
750}
751
752impl<I: Serialize, W: View> CollectionView<W::Context, I, W> {
753    /// Loads a subview for the data at the given index in the collection. If an entry
754    /// is absent then a default entry is added to the collection. The resulting view
755    /// can be modified.
756    /// ```rust
757    /// # tokio_test::block_on(async {
758    /// # use linera_views::context::MemoryContext;
759    /// # use linera_views::collection_view::CollectionView;
760    /// # use linera_views::register_view::RegisterView;
761    /// # use linera_views::views::View;
762    /// # let context = MemoryContext::new_for_testing(());
763    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
764    ///     CollectionView::load(context).await.unwrap();
765    /// let subview = view.load_entry_mut(&23).await.unwrap();
766    /// let value = subview.get();
767    /// assert_eq!(*value, String::default());
768    /// # })
769    /// ```
770    pub async fn load_entry_mut<Q>(&mut self, index: &Q) -> Result<&mut W, ViewError>
771    where
772        I: Borrow<Q>,
773        Q: Serialize + ?Sized,
774    {
775        let short_key = BaseKey::derive_short_key(index)?;
776        self.collection.load_entry_mut(&short_key).await
777    }
778
779    /// Loads a subview for the data at the given index in the collection. If an entry
780    /// is absent then a default entry is added to the collection. The resulting view
781    /// is read-only.
782    /// ```rust
783    /// # tokio_test::block_on(async {
784    /// # use linera_views::context::MemoryContext;
785    /// # use linera_views::collection_view::CollectionView;
786    /// # use linera_views::register_view::RegisterView;
787    /// # use linera_views::views::View;
788    /// # let context = MemoryContext::new_for_testing(());
789    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
790    ///     CollectionView::load(context).await.unwrap();
791    /// view.load_entry_mut(&23).await.unwrap();
792    /// let subview = view.load_entry_or_insert(&23).await.unwrap();
793    /// let value = subview.get();
794    /// assert_eq!(*value, String::default());
795    /// # })
796    /// ```
797    pub async fn load_entry_or_insert<Q>(&mut self, index: &Q) -> Result<&W, ViewError>
798    where
799        I: Borrow<Q>,
800        Q: Serialize + ?Sized,
801    {
802        let short_key = BaseKey::derive_short_key(index)?;
803        self.collection.load_entry_or_insert(&short_key).await
804    }
805
806    /// Loads a subview for the data at the given index in the collection. If an entry
807    /// is absent then `None` is returned. The resulting view cannot be modified.
808    /// May fail if one subview is already being visited.
809    /// ```rust
810    /// # tokio_test::block_on(async {
811    /// # use linera_views::context::MemoryContext;
812    /// # use linera_views::collection_view::CollectionView;
813    /// # use linera_views::register_view::RegisterView;
814    /// # use linera_views::views::View;
815    /// # let context = MemoryContext::new_for_testing(());
816    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
817    ///     CollectionView::load(context).await.unwrap();
818    /// {
819    ///     let _subview = view.load_entry_or_insert(&23).await.unwrap();
820    /// }
821    /// {
822    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
823    ///     let value = subview.get();
824    ///     assert_eq!(*value, String::default());
825    /// }
826    /// assert!(view.try_load_entry(&24).await.unwrap().is_none());
827    /// # })
828    /// ```
829    pub async fn try_load_entry<Q>(
830        &self,
831        index: &Q,
832    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
833    where
834        I: Borrow<Q>,
835        Q: Serialize + ?Sized,
836    {
837        let short_key = BaseKey::derive_short_key(index)?;
838        self.collection.try_load_entry(&short_key).await
839    }
840
841    /// Resets an entry to the default value.
842    /// ```rust
843    /// # tokio_test::block_on(async {
844    /// # use linera_views::context::MemoryContext;
845    /// # use linera_views::collection_view::CollectionView;
846    /// # use linera_views::register_view::RegisterView;
847    /// # use linera_views::views::View;
848    /// # let context = MemoryContext::new_for_testing(());
849    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
850    ///     CollectionView::load(context).await.unwrap();
851    /// let subview = view.load_entry_mut(&23).await.unwrap();
852    /// let value = subview.get_mut();
853    /// *value = String::from("Hello");
854    /// view.reset_entry_to_default(&23).unwrap();
855    /// let subview = view.load_entry_mut(&23).await.unwrap();
856    /// let value = subview.get_mut();
857    /// assert_eq!(*value, String::default());
858    /// # })
859    /// ```
860    pub fn reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
861    where
862        I: Borrow<Q>,
863        Q: Serialize + ?Sized,
864    {
865        let short_key = BaseKey::derive_short_key(index)?;
866        self.collection.reset_entry_to_default(&short_key)
867    }
868
869    /// Removes an entry from the `CollectionView`. If absent nothing happens.
870    /// ```rust
871    /// # tokio_test::block_on(async {
872    /// # use linera_views::context::MemoryContext;
873    /// # use linera_views::collection_view::CollectionView;
874    /// # use linera_views::register_view::RegisterView;
875    /// # use linera_views::views::View;
876    /// # let context = MemoryContext::new_for_testing(());
877    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
878    ///     CollectionView::load(context).await.unwrap();
879    /// let subview = view.load_entry_mut(&23).await.unwrap();
880    /// let value = subview.get_mut();
881    /// assert_eq!(*value, String::default());
882    /// view.remove_entry(&23);
883    /// let keys = view.indices().await.unwrap();
884    /// assert_eq!(keys.len(), 0);
885    /// # })
886    /// ```
887    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
888    where
889        I: Borrow<Q>,
890        Q: Serialize + ?Sized,
891    {
892        let short_key = BaseKey::derive_short_key(index)?;
893        self.collection.remove_entry(short_key);
894        Ok(())
895    }
896
897    /// Gets the extra data.
898    pub fn extra(&self) -> &<W::Context as Context>::Extra {
899        self.collection.extra()
900    }
901}
902
903impl<I, W: View> CollectionView<W::Context, I, W>
904where
905    I: Sync + Clone + Send + Serialize + DeserializeOwned,
906{
907    /// Returns the list of indices in the collection in the order determined by
908    /// the serialization.
909    /// ```rust
910    /// # tokio_test::block_on(async {
911    /// # use linera_views::context::MemoryContext;
912    /// # use linera_views::collection_view::CollectionView;
913    /// # use linera_views::register_view::RegisterView;
914    /// # use linera_views::views::View;
915    /// # let context = MemoryContext::new_for_testing(());
916    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
917    ///     CollectionView::load(context).await.unwrap();
918    /// view.load_entry_mut(&23).await.unwrap();
919    /// view.load_entry_mut(&25).await.unwrap();
920    /// let indices = view.indices().await.unwrap();
921    /// assert_eq!(indices.len(), 2);
922    /// # })
923    /// ```
924    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
925        let mut indices = Vec::new();
926        self.for_each_index(|index| {
927            indices.push(index);
928            Ok(())
929        })
930        .await?;
931        Ok(indices)
932    }
933
934    /// Returns the number of entries in the collection.
935    /// ```rust
936    /// # tokio_test::block_on(async {
937    /// # use linera_views::context::MemoryContext;
938    /// # use linera_views::collection_view::CollectionView;
939    /// # use linera_views::register_view::RegisterView;
940    /// # use linera_views::views::View;
941    /// # let context = MemoryContext::new_for_testing(());
942    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
943    ///     CollectionView::load(context).await.unwrap();
944    /// view.load_entry_mut(&23).await.unwrap();
945    /// view.load_entry_mut(&25).await.unwrap();
946    /// assert_eq!(view.count().await.unwrap(), 2);
947    /// # })
948    /// ```
949    pub async fn count(&self) -> Result<usize, ViewError> {
950        self.collection.count().await
951    }
952}
953
954impl<I: DeserializeOwned, W: View> CollectionView<W::Context, I, W> {
955    /// Applies a function f on each index. Indices are visited in an order
956    /// determined by the serialization. If the function returns false then
957    /// the loop ends prematurely.
958    /// ```rust
959    /// # tokio_test::block_on(async {
960    /// # use linera_views::context::MemoryContext;
961    /// # use linera_views::collection_view::CollectionView;
962    /// # use linera_views::register_view::RegisterView;
963    /// # use linera_views::views::View;
964    /// # let context = MemoryContext::new_for_testing(());
965    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
966    ///     CollectionView::load(context).await.unwrap();
967    /// view.load_entry_mut(&23).await.unwrap();
968    /// view.load_entry_mut(&24).await.unwrap();
969    /// let mut count = 0;
970    /// view.for_each_index_while(|_key| {
971    ///     count += 1;
972    ///     Ok(count < 1)
973    /// })
974    /// .await
975    /// .unwrap();
976    /// assert_eq!(count, 1);
977    /// # })
978    /// ```
979    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
980    where
981        F: FnMut(I) -> Result<bool, ViewError> + Send,
982    {
983        self.collection
984            .for_each_key_while(|key| {
985                let index = BaseKey::deserialize_value(key)?;
986                f(index)
987            })
988            .await?;
989        Ok(())
990    }
991
992    /// Applies a function f on each index. Indices are visited in an order
993    /// determined by the serialization.
994    /// ```rust
995    /// # tokio_test::block_on(async {
996    /// # use linera_views::context::MemoryContext;
997    /// # use linera_views::collection_view::CollectionView;
998    /// # use linera_views::register_view::RegisterView;
999    /// # use linera_views::views::View;
1000    /// # let context = MemoryContext::new_for_testing(());
1001    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1002    ///     CollectionView::load(context).await.unwrap();
1003    /// view.load_entry_mut(&23).await.unwrap();
1004    /// view.load_entry_mut(&28).await.unwrap();
1005    /// let mut count = 0;
1006    /// view.for_each_index(|_key| {
1007    ///     count += 1;
1008    ///     Ok(())
1009    /// })
1010    /// .await
1011    /// .unwrap();
1012    /// assert_eq!(count, 2);
1013    /// # })
1014    /// ```
1015    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1016    where
1017        F: FnMut(I) -> Result<(), ViewError> + Send,
1018    {
1019        self.collection
1020            .for_each_key(|key| {
1021                let index = BaseKey::deserialize_value(key)?;
1022                f(index)
1023            })
1024            .await?;
1025        Ok(())
1026    }
1027}
1028
1029impl<I, W: HashableView> HashableView for CollectionView<W::Context, I, W>
1030where
1031    I: Clone + Send + Sync + Serialize + DeserializeOwned,
1032{
1033    type Hasher = sha3::Sha3_256;
1034
1035    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1036        self.collection.hash_mut().await
1037    }
1038
1039    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1040        self.collection.hash().await
1041    }
1042}
1043
1044/// A map view that serializes the indices.
1045#[derive(Debug)]
1046pub struct CustomCollectionView<C, I, W> {
1047    collection: ByteCollectionView<C, W>,
1048    _phantom: PhantomData<I>,
1049}
1050
1051impl<I: Send + Sync, W: View> View for CustomCollectionView<W::Context, I, W> {
1052    const NUM_INIT_KEYS: usize = ByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1053
1054    type Context = W::Context;
1055
1056    fn context(&self) -> &Self::Context {
1057        self.collection.context()
1058    }
1059
1060    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1061        ByteCollectionView::<_, W>::pre_load(context)
1062    }
1063
1064    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1065        let collection = ByteCollectionView::post_load(context, values)?;
1066        Ok(CustomCollectionView {
1067            collection,
1068            _phantom: PhantomData,
1069        })
1070    }
1071
1072    async fn load(context: Self::Context) -> Result<Self, ViewError> {
1073        Self::post_load(context, &[])
1074    }
1075
1076    fn rollback(&mut self) {
1077        self.collection.rollback()
1078    }
1079
1080    async fn has_pending_changes(&self) -> bool {
1081        self.collection.has_pending_changes().await
1082    }
1083
1084    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
1085        self.collection.flush(batch)
1086    }
1087
1088    fn clear(&mut self) {
1089        self.collection.clear()
1090    }
1091}
1092
1093impl<I: Send + Sync, W: ClonableView> ClonableView for CustomCollectionView<W::Context, I, W> {
1094    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1095        Ok(CustomCollectionView {
1096            collection: self.collection.clone_unchecked()?,
1097            _phantom: PhantomData,
1098        })
1099    }
1100}
1101
1102impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
1103    /// Loads a subview for the data at the given index in the collection. If an entry
1104    /// is absent then a default entry is added to the collection. The resulting view
1105    /// can be modified.
1106    /// ```rust
1107    /// # tokio_test::block_on(async {
1108    /// # use linera_views::context::MemoryContext;
1109    /// # use linera_views::collection_view::CustomCollectionView;
1110    /// # use linera_views::register_view::RegisterView;
1111    /// # use linera_views::views::View;
1112    /// # let context = MemoryContext::new_for_testing(());
1113    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1114    ///     CustomCollectionView::load(context).await.unwrap();
1115    /// let subview = view.load_entry_mut(&23).await.unwrap();
1116    /// let value = subview.get();
1117    /// assert_eq!(*value, String::default());
1118    /// # })
1119    /// ```
1120    pub async fn load_entry_mut<Q>(&mut self, index: &Q) -> Result<&mut W, ViewError>
1121    where
1122        I: Borrow<Q>,
1123        Q: CustomSerialize,
1124    {
1125        let short_key = index.to_custom_bytes()?;
1126        self.collection.load_entry_mut(&short_key).await
1127    }
1128
1129    /// Loads a subview for the data at the given index in the collection. If an entry
1130    /// is absent then a default entry is added to the collection. The resulting view
1131    /// is read-only.
1132    /// ```rust
1133    /// # tokio_test::block_on(async {
1134    /// # use linera_views::context::MemoryContext;
1135    /// # use linera_views::collection_view::CustomCollectionView;
1136    /// # use linera_views::register_view::RegisterView;
1137    /// # use linera_views::views::View;
1138    /// # let context = MemoryContext::new_for_testing(());
1139    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1140    ///     CustomCollectionView::load(context).await.unwrap();
1141    /// view.load_entry_mut(&23).await.unwrap();
1142    /// let subview = view.load_entry_or_insert(&23).await.unwrap();
1143    /// let value = subview.get();
1144    /// assert_eq!(*value, String::default());
1145    /// # })
1146    /// ```
1147    pub async fn load_entry_or_insert<Q>(&mut self, index: &Q) -> Result<&W, ViewError>
1148    where
1149        I: Borrow<Q>,
1150        Q: CustomSerialize,
1151    {
1152        let short_key = index.to_custom_bytes()?;
1153        self.collection.load_entry_or_insert(&short_key).await
1154    }
1155
1156    /// Loads a subview for the data at the given index in the collection. If an entry
1157    /// is absent then `None` is returned. The resulting view cannot be modified.
1158    /// May fail if one subview is already being visited.
1159    /// ```rust
1160    /// # tokio_test::block_on(async {
1161    /// # use linera_views::context::MemoryContext;
1162    /// # use linera_views::collection_view::CustomCollectionView;
1163    /// # use linera_views::register_view::RegisterView;
1164    /// # use linera_views::views::View;
1165    /// # let context = MemoryContext::new_for_testing(());
1166    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1167    ///     CustomCollectionView::load(context).await.unwrap();
1168    /// {
1169    ///     let _subview = view.load_entry_or_insert(&23).await.unwrap();
1170    /// }
1171    /// {
1172    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1173    ///     let value = subview.get();
1174    ///     assert_eq!(*value, String::default());
1175    /// }
1176    /// assert!(view.try_load_entry(&24).await.unwrap().is_none());
1177    /// # })
1178    /// ```
1179    pub async fn try_load_entry<Q>(
1180        &self,
1181        index: &Q,
1182    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1183    where
1184        I: Borrow<Q>,
1185        Q: CustomSerialize,
1186    {
1187        let short_key = index.to_custom_bytes()?;
1188        self.collection.try_load_entry(&short_key).await
1189    }
1190
1191    /// Marks the entry so that it is removed in the next flush.
1192    /// ```rust
1193    /// # tokio_test::block_on(async {
1194    /// # use linera_views::context::MemoryContext;
1195    /// # use linera_views::collection_view::CustomCollectionView;
1196    /// # use linera_views::register_view::RegisterView;
1197    /// # use linera_views::views::View;
1198    /// # let context = MemoryContext::new_for_testing(());
1199    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1200    ///     CustomCollectionView::load(context).await.unwrap();
1201    /// let subview = view.load_entry_mut(&23).await.unwrap();
1202    /// let value = subview.get_mut();
1203    /// *value = String::from("Hello");
1204    /// view.reset_entry_to_default(&23).unwrap();
1205    /// let subview = view.load_entry_mut(&23).await.unwrap();
1206    /// let value = subview.get_mut();
1207    /// assert_eq!(*value, String::default());
1208    /// # })
1209    /// ```
1210    pub fn reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1211    where
1212        I: Borrow<Q>,
1213        Q: CustomSerialize,
1214    {
1215        let short_key = index.to_custom_bytes()?;
1216        self.collection.reset_entry_to_default(&short_key)
1217    }
1218
1219    /// Removes an entry from the `CollectionView`. If absent nothing happens.
1220    /// ```rust
1221    /// # tokio_test::block_on(async {
1222    /// # use linera_views::context::MemoryContext;
1223    /// # use linera_views::collection_view::CustomCollectionView;
1224    /// # use linera_views::register_view::RegisterView;
1225    /// # use linera_views::views::View;
1226    /// # let context = MemoryContext::new_for_testing(());
1227    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1228    ///     CustomCollectionView::load(context).await.unwrap();
1229    /// let subview = view.load_entry_mut(&23).await.unwrap();
1230    /// let value = subview.get_mut();
1231    /// assert_eq!(*value, String::default());
1232    /// view.remove_entry(&23);
1233    /// let keys = view.indices().await.unwrap();
1234    /// assert_eq!(keys.len(), 0);
1235    /// # })
1236    /// ```
1237    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1238    where
1239        I: Borrow<Q>,
1240        Q: CustomSerialize,
1241    {
1242        let short_key = index.to_custom_bytes()?;
1243        self.collection.remove_entry(short_key);
1244        Ok(())
1245    }
1246
1247    /// Gets the extra data.
1248    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1249        self.collection.extra()
1250    }
1251}
1252
1253impl<I: CustomSerialize + Send, W: View> CustomCollectionView<W::Context, I, W> {
1254    /// Returns the list of indices in the collection in the order determined by the custom serialization.
1255    /// ```rust
1256    /// # tokio_test::block_on(async {
1257    /// # use linera_views::context::MemoryContext;
1258    /// # use linera_views::collection_view::CustomCollectionView;
1259    /// # use linera_views::register_view::RegisterView;
1260    /// # use linera_views::views::View;
1261    /// # let context = MemoryContext::new_for_testing(());
1262    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1263    ///     CustomCollectionView::load(context).await.unwrap();
1264    /// view.load_entry_mut(&23).await.unwrap();
1265    /// view.load_entry_mut(&25).await.unwrap();
1266    /// let indices = view.indices().await.unwrap();
1267    /// assert_eq!(indices, vec![23, 25]);
1268    /// # })
1269    /// ```
1270    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
1271        let mut indices = Vec::new();
1272        self.for_each_index(|index| {
1273            indices.push(index);
1274            Ok(())
1275        })
1276        .await?;
1277        Ok(indices)
1278    }
1279
1280    /// Returns the number of entries in the collection.
1281    /// ```rust
1282    /// # tokio_test::block_on(async {
1283    /// # use linera_views::context::MemoryContext;
1284    /// # use linera_views::collection_view::CollectionView;
1285    /// # use linera_views::register_view::RegisterView;
1286    /// # use linera_views::views::View;
1287    /// # let context = MemoryContext::new_for_testing(());
1288    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1289    ///     CollectionView::load(context).await.unwrap();
1290    /// view.load_entry_mut(&23).await.unwrap();
1291    /// view.load_entry_mut(&25).await.unwrap();
1292    /// assert_eq!(view.count().await.unwrap(), 2);
1293    /// # })
1294    /// ```
1295    pub async fn count(&self) -> Result<usize, ViewError> {
1296        self.collection.count().await
1297    }
1298}
1299
1300impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
1301    /// Applies a function f on each index. Indices are visited in an order
1302    /// determined by the custom serialization. If the function f returns false,
1303    /// then the loop ends prematurely.
1304    /// ```rust
1305    /// # tokio_test::block_on(async {
1306    /// # use linera_views::context::MemoryContext;
1307    /// # use linera_views::collection_view::CustomCollectionView;
1308    /// # use linera_views::register_view::RegisterView;
1309    /// # use linera_views::views::View;
1310    /// # let context = MemoryContext::new_for_testing(());
1311    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1312    ///     CustomCollectionView::load(context).await.unwrap();
1313    /// view.load_entry_mut(&28).await.unwrap();
1314    /// view.load_entry_mut(&24).await.unwrap();
1315    /// view.load_entry_mut(&23).await.unwrap();
1316    /// let mut part_indices = Vec::new();
1317    /// view.for_each_index_while(|index| {
1318    ///     part_indices.push(index);
1319    ///     Ok(part_indices.len() < 2)
1320    /// })
1321    /// .await
1322    /// .unwrap();
1323    /// assert_eq!(part_indices, vec![23, 24]);
1324    /// # })
1325    /// ```
1326    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1327    where
1328        F: FnMut(I) -> Result<bool, ViewError> + Send,
1329    {
1330        self.collection
1331            .for_each_key_while(|key| {
1332                let index = I::from_custom_bytes(key)?;
1333                f(index)
1334            })
1335            .await?;
1336        Ok(())
1337    }
1338
1339    /// Applies a function on each index. Indices are visited in an order
1340    /// determined by the custom serialization.
1341    /// ```rust
1342    /// # tokio_test::block_on(async {
1343    /// # use linera_views::context::MemoryContext;
1344    /// # use linera_views::collection_view::CustomCollectionView;
1345    /// # use linera_views::register_view::RegisterView;
1346    /// # use linera_views::views::View;
1347    /// # let context = MemoryContext::new_for_testing(());
1348    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1349    ///     CustomCollectionView::load(context).await.unwrap();
1350    /// view.load_entry_mut(&28).await.unwrap();
1351    /// view.load_entry_mut(&24).await.unwrap();
1352    /// view.load_entry_mut(&23).await.unwrap();
1353    /// let mut indices = Vec::new();
1354    /// view.for_each_index(|index| {
1355    ///     indices.push(index);
1356    ///     Ok(())
1357    /// })
1358    /// .await
1359    /// .unwrap();
1360    /// assert_eq!(indices, vec![23, 24, 28]);
1361    /// # })
1362    /// ```
1363    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1364    where
1365        F: FnMut(I) -> Result<(), ViewError> + Send,
1366    {
1367        self.collection
1368            .for_each_key(|key| {
1369                let index = I::from_custom_bytes(key)?;
1370                f(index)
1371            })
1372            .await?;
1373        Ok(())
1374    }
1375}
1376
1377impl<I, W: HashableView> HashableView for CustomCollectionView<W::Context, I, W>
1378where
1379    Self: View,
1380{
1381    type Hasher = sha3::Sha3_256;
1382
1383    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1384        self.collection.hash_mut().await
1385    }
1386
1387    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1388        self.collection.hash().await
1389    }
1390}
1391
1392/// Type wrapping `ByteCollectionView` while memoizing the hash.
1393pub type HashedByteCollectionView<C, W> =
1394    WrappedHashableContainerView<C, ByteCollectionView<C, W>, HasherOutput>;
1395
1396/// Type wrapping `CollectionView` while memoizing the hash.
1397pub type HashedCollectionView<C, I, W> =
1398    WrappedHashableContainerView<C, CollectionView<C, I, W>, HasherOutput>;
1399
1400/// Type wrapping `CustomCollectionView` while memoizing the hash.
1401pub type HashedCustomCollectionView<C, I, W> =
1402    WrappedHashableContainerView<C, CustomCollectionView<C, I, W>, HasherOutput>;
1403
1404#[cfg(with_graphql)]
1405mod graphql {
1406    use std::borrow::Cow;
1407
1408    use super::{CollectionView, CustomCollectionView, ReadGuardedView};
1409    use crate::{
1410        graphql::{hash_name, mangle, missing_key_error, Entry, MapFilters, MapInput},
1411        views::View,
1412    };
1413
1414    impl<T: async_graphql::OutputType> async_graphql::OutputType for ReadGuardedView<'_, T> {
1415        fn type_name() -> Cow<'static, str> {
1416            T::type_name()
1417        }
1418
1419        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
1420            T::create_type_info(registry)
1421        }
1422
1423        async fn resolve(
1424            &self,
1425            ctx: &async_graphql::ContextSelectionSet<'_>,
1426            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
1427        ) -> async_graphql::ServerResult<async_graphql::Value> {
1428            (**self).resolve(ctx, field).await
1429        }
1430    }
1431
1432    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
1433        async_graphql::TypeName for CollectionView<C, K, V>
1434    {
1435        fn type_name() -> Cow<'static, str> {
1436            format!(
1437                "CollectionView_{}_{}_{:08x}",
1438                mangle(K::type_name()),
1439                mangle(V::type_name()),
1440                hash_name::<(K, V)>(),
1441            )
1442            .into()
1443        }
1444    }
1445
1446    #[async_graphql::Object(cache_control(no_cache), name_type)]
1447    impl<K, V> CollectionView<V::Context, K, V>
1448    where
1449        K: async_graphql::InputType
1450            + async_graphql::OutputType
1451            + serde::ser::Serialize
1452            + serde::de::DeserializeOwned
1453            + std::fmt::Debug
1454            + Clone,
1455        V: View + async_graphql::OutputType,
1456        MapInput<K>: async_graphql::InputType,
1457        MapFilters<K>: async_graphql::InputType,
1458    {
1459        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
1460            Ok(self.indices().await?)
1461        }
1462
1463        async fn entry(
1464            &self,
1465            key: K,
1466        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
1467            let value = self
1468                .try_load_entry(&key)
1469                .await?
1470                .ok_or_else(|| missing_key_error(&key))?;
1471            Ok(Entry { value, key })
1472        }
1473
1474        async fn entries(
1475            &self,
1476            input: Option<MapInput<K>>,
1477        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
1478            let keys = if let Some(keys) = input
1479                .and_then(|input| input.filters)
1480                .and_then(|filters| filters.keys)
1481            {
1482                keys
1483            } else {
1484                self.indices().await?
1485            };
1486
1487            let mut values = vec![];
1488            for key in keys {
1489                let value = self
1490                    .try_load_entry(&key)
1491                    .await?
1492                    .ok_or_else(|| missing_key_error(&key))?;
1493                values.push(Entry { value, key })
1494            }
1495
1496            Ok(values)
1497        }
1498    }
1499
1500    impl<C: Send + Sync, K: async_graphql::InputType, V: async_graphql::OutputType>
1501        async_graphql::TypeName for CustomCollectionView<C, K, V>
1502    {
1503        fn type_name() -> Cow<'static, str> {
1504            format!(
1505                "CustomCollectionView_{}_{}_{:08x}",
1506                mangle(K::type_name()),
1507                mangle(V::type_name()),
1508                hash_name::<(K, V)>(),
1509            )
1510            .into()
1511        }
1512    }
1513
1514    #[async_graphql::Object(cache_control(no_cache), name_type)]
1515    impl<K, V> CustomCollectionView<V::Context, K, V>
1516    where
1517        K: async_graphql::InputType
1518            + async_graphql::OutputType
1519            + crate::common::CustomSerialize
1520            + std::fmt::Debug,
1521        V: View + async_graphql::OutputType,
1522        MapInput<K>: async_graphql::InputType,
1523        MapFilters<K>: async_graphql::InputType,
1524    {
1525        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
1526            Ok(self.indices().await?)
1527        }
1528
1529        async fn entry(
1530            &self,
1531            key: K,
1532        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
1533            let value = self
1534                .try_load_entry(&key)
1535                .await?
1536                .ok_or_else(|| missing_key_error(&key))?;
1537            Ok(Entry { value, key })
1538        }
1539
1540        async fn entries(
1541            &self,
1542            input: Option<MapInput<K>>,
1543        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
1544            let keys = if let Some(keys) = input
1545                .and_then(|input| input.filters)
1546                .and_then(|filters| filters.keys)
1547            {
1548                keys
1549            } else {
1550                self.indices().await?
1551            };
1552
1553            let mut values = vec![];
1554            for key in keys {
1555                let value = self
1556                    .try_load_entry(&key)
1557                    .await?
1558                    .ok_or_else(|| missing_key_error(&key))?;
1559                values.push(Entry { value, key })
1560            }
1561
1562            Ok(values)
1563        }
1564    }
1565}