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::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.context.store().find_keys_by_prefix(&base).await? {
492                loop {
493                    match update {
494                        Some((key, value)) if key <= &index => {
495                            if let Update::Set(_) = value {
496                                if !f(key)? {
497                                    return Ok(());
498                                }
499                            }
500                            update = updates.next();
501                            if key == &index {
502                                break;
503                            }
504                        }
505                        _ => {
506                            if !f(&index)? {
507                                return Ok(());
508                            }
509                            break;
510                        }
511                    }
512                }
513            }
514        }
515        while let Some((key, value)) = update {
516            if let Update::Set(_) = value {
517                if !f(key)? {
518                    return Ok(());
519                }
520            }
521            update = updates.next();
522        }
523        Ok(())
524    }
525
526    /// Applies a function f on each index (aka key). Keys are visited in a
527    /// lexicographic order.
528    /// ```rust
529    /// # tokio_test::block_on(async {
530    /// # use linera_views::context::MemoryContext;
531    /// # use linera_views::collection_view::ByteCollectionView;
532    /// # use linera_views::register_view::RegisterView;
533    /// # use linera_views::views::View;
534    /// # let context = MemoryContext::new_for_testing(());
535    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
536    ///     ByteCollectionView::load(context).await.unwrap();
537    /// view.load_entry_mut(&[0, 1]).await.unwrap();
538    /// view.load_entry_mut(&[0, 2]).await.unwrap();
539    /// let mut count = 0;
540    /// view.for_each_key(|_key| {
541    ///     count += 1;
542    ///     Ok(())
543    /// })
544    /// .await
545    /// .unwrap();
546    /// assert_eq!(count, 2);
547    /// # })
548    /// ```
549    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
550    where
551        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
552    {
553        self.for_each_key_while(|key| {
554            f(key)?;
555            Ok(true)
556        })
557        .await
558    }
559
560    /// Returns the list of keys in the collection. The order is lexicographic.
561    /// ```rust
562    /// # tokio_test::block_on(async {
563    /// # use linera_views::context::MemoryContext;
564    /// # use linera_views::collection_view::ByteCollectionView;
565    /// # use linera_views::register_view::RegisterView;
566    /// # use linera_views::views::View;
567    /// # let context = MemoryContext::new_for_testing(());
568    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
569    ///     ByteCollectionView::load(context).await.unwrap();
570    /// view.load_entry_mut(&[0, 1]).await.unwrap();
571    /// view.load_entry_mut(&[0, 2]).await.unwrap();
572    /// let keys = view.keys().await.unwrap();
573    /// assert_eq!(keys, vec![vec![0, 1], vec![0, 2]]);
574    /// # })
575    /// ```
576    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
577        let mut keys = Vec::new();
578        self.for_each_key(|key| {
579            keys.push(key.to_vec());
580            Ok(())
581        })
582        .await?;
583        Ok(keys)
584    }
585
586    /// Returns the number of entries in the collection.
587    /// ```rust
588    /// # tokio_test::block_on(async {
589    /// # use linera_views::context::MemoryContext;
590    /// # use linera_views::collection_view::ByteCollectionView;
591    /// # use linera_views::register_view::RegisterView;
592    /// # use linera_views::views::View;
593    /// # let context = MemoryContext::new_for_testing(());
594    /// let mut view: ByteCollectionView<_, RegisterView<_, String>> =
595    ///     ByteCollectionView::load(context).await.unwrap();
596    /// view.load_entry_mut(&[0, 1]).await.unwrap();
597    /// view.load_entry_mut(&[0, 2]).await.unwrap();
598    /// assert_eq!(view.count().await.unwrap(), 2);
599    /// # })
600    /// ```
601    pub async fn count(&self) -> Result<usize, ViewError> {
602        let mut count = 0;
603        self.for_each_key(|_key| {
604            count += 1;
605            Ok(())
606        })
607        .await?;
608        Ok(count)
609    }
610}
611
612impl<W: HashableView> HashableView for ByteCollectionView<W::Context, W> {
613    type Hasher = sha3::Sha3_256;
614
615    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
616        #[cfg(with_metrics)]
617        let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
618        let mut hasher = sha3::Sha3_256::default();
619        let keys = self.keys().await?;
620        let count = keys.len() as u32;
621        hasher.update_with_bcs_bytes(&count)?;
622        let updates = self.updates.get_mut();
623        for key in keys {
624            hasher.update_with_bytes(&key)?;
625            let hash = match updates.get_mut(&key) {
626                Some(entry) => {
627                    let Update::Set(view) = entry else {
628                        unreachable!();
629                    };
630                    view.hash_mut().await?
631                }
632                None => {
633                    let key = self
634                        .context
635                        .base_key()
636                        .base_tag_index(KeyTag::Subview as u8, &key);
637                    let context = self.context.clone_with_base_key(key);
638                    let mut view = W::load(context).await?;
639                    view.hash_mut().await?
640                }
641            };
642            hasher.write_all(hash.as_ref())?;
643        }
644        Ok(hasher.finalize())
645    }
646
647    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
648        #[cfg(with_metrics)]
649        let _hash_latency = metrics::COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
650        let mut hasher = sha3::Sha3_256::default();
651        let keys = self.keys().await?;
652        let count = keys.len() as u32;
653        hasher.update_with_bcs_bytes(&count)?;
654        let updates = self.updates.read().await;
655        for key in keys {
656            hasher.update_with_bytes(&key)?;
657            let hash = match updates.get(&key) {
658                Some(entry) => {
659                    let Update::Set(view) = entry else {
660                        unreachable!();
661                    };
662                    view.hash().await?
663                }
664                None => {
665                    let key = self
666                        .context
667                        .base_key()
668                        .base_tag_index(KeyTag::Subview as u8, &key);
669                    let context = self.context.clone_with_base_key(key);
670                    let view = W::load(context).await?;
671                    view.hash().await?
672                }
673            };
674            hasher.write_all(hash.as_ref())?;
675        }
676        Ok(hasher.finalize())
677    }
678}
679
680/// A view that supports accessing a collection of views of the same kind, indexed by a
681/// key, one subview at a time.
682#[derive(Debug)]
683pub struct CollectionView<C, I, W> {
684    collection: ByteCollectionView<C, W>,
685    _phantom: PhantomData<I>,
686}
687
688impl<W: View, I> View for CollectionView<W::Context, I, W>
689where
690    I: Send + Sync + Serialize + DeserializeOwned,
691{
692    const NUM_INIT_KEYS: usize = ByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
693
694    type Context = W::Context;
695
696    fn context(&self) -> &Self::Context {
697        self.collection.context()
698    }
699
700    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
701        ByteCollectionView::<W::Context, W>::pre_load(context)
702    }
703
704    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
705        let collection = ByteCollectionView::post_load(context, values)?;
706        Ok(CollectionView {
707            collection,
708            _phantom: PhantomData,
709        })
710    }
711
712    async fn load(context: Self::Context) -> Result<Self, ViewError> {
713        Self::post_load(context, &[])
714    }
715
716    fn rollback(&mut self) {
717        self.collection.rollback()
718    }
719
720    async fn has_pending_changes(&self) -> bool {
721        self.collection.has_pending_changes().await
722    }
723
724    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
725        self.collection.flush(batch)
726    }
727
728    fn clear(&mut self) {
729        self.collection.clear()
730    }
731}
732
733impl<I, W: ClonableView> ClonableView for CollectionView<W::Context, I, W>
734where
735    I: Send + Sync + Serialize + DeserializeOwned,
736{
737    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
738        Ok(CollectionView {
739            collection: self.collection.clone_unchecked()?,
740            _phantom: PhantomData,
741        })
742    }
743}
744
745impl<I: Serialize, W: View> CollectionView<W::Context, I, W> {
746    /// Loads a subview for the data at the given index in the collection. If an entry
747    /// is absent then a default entry is added to the collection. The resulting view
748    /// can be modified.
749    /// ```rust
750    /// # tokio_test::block_on(async {
751    /// # use linera_views::context::MemoryContext;
752    /// # use linera_views::collection_view::CollectionView;
753    /// # use linera_views::register_view::RegisterView;
754    /// # use linera_views::views::View;
755    /// # let context = MemoryContext::new_for_testing(());
756    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
757    ///     CollectionView::load(context).await.unwrap();
758    /// let subview = view.load_entry_mut(&23).await.unwrap();
759    /// let value = subview.get();
760    /// assert_eq!(*value, String::default());
761    /// # })
762    /// ```
763    pub async fn load_entry_mut<Q>(&mut self, index: &Q) -> Result<&mut W, ViewError>
764    where
765        I: Borrow<Q>,
766        Q: Serialize + ?Sized,
767    {
768        let short_key = BaseKey::derive_short_key(index)?;
769        self.collection.load_entry_mut(&short_key).await
770    }
771
772    /// Loads a subview for the data at the given index in the collection. If an entry
773    /// is absent then a default entry is added to the collection. The resulting view
774    /// is read-only.
775    /// ```rust
776    /// # tokio_test::block_on(async {
777    /// # use linera_views::context::MemoryContext;
778    /// # use linera_views::collection_view::CollectionView;
779    /// # use linera_views::register_view::RegisterView;
780    /// # use linera_views::views::View;
781    /// # let context = MemoryContext::new_for_testing(());
782    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
783    ///     CollectionView::load(context).await.unwrap();
784    /// view.load_entry_mut(&23).await.unwrap();
785    /// let subview = view.load_entry_or_insert(&23).await.unwrap();
786    /// let value = subview.get();
787    /// assert_eq!(*value, String::default());
788    /// # })
789    /// ```
790    pub async fn load_entry_or_insert<Q>(&mut self, index: &Q) -> Result<&W, ViewError>
791    where
792        I: Borrow<Q>,
793        Q: Serialize + ?Sized,
794    {
795        let short_key = BaseKey::derive_short_key(index)?;
796        self.collection.load_entry_or_insert(&short_key).await
797    }
798
799    /// Loads a subview for the data at the given index in the collection. If an entry
800    /// is absent then `None` is returned. The resulting view cannot be modified.
801    /// May fail if one subview is already being visited.
802    /// ```rust
803    /// # tokio_test::block_on(async {
804    /// # use linera_views::context::MemoryContext;
805    /// # use linera_views::collection_view::CollectionView;
806    /// # use linera_views::register_view::RegisterView;
807    /// # use linera_views::views::View;
808    /// # let context = MemoryContext::new_for_testing(());
809    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
810    ///     CollectionView::load(context).await.unwrap();
811    /// {
812    ///     let _subview = view.load_entry_or_insert(&23).await.unwrap();
813    /// }
814    /// {
815    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
816    ///     let value = subview.get();
817    ///     assert_eq!(*value, String::default());
818    /// }
819    /// assert!(view.try_load_entry(&24).await.unwrap().is_none());
820    /// # })
821    /// ```
822    pub async fn try_load_entry<Q>(
823        &self,
824        index: &Q,
825    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
826    where
827        I: Borrow<Q>,
828        Q: Serialize + ?Sized,
829    {
830        let short_key = BaseKey::derive_short_key(index)?;
831        self.collection.try_load_entry(&short_key).await
832    }
833
834    /// Resets an entry to the default value.
835    /// ```rust
836    /// # tokio_test::block_on(async {
837    /// # use linera_views::context::MemoryContext;
838    /// # use linera_views::collection_view::CollectionView;
839    /// # use linera_views::register_view::RegisterView;
840    /// # use linera_views::views::View;
841    /// # let context = MemoryContext::new_for_testing(());
842    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
843    ///     CollectionView::load(context).await.unwrap();
844    /// let subview = view.load_entry_mut(&23).await.unwrap();
845    /// let value = subview.get_mut();
846    /// *value = String::from("Hello");
847    /// view.reset_entry_to_default(&23).unwrap();
848    /// let subview = view.load_entry_mut(&23).await.unwrap();
849    /// let value = subview.get_mut();
850    /// assert_eq!(*value, String::default());
851    /// # })
852    /// ```
853    pub fn reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
854    where
855        I: Borrow<Q>,
856        Q: Serialize + ?Sized,
857    {
858        let short_key = BaseKey::derive_short_key(index)?;
859        self.collection.reset_entry_to_default(&short_key)
860    }
861
862    /// Removes an entry from the `CollectionView`. If absent nothing happens.
863    /// ```rust
864    /// # tokio_test::block_on(async {
865    /// # use linera_views::context::MemoryContext;
866    /// # use linera_views::collection_view::CollectionView;
867    /// # use linera_views::register_view::RegisterView;
868    /// # use linera_views::views::View;
869    /// # let context = MemoryContext::new_for_testing(());
870    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
871    ///     CollectionView::load(context).await.unwrap();
872    /// let subview = view.load_entry_mut(&23).await.unwrap();
873    /// let value = subview.get_mut();
874    /// assert_eq!(*value, String::default());
875    /// view.remove_entry(&23);
876    /// let keys = view.indices().await.unwrap();
877    /// assert_eq!(keys.len(), 0);
878    /// # })
879    /// ```
880    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
881    where
882        I: Borrow<Q>,
883        Q: Serialize + ?Sized,
884    {
885        let short_key = BaseKey::derive_short_key(index)?;
886        self.collection.remove_entry(short_key);
887        Ok(())
888    }
889
890    /// Gets the extra data.
891    pub fn extra(&self) -> &<W::Context as Context>::Extra {
892        self.collection.extra()
893    }
894}
895
896impl<I, W: View> CollectionView<W::Context, I, W>
897where
898    I: Sync + Clone + Send + Serialize + DeserializeOwned,
899{
900    /// Returns the list of indices in the collection in the order determined by
901    /// the serialization.
902    /// ```rust
903    /// # tokio_test::block_on(async {
904    /// # use linera_views::context::MemoryContext;
905    /// # use linera_views::collection_view::CollectionView;
906    /// # use linera_views::register_view::RegisterView;
907    /// # use linera_views::views::View;
908    /// # let context = MemoryContext::new_for_testing(());
909    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
910    ///     CollectionView::load(context).await.unwrap();
911    /// view.load_entry_mut(&23).await.unwrap();
912    /// view.load_entry_mut(&25).await.unwrap();
913    /// let indices = view.indices().await.unwrap();
914    /// assert_eq!(indices.len(), 2);
915    /// # })
916    /// ```
917    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
918        let mut indices = Vec::new();
919        self.for_each_index(|index| {
920            indices.push(index);
921            Ok(())
922        })
923        .await?;
924        Ok(indices)
925    }
926
927    /// Returns the number of entries in the collection.
928    /// ```rust
929    /// # tokio_test::block_on(async {
930    /// # use linera_views::context::MemoryContext;
931    /// # use linera_views::collection_view::CollectionView;
932    /// # use linera_views::register_view::RegisterView;
933    /// # use linera_views::views::View;
934    /// # let context = MemoryContext::new_for_testing(());
935    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
936    ///     CollectionView::load(context).await.unwrap();
937    /// view.load_entry_mut(&23).await.unwrap();
938    /// view.load_entry_mut(&25).await.unwrap();
939    /// assert_eq!(view.count().await.unwrap(), 2);
940    /// # })
941    /// ```
942    pub async fn count(&self) -> Result<usize, ViewError> {
943        self.collection.count().await
944    }
945}
946
947impl<I: DeserializeOwned, W: View> CollectionView<W::Context, I, W> {
948    /// Applies a function f on each index. Indices are visited in an order
949    /// determined by the serialization. If the function returns false then
950    /// the loop ends prematurely.
951    /// ```rust
952    /// # tokio_test::block_on(async {
953    /// # use linera_views::context::MemoryContext;
954    /// # use linera_views::collection_view::CollectionView;
955    /// # use linera_views::register_view::RegisterView;
956    /// # use linera_views::views::View;
957    /// # let context = MemoryContext::new_for_testing(());
958    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
959    ///     CollectionView::load(context).await.unwrap();
960    /// view.load_entry_mut(&23).await.unwrap();
961    /// view.load_entry_mut(&24).await.unwrap();
962    /// let mut count = 0;
963    /// view.for_each_index_while(|_key| {
964    ///     count += 1;
965    ///     Ok(count < 1)
966    /// })
967    /// .await
968    /// .unwrap();
969    /// assert_eq!(count, 1);
970    /// # })
971    /// ```
972    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
973    where
974        F: FnMut(I) -> Result<bool, ViewError> + Send,
975    {
976        self.collection
977            .for_each_key_while(|key| {
978                let index = BaseKey::deserialize_value(key)?;
979                f(index)
980            })
981            .await?;
982        Ok(())
983    }
984
985    /// Applies a function f on each index. Indices are visited in an order
986    /// determined by the serialization.
987    /// ```rust
988    /// # tokio_test::block_on(async {
989    /// # use linera_views::context::MemoryContext;
990    /// # use linera_views::collection_view::CollectionView;
991    /// # use linera_views::register_view::RegisterView;
992    /// # use linera_views::views::View;
993    /// # let context = MemoryContext::new_for_testing(());
994    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
995    ///     CollectionView::load(context).await.unwrap();
996    /// view.load_entry_mut(&23).await.unwrap();
997    /// view.load_entry_mut(&28).await.unwrap();
998    /// let mut count = 0;
999    /// view.for_each_index(|_key| {
1000    ///     count += 1;
1001    ///     Ok(())
1002    /// })
1003    /// .await
1004    /// .unwrap();
1005    /// assert_eq!(count, 2);
1006    /// # })
1007    /// ```
1008    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1009    where
1010        F: FnMut(I) -> Result<(), ViewError> + Send,
1011    {
1012        self.collection
1013            .for_each_key(|key| {
1014                let index = BaseKey::deserialize_value(key)?;
1015                f(index)
1016            })
1017            .await?;
1018        Ok(())
1019    }
1020}
1021
1022impl<I, W: HashableView> HashableView for CollectionView<W::Context, I, W>
1023where
1024    I: Clone + Send + Sync + Serialize + DeserializeOwned,
1025{
1026    type Hasher = sha3::Sha3_256;
1027
1028    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1029        self.collection.hash_mut().await
1030    }
1031
1032    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1033        self.collection.hash().await
1034    }
1035}
1036
1037/// A map view that serializes the indices.
1038#[derive(Debug)]
1039pub struct CustomCollectionView<C, I, W> {
1040    collection: ByteCollectionView<C, W>,
1041    _phantom: PhantomData<I>,
1042}
1043
1044impl<I: Send + Sync, W: View> View for CustomCollectionView<W::Context, I, W> {
1045    const NUM_INIT_KEYS: usize = ByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1046
1047    type Context = W::Context;
1048
1049    fn context(&self) -> &Self::Context {
1050        self.collection.context()
1051    }
1052
1053    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1054        ByteCollectionView::<_, W>::pre_load(context)
1055    }
1056
1057    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1058        let collection = ByteCollectionView::post_load(context, values)?;
1059        Ok(CustomCollectionView {
1060            collection,
1061            _phantom: PhantomData,
1062        })
1063    }
1064
1065    async fn load(context: Self::Context) -> Result<Self, ViewError> {
1066        Self::post_load(context, &[])
1067    }
1068
1069    fn rollback(&mut self) {
1070        self.collection.rollback()
1071    }
1072
1073    async fn has_pending_changes(&self) -> bool {
1074        self.collection.has_pending_changes().await
1075    }
1076
1077    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
1078        self.collection.flush(batch)
1079    }
1080
1081    fn clear(&mut self) {
1082        self.collection.clear()
1083    }
1084}
1085
1086impl<I: Send + Sync, W: ClonableView> ClonableView for CustomCollectionView<W::Context, I, W> {
1087    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1088        Ok(CustomCollectionView {
1089            collection: self.collection.clone_unchecked()?,
1090            _phantom: PhantomData,
1091        })
1092    }
1093}
1094
1095impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
1096    /// Loads a subview for the data at the given index in the collection. If an entry
1097    /// is absent then a default entry is added to the collection. The resulting view
1098    /// can be modified.
1099    /// ```rust
1100    /// # tokio_test::block_on(async {
1101    /// # use linera_views::context::MemoryContext;
1102    /// # use linera_views::collection_view::CustomCollectionView;
1103    /// # use linera_views::register_view::RegisterView;
1104    /// # use linera_views::views::View;
1105    /// # let context = MemoryContext::new_for_testing(());
1106    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1107    ///     CustomCollectionView::load(context).await.unwrap();
1108    /// let subview = view.load_entry_mut(&23).await.unwrap();
1109    /// let value = subview.get();
1110    /// assert_eq!(*value, String::default());
1111    /// # })
1112    /// ```
1113    pub async fn load_entry_mut<Q>(&mut self, index: &Q) -> Result<&mut W, ViewError>
1114    where
1115        I: Borrow<Q>,
1116        Q: CustomSerialize,
1117    {
1118        let short_key = index.to_custom_bytes()?;
1119        self.collection.load_entry_mut(&short_key).await
1120    }
1121
1122    /// Loads a subview for the data at the given index in the collection. If an entry
1123    /// is absent then a default entry is added to the collection. The resulting view
1124    /// is read-only.
1125    /// ```rust
1126    /// # tokio_test::block_on(async {
1127    /// # use linera_views::context::MemoryContext;
1128    /// # use linera_views::collection_view::CustomCollectionView;
1129    /// # use linera_views::register_view::RegisterView;
1130    /// # use linera_views::views::View;
1131    /// # let context = MemoryContext::new_for_testing(());
1132    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1133    ///     CustomCollectionView::load(context).await.unwrap();
1134    /// view.load_entry_mut(&23).await.unwrap();
1135    /// let subview = view.load_entry_or_insert(&23).await.unwrap();
1136    /// let value = subview.get();
1137    /// assert_eq!(*value, String::default());
1138    /// # })
1139    /// ```
1140    pub async fn load_entry_or_insert<Q>(&mut self, index: &Q) -> Result<&W, ViewError>
1141    where
1142        I: Borrow<Q>,
1143        Q: CustomSerialize,
1144    {
1145        let short_key = index.to_custom_bytes()?;
1146        self.collection.load_entry_or_insert(&short_key).await
1147    }
1148
1149    /// Loads a subview for the data at the given index in the collection. If an entry
1150    /// is absent then `None` is returned. The resulting view cannot be modified.
1151    /// May fail if one subview is already being visited.
1152    /// ```rust
1153    /// # tokio_test::block_on(async {
1154    /// # use linera_views::context::MemoryContext;
1155    /// # use linera_views::collection_view::CustomCollectionView;
1156    /// # use linera_views::register_view::RegisterView;
1157    /// # use linera_views::views::View;
1158    /// # let context = MemoryContext::new_for_testing(());
1159    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1160    ///     CustomCollectionView::load(context).await.unwrap();
1161    /// {
1162    ///     let _subview = view.load_entry_or_insert(&23).await.unwrap();
1163    /// }
1164    /// {
1165    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1166    ///     let value = subview.get();
1167    ///     assert_eq!(*value, String::default());
1168    /// }
1169    /// assert!(view.try_load_entry(&24).await.unwrap().is_none());
1170    /// # })
1171    /// ```
1172    pub async fn try_load_entry<Q>(
1173        &self,
1174        index: &Q,
1175    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1176    where
1177        I: Borrow<Q>,
1178        Q: CustomSerialize,
1179    {
1180        let short_key = index.to_custom_bytes()?;
1181        self.collection.try_load_entry(&short_key).await
1182    }
1183
1184    /// Marks the entry so that it is removed in the next flush.
1185    /// ```rust
1186    /// # tokio_test::block_on(async {
1187    /// # use linera_views::context::MemoryContext;
1188    /// # use linera_views::collection_view::CustomCollectionView;
1189    /// # use linera_views::register_view::RegisterView;
1190    /// # use linera_views::views::View;
1191    /// # let context = MemoryContext::new_for_testing(());
1192    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1193    ///     CustomCollectionView::load(context).await.unwrap();
1194    /// let subview = view.load_entry_mut(&23).await.unwrap();
1195    /// let value = subview.get_mut();
1196    /// *value = String::from("Hello");
1197    /// view.reset_entry_to_default(&23).unwrap();
1198    /// let subview = view.load_entry_mut(&23).await.unwrap();
1199    /// let value = subview.get_mut();
1200    /// assert_eq!(*value, String::default());
1201    /// # })
1202    /// ```
1203    pub fn reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1204    where
1205        I: Borrow<Q>,
1206        Q: CustomSerialize,
1207    {
1208        let short_key = index.to_custom_bytes()?;
1209        self.collection.reset_entry_to_default(&short_key)
1210    }
1211
1212    /// Removes an entry from the `CollectionView`. If absent nothing happens.
1213    /// ```rust
1214    /// # tokio_test::block_on(async {
1215    /// # use linera_views::context::MemoryContext;
1216    /// # use linera_views::collection_view::CustomCollectionView;
1217    /// # use linera_views::register_view::RegisterView;
1218    /// # use linera_views::views::View;
1219    /// # let context = MemoryContext::new_for_testing(());
1220    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1221    ///     CustomCollectionView::load(context).await.unwrap();
1222    /// let subview = view.load_entry_mut(&23).await.unwrap();
1223    /// let value = subview.get_mut();
1224    /// assert_eq!(*value, String::default());
1225    /// view.remove_entry(&23);
1226    /// let keys = view.indices().await.unwrap();
1227    /// assert_eq!(keys.len(), 0);
1228    /// # })
1229    /// ```
1230    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1231    where
1232        I: Borrow<Q>,
1233        Q: CustomSerialize,
1234    {
1235        let short_key = index.to_custom_bytes()?;
1236        self.collection.remove_entry(short_key);
1237        Ok(())
1238    }
1239
1240    /// Gets the extra data.
1241    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1242        self.collection.extra()
1243    }
1244}
1245
1246impl<I: CustomSerialize + Send, W: View> CustomCollectionView<W::Context, I, W> {
1247    /// Returns the list of indices in the collection in the order determined by the custom serialization.
1248    /// ```rust
1249    /// # tokio_test::block_on(async {
1250    /// # use linera_views::context::MemoryContext;
1251    /// # use linera_views::collection_view::CustomCollectionView;
1252    /// # use linera_views::register_view::RegisterView;
1253    /// # use linera_views::views::View;
1254    /// # let context = MemoryContext::new_for_testing(());
1255    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1256    ///     CustomCollectionView::load(context).await.unwrap();
1257    /// view.load_entry_mut(&23).await.unwrap();
1258    /// view.load_entry_mut(&25).await.unwrap();
1259    /// let indices = view.indices().await.unwrap();
1260    /// assert_eq!(indices, vec![23, 25]);
1261    /// # })
1262    /// ```
1263    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
1264        let mut indices = Vec::new();
1265        self.for_each_index(|index| {
1266            indices.push(index);
1267            Ok(())
1268        })
1269        .await?;
1270        Ok(indices)
1271    }
1272
1273    /// Returns the number of entries in the collection.
1274    /// ```rust
1275    /// # tokio_test::block_on(async {
1276    /// # use linera_views::context::MemoryContext;
1277    /// # use linera_views::collection_view::CollectionView;
1278    /// # use linera_views::register_view::RegisterView;
1279    /// # use linera_views::views::View;
1280    /// # let context = MemoryContext::new_for_testing(());
1281    /// let mut view: CollectionView<_, u64, RegisterView<_, String>> =
1282    ///     CollectionView::load(context).await.unwrap();
1283    /// view.load_entry_mut(&23).await.unwrap();
1284    /// view.load_entry_mut(&25).await.unwrap();
1285    /// assert_eq!(view.count().await.unwrap(), 2);
1286    /// # })
1287    /// ```
1288    pub async fn count(&self) -> Result<usize, ViewError> {
1289        self.collection.count().await
1290    }
1291}
1292
1293impl<I: CustomSerialize, W: View> CustomCollectionView<W::Context, I, W> {
1294    /// Applies a function f on each index. Indices are visited in an order
1295    /// determined by the custom serialization. If the function f returns false,
1296    /// then the loop ends prematurely.
1297    /// ```rust
1298    /// # tokio_test::block_on(async {
1299    /// # use linera_views::context::MemoryContext;
1300    /// # use linera_views::collection_view::CustomCollectionView;
1301    /// # use linera_views::register_view::RegisterView;
1302    /// # use linera_views::views::View;
1303    /// # let context = MemoryContext::new_for_testing(());
1304    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1305    ///     CustomCollectionView::load(context).await.unwrap();
1306    /// view.load_entry_mut(&28).await.unwrap();
1307    /// view.load_entry_mut(&24).await.unwrap();
1308    /// view.load_entry_mut(&23).await.unwrap();
1309    /// let mut part_indices = Vec::new();
1310    /// view.for_each_index_while(|index| {
1311    ///     part_indices.push(index);
1312    ///     Ok(part_indices.len() < 2)
1313    /// })
1314    /// .await
1315    /// .unwrap();
1316    /// assert_eq!(part_indices, vec![23, 24]);
1317    /// # })
1318    /// ```
1319    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1320    where
1321        F: FnMut(I) -> Result<bool, ViewError> + Send,
1322    {
1323        self.collection
1324            .for_each_key_while(|key| {
1325                let index = I::from_custom_bytes(key)?;
1326                f(index)
1327            })
1328            .await?;
1329        Ok(())
1330    }
1331
1332    /// Applies a function on each index. Indices are visited in an order
1333    /// determined by the custom serialization.
1334    /// ```rust
1335    /// # tokio_test::block_on(async {
1336    /// # use linera_views::context::MemoryContext;
1337    /// # use linera_views::collection_view::CustomCollectionView;
1338    /// # use linera_views::register_view::RegisterView;
1339    /// # use linera_views::views::View;
1340    /// # let context = MemoryContext::new_for_testing(());
1341    /// let mut view: CustomCollectionView<_, u128, RegisterView<_, String>> =
1342    ///     CustomCollectionView::load(context).await.unwrap();
1343    /// view.load_entry_mut(&28).await.unwrap();
1344    /// view.load_entry_mut(&24).await.unwrap();
1345    /// view.load_entry_mut(&23).await.unwrap();
1346    /// let mut indices = Vec::new();
1347    /// view.for_each_index(|index| {
1348    ///     indices.push(index);
1349    ///     Ok(())
1350    /// })
1351    /// .await
1352    /// .unwrap();
1353    /// assert_eq!(indices, vec![23, 24, 28]);
1354    /// # })
1355    /// ```
1356    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1357    where
1358        F: FnMut(I) -> Result<(), ViewError> + Send,
1359    {
1360        self.collection
1361            .for_each_key(|key| {
1362                let index = I::from_custom_bytes(key)?;
1363                f(index)
1364            })
1365            .await?;
1366        Ok(())
1367    }
1368}
1369
1370impl<I, W: HashableView> HashableView for CustomCollectionView<W::Context, I, W>
1371where
1372    Self: View,
1373{
1374    type Hasher = sha3::Sha3_256;
1375
1376    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1377        self.collection.hash_mut().await
1378    }
1379
1380    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1381        self.collection.hash().await
1382    }
1383}
1384
1385/// Type wrapping `ByteCollectionView` while memoizing the hash.
1386pub type HashedByteCollectionView<C, W> =
1387    WrappedHashableContainerView<C, ByteCollectionView<C, W>, HasherOutput>;
1388
1389/// Type wrapping `CollectionView` while memoizing the hash.
1390pub type HashedCollectionView<C, I, W> =
1391    WrappedHashableContainerView<C, CollectionView<C, I, W>, HasherOutput>;
1392
1393/// Type wrapping `CustomCollectionView` while memoizing the hash.
1394pub type HashedCustomCollectionView<C, I, W> =
1395    WrappedHashableContainerView<C, CustomCollectionView<C, I, W>, HasherOutput>;
1396
1397#[cfg(with_graphql)]
1398mod graphql {
1399    use std::borrow::Cow;
1400
1401    use super::{CollectionView, CustomCollectionView, ReadGuardedView};
1402    use crate::{
1403        graphql::{hash_name, mangle, missing_key_error, Entry, MapFilters, MapInput},
1404        views::View,
1405    };
1406
1407    impl<T: async_graphql::OutputType> async_graphql::OutputType for ReadGuardedView<'_, T> {
1408        fn type_name() -> Cow<'static, str> {
1409            T::type_name()
1410        }
1411
1412        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
1413            T::create_type_info(registry)
1414        }
1415
1416        async fn resolve(
1417            &self,
1418            ctx: &async_graphql::ContextSelectionSet<'_>,
1419            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
1420        ) -> async_graphql::ServerResult<async_graphql::Value> {
1421            (**self).resolve(ctx, field).await
1422        }
1423    }
1424
1425    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
1426        async_graphql::TypeName for CollectionView<C, K, V>
1427    {
1428        fn type_name() -> Cow<'static, str> {
1429            format!(
1430                "CollectionView_{}_{}_{:08x}",
1431                mangle(K::type_name()),
1432                mangle(V::type_name()),
1433                hash_name::<(K, V)>(),
1434            )
1435            .into()
1436        }
1437    }
1438
1439    #[async_graphql::Object(cache_control(no_cache), name_type)]
1440    impl<K, V> CollectionView<V::Context, K, V>
1441    where
1442        K: async_graphql::InputType
1443            + async_graphql::OutputType
1444            + serde::ser::Serialize
1445            + serde::de::DeserializeOwned
1446            + std::fmt::Debug
1447            + Clone,
1448        V: View + async_graphql::OutputType,
1449        MapInput<K>: async_graphql::InputType,
1450        MapFilters<K>: async_graphql::InputType,
1451    {
1452        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
1453            Ok(self.indices().await?)
1454        }
1455
1456        async fn entry(
1457            &self,
1458            key: K,
1459        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
1460            let value = self
1461                .try_load_entry(&key)
1462                .await?
1463                .ok_or_else(|| missing_key_error(&key))?;
1464            Ok(Entry { value, key })
1465        }
1466
1467        async fn entries(
1468            &self,
1469            input: Option<MapInput<K>>,
1470        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
1471            let keys = if let Some(keys) = input
1472                .and_then(|input| input.filters)
1473                .and_then(|filters| filters.keys)
1474            {
1475                keys
1476            } else {
1477                self.indices().await?
1478            };
1479
1480            let mut values = vec![];
1481            for key in keys {
1482                let value = self
1483                    .try_load_entry(&key)
1484                    .await?
1485                    .ok_or_else(|| missing_key_error(&key))?;
1486                values.push(Entry { value, key })
1487            }
1488
1489            Ok(values)
1490        }
1491    }
1492
1493    impl<C: Send + Sync, K: async_graphql::InputType, V: async_graphql::OutputType>
1494        async_graphql::TypeName for CustomCollectionView<C, K, V>
1495    {
1496        fn type_name() -> Cow<'static, str> {
1497            format!(
1498                "CustomCollectionView_{}_{}_{:08x}",
1499                mangle(K::type_name()),
1500                mangle(V::type_name()),
1501                hash_name::<(K, V)>(),
1502            )
1503            .into()
1504        }
1505    }
1506
1507    #[async_graphql::Object(cache_control(no_cache), name_type)]
1508    impl<K, V> CustomCollectionView<V::Context, K, V>
1509    where
1510        K: async_graphql::InputType
1511            + async_graphql::OutputType
1512            + crate::common::CustomSerialize
1513            + std::fmt::Debug,
1514        V: View + async_graphql::OutputType,
1515        MapInput<K>: async_graphql::InputType,
1516        MapFilters<K>: async_graphql::InputType,
1517    {
1518        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
1519            Ok(self.indices().await?)
1520        }
1521
1522        async fn entry(
1523            &self,
1524            key: K,
1525        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
1526            let value = self
1527                .try_load_entry(&key)
1528                .await?
1529                .ok_or_else(|| missing_key_error(&key))?;
1530            Ok(Entry { value, key })
1531        }
1532
1533        async fn entries(
1534            &self,
1535            input: Option<MapInput<K>>,
1536        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
1537            let keys = if let Some(keys) = input
1538                .and_then(|input| input.filters)
1539                .and_then(|filters| filters.keys)
1540            {
1541                keys
1542            } else {
1543                self.indices().await?
1544            };
1545
1546            let mut values = vec![];
1547            for key in keys {
1548                let value = self
1549                    .try_load_entry(&key)
1550                    .await?
1551                    .ok_or_else(|| missing_key_error(&key))?;
1552                values.push(Entry { value, key })
1553            }
1554
1555            Ok(values)
1556        }
1557    }
1558}