Skip to main content

linera_views/views/
reentrant_collection_view.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{
5    borrow::Borrow,
6    collections::{btree_map, BTreeMap},
7    io::Write,
8    marker::PhantomData,
9    mem,
10    ops::Deref,
11    sync::Arc,
12};
13
14use allocative::{Allocative, Key, Visitor};
15use async_lock::{RwLock, RwLockReadGuardArc, RwLockWriteGuardArc};
16use linera_base::data_types::ArithmeticError;
17#[cfg(with_metrics)]
18use linera_base::prometheus_util::MeasureLatency as _;
19use serde::{de::DeserializeOwned, Serialize};
20
21use crate::{
22    batch::Batch,
23    common::{CustomSerialize, HasherOutput, SliceExt as _, Update},
24    context::{BaseKey, Context},
25    hashable_wrapper::WrappedHashableContainerView,
26    historical_hash_wrapper::HistoricallyHashableView,
27    store::ReadableKeyValueStore as _,
28    views::{ClonableView, HashableView, Hasher, ReplaceContext, View, ViewError, MIN_VIEW_TAG},
29};
30
31#[cfg(with_metrics)]
32mod metrics {
33    use std::sync::LazyLock;
34
35    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
36    use prometheus::HistogramVec;
37
38    /// The runtime of hash computation
39    pub static REENTRANT_COLLECTION_VIEW_HASH_RUNTIME: LazyLock<HistogramVec> =
40        LazyLock::new(|| {
41            register_histogram_vec(
42                "reentrant_collection_view_hash_runtime",
43                "ReentrantCollectionView hash runtime",
44                &[],
45                exponential_bucket_latencies(5.0),
46            )
47        });
48}
49
50/// A read-only accessor for a particular subview in a [`ReentrantCollectionView`].
51#[derive(Debug)]
52pub struct ReadGuardedView<T>(RwLockReadGuardArc<T>);
53
54impl<T> std::ops::Deref for ReadGuardedView<T> {
55    type Target = T;
56    fn deref(&self) -> &T {
57        self.0.deref()
58    }
59}
60
61/// A read-write accessor for a particular subview in a [`ReentrantCollectionView`].
62#[derive(Debug)]
63pub struct WriteGuardedView<T>(RwLockWriteGuardArc<T>);
64
65impl<T> std::ops::Deref for WriteGuardedView<T> {
66    type Target = T;
67    fn deref(&self) -> &T {
68        self.0.deref()
69    }
70}
71
72impl<T> std::ops::DerefMut for WriteGuardedView<T> {
73    fn deref_mut(&mut self) -> &mut T {
74        self.0.deref_mut()
75    }
76}
77
78/// A view that supports accessing a collection of views of the same kind, indexed by `Vec<u8>`,
79/// possibly several subviews at a time.
80#[derive(Debug)]
81pub struct ReentrantByteCollectionView<C, W> {
82    /// The view [`Context`].
83    context: C,
84    /// If the current persisted data will be completely erased and replaced on the next flush.
85    delete_storage_first: bool,
86    /// Entries that may have staged changes.
87    updates: BTreeMap<Vec<u8>, Update<Arc<RwLock<W>>>>,
88}
89
90impl<C, W: Allocative> Allocative for ReentrantByteCollectionView<C, W> {
91    fn visit<'a, 'b: 'a>(&self, visitor: &'a mut Visitor<'b>) {
92        let name = Key::new("ReentrantByteCollectionView");
93        let size = mem::size_of::<Self>();
94        let mut visitor = visitor.enter(name, size);
95
96        for (k, v) in &self.updates {
97            let key_name = Key::new("key");
98            visitor.visit_field(key_name, k);
99            match v {
100                Update::Removed => {
101                    let key = Key::new("update_removed");
102                    visitor.visit_field(key, &());
103                }
104                Update::Set(v) => {
105                    if let Some(v) = v.try_read() {
106                        let key = Key::new("update_set");
107                        visitor.visit_field(key, v.deref());
108                    }
109                }
110            }
111        }
112        visitor.exit();
113    }
114}
115
116impl<W, C2> ReplaceContext<C2> for ReentrantByteCollectionView<W::Context, W>
117where
118    W: View + ReplaceContext<C2>,
119    C2: Context,
120{
121    type Target = ReentrantByteCollectionView<C2, <W as ReplaceContext<C2>>::Target>;
122
123    async fn with_context(
124        &mut self,
125        ctx: impl FnOnce(&Self::Context) -> C2 + Clone,
126    ) -> Self::Target {
127        let mut updates: BTreeMap<_, Update<Arc<RwLock<W::Target>>>> = BTreeMap::new();
128        for (key, update) in &self.updates {
129            let new_value = match update {
130                Update::Removed => Update::Removed,
131                Update::Set(x) => Update::Set(Arc::new(RwLock::new(
132                    x.write().await.with_context(ctx.clone()).await,
133                ))),
134            };
135            updates.insert(key.clone(), new_value);
136        }
137        ReentrantByteCollectionView {
138            context: ctx(&self.context),
139            delete_storage_first: self.delete_storage_first,
140            updates,
141        }
142    }
143}
144
145/// We need to find new base keys in order to implement the collection view.
146/// We do this by appending a value to the base key.
147///
148/// Sub-views in a collection share a common key prefix, like in other view types. However,
149/// just concatenating the shared prefix with sub-view keys makes it impossible to distinguish if a
150/// given key belongs to a child sub-view or a grandchild sub-view (consider for example if a
151/// collection is stored inside the collection).
152#[repr(u8)]
153enum KeyTag {
154    /// Prefix for specifying an index and serves to indicate the existence of an entry in the collection.
155    Index = MIN_VIEW_TAG,
156    /// Prefix for specifying as the prefix for the sub-view.
157    Subview,
158}
159
160impl<W: View> View for ReentrantByteCollectionView<W::Context, W> {
161    const NUM_INIT_KEYS: usize = 0;
162
163    type Context = W::Context;
164
165    fn context(&self) -> Self::Context {
166        self.context.clone()
167    }
168
169    fn pre_load(_context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
170        Ok(Vec::new())
171    }
172
173    fn post_load(context: Self::Context, _values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
174        Ok(Self {
175            context,
176            delete_storage_first: false,
177            updates: BTreeMap::new(),
178        })
179    }
180
181    fn rollback(&mut self) {
182        self.delete_storage_first = false;
183        self.updates.clear();
184    }
185
186    async fn has_pending_changes(&self) -> bool {
187        if self.delete_storage_first {
188            return true;
189        }
190        !self.updates.is_empty()
191    }
192
193    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
194        let mut delete_view = false;
195        if self.delete_storage_first {
196            delete_view = true;
197            batch.delete_key_prefix(self.context.base_key().bytes.clone());
198            for (index, update) in &self.updates {
199                if let Update::Set(view) = update {
200                    let view = view
201                        .try_read()
202                        .ok_or_else(|| ViewError::TryLockError(index.clone()))?;
203                    view.pre_save(batch)?;
204                    self.add_index(batch, index);
205                    delete_view = false;
206                }
207            }
208        } else {
209            for (index, update) in &self.updates {
210                match update {
211                    Update::Set(view) => {
212                        let view = view
213                            .try_read()
214                            .ok_or_else(|| ViewError::TryLockError(index.clone()))?;
215                        view.pre_save(batch)?;
216                        self.add_index(batch, index);
217                    }
218                    Update::Removed => {
219                        let key_subview = self.get_subview_key(index);
220                        let key_index = self.get_index_key(index);
221                        batch.delete_key(key_index);
222                        batch.delete_key_prefix(key_subview);
223                    }
224                }
225            }
226        }
227        Ok(delete_view)
228    }
229
230    fn post_save(&mut self) {
231        for (_index, update) in mem::take(&mut self.updates) {
232            if let Update::Set(view) = update {
233                let mut view = view.try_write().expect("pre_save was called before");
234                view.post_save();
235            }
236        }
237        self.delete_storage_first = false;
238    }
239
240    fn clear(&mut self) {
241        self.delete_storage_first = true;
242        self.updates.clear();
243    }
244}
245
246impl<W: ClonableView> ClonableView for ReentrantByteCollectionView<W::Context, W> {
247    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
248        let cloned_updates = self
249            .updates
250            .iter()
251            .map(|(key, value)| {
252                let cloned_value = match value {
253                    Update::Removed => Update::Removed,
254                    Update::Set(view_lock) => {
255                        let mut view = view_lock
256                            .try_write()
257                            .ok_or_else(|| ViewError::TryLockError(key.clone()))?;
258                        Update::Set(Arc::new(RwLock::new(view.clone_unchecked()?)))
259                    }
260                };
261                Ok::<_, ViewError>((key.clone(), cloned_value))
262            })
263            .collect::<Result<_, _>>()?;
264
265        Ok(ReentrantByteCollectionView {
266            context: self.context.clone(),
267            delete_storage_first: self.delete_storage_first,
268            updates: cloned_updates,
269        })
270    }
271}
272
273impl<C: Context, W> ReentrantByteCollectionView<C, W> {
274    fn get_index_key(&self, index: &[u8]) -> Vec<u8> {
275        self.context
276            .base_key()
277            .base_tag_index(KeyTag::Index as u8, index)
278    }
279
280    fn get_subview_key(&self, index: &[u8]) -> Vec<u8> {
281        self.context
282            .base_key()
283            .base_tag_index(KeyTag::Subview as u8, index)
284    }
285
286    fn add_index(&self, batch: &mut Batch, index: &[u8]) {
287        let key = self.get_index_key(index);
288        batch.put_key_value_bytes(key, vec![]);
289    }
290}
291
292impl<W: View> ReentrantByteCollectionView<W::Context, W> {
293    /// Reads the view and if missing returns the default view
294    async fn wrapped_view(
295        context: &W::Context,
296        delete_storage_first: bool,
297        short_key: &[u8],
298    ) -> Result<Arc<RwLock<W>>, ViewError> {
299        let key = context
300            .base_key()
301            .base_tag_index(KeyTag::Subview as u8, short_key);
302        let context = context.clone_with_base_key(key);
303        // Obtain a view and set its pending state to the default (e.g. empty) state
304        let view = if delete_storage_first {
305            W::new(context)?
306        } else {
307            W::load(context).await?
308        };
309        Ok(Arc::new(RwLock::new(view)))
310    }
311
312    /// Load the view and insert it into the updates if needed.
313    /// If the entry is missing, then it is set to default.
314    async fn try_load_view_mut(&mut self, short_key: &[u8]) -> Result<Arc<RwLock<W>>, ViewError> {
315        use btree_map::Entry::*;
316        Ok(match self.updates.entry(short_key.to_owned()) {
317            Occupied(mut entry) => match entry.get_mut() {
318                Update::Set(view) => view.clone(),
319                entry @ Update::Removed => {
320                    let wrapped_view = Self::wrapped_view(&self.context, true, short_key).await?;
321                    *entry = Update::Set(wrapped_view.clone());
322                    wrapped_view
323                }
324            },
325            Vacant(entry) => {
326                let wrapped_view =
327                    Self::wrapped_view(&self.context, self.delete_storage_first, short_key).await?;
328                entry.insert(Update::Set(wrapped_view.clone()));
329                wrapped_view
330            }
331        })
332    }
333
334    /// Load the view from the update is available.
335    /// If missing, then the entry is loaded from storage and if
336    /// missing there an error is reported.
337    async fn try_load_view(&self, short_key: &[u8]) -> Result<Option<Arc<RwLock<W>>>, ViewError> {
338        Ok(if let Some(entry) = self.updates.get(short_key) {
339            match entry {
340                Update::Set(view) => Some(view.clone()),
341                _entry @ Update::Removed => None,
342            }
343        } else if self.delete_storage_first {
344            None
345        } else {
346            let key_index = self
347                .context
348                .base_key()
349                .base_tag_index(KeyTag::Index as u8, short_key);
350            if self.context.store().contains_key(&key_index).await? {
351                let view = Self::wrapped_view(&self.context, false, short_key).await?;
352                Some(view)
353            } else {
354                None
355            }
356        })
357    }
358
359    /// Loads a subview for the data at the given index in the collection. If an entry
360    /// is absent then a default entry is added to the collection. The resulting view
361    /// can be modified.
362    /// ```rust
363    /// # tokio_test::block_on(async {
364    /// # use linera_views::context::MemoryContext;
365    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
366    /// # use linera_views::register_view::RegisterView;
367    /// # use linera_views::views::View;
368    /// # let context = MemoryContext::new_for_testing(());
369    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
370    ///     ReentrantByteCollectionView::load(context).await.unwrap();
371    /// let subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
372    /// let value = subview.get();
373    /// assert_eq!(*value, String::default());
374    /// # })
375    /// ```
376    pub async fn try_load_entry_mut(
377        &mut self,
378        short_key: &[u8],
379    ) -> Result<WriteGuardedView<W>, ViewError> {
380        Ok(WriteGuardedView(
381            self.try_load_view_mut(short_key)
382                .await?
383                .try_write_arc()
384                .ok_or_else(|| ViewError::TryLockError(short_key.to_vec()))?,
385        ))
386    }
387
388    /// Loads a subview at the given index in the collection and gives read-only access to the data.
389    /// If an entry is absent then `None` is returned.
390    /// ```rust
391    /// # tokio_test::block_on(async {
392    /// # use linera_views::context::MemoryContext;
393    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
394    /// # use linera_views::register_view::RegisterView;
395    /// # use linera_views::views::View;
396    /// # let context = MemoryContext::new_for_testing(());
397    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
398    ///     ReentrantByteCollectionView::load(context).await.unwrap();
399    /// {
400    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
401    /// }
402    /// let subview = view.try_load_entry(&[0, 1]).await.unwrap().unwrap();
403    /// let value = subview.get();
404    /// assert_eq!(*value, String::default());
405    /// # })
406    /// ```
407    pub async fn try_load_entry(
408        &self,
409        short_key: &[u8],
410    ) -> Result<Option<ReadGuardedView<W>>, ViewError> {
411        match self.try_load_view(short_key).await? {
412            None => Ok(None),
413            Some(view) => Ok(Some(ReadGuardedView(
414                view.try_read_arc()
415                    .ok_or_else(|| ViewError::TryLockError(short_key.to_vec()))?,
416            ))),
417        }
418    }
419
420    /// Returns `true` if the collection contains a value for the specified key.
421    /// ```rust
422    /// # tokio_test::block_on(async {
423    /// # use linera_views::context::MemoryContext;
424    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
425    /// # use linera_views::register_view::RegisterView;
426    /// # use linera_views::views::View;
427    /// # let context = MemoryContext::new_for_testing(());
428    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
429    ///     ReentrantByteCollectionView::load(context).await.unwrap();
430    /// let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
431    /// assert!(view.contains_key(&[0, 1]).await.unwrap());
432    /// assert!(!view.contains_key(&[0, 2]).await.unwrap());
433    /// # })
434    /// ```
435    pub async fn contains_key(&self, short_key: &[u8]) -> Result<bool, ViewError> {
436        Ok(if let Some(entry) = self.updates.get(short_key) {
437            match entry {
438                Update::Set(_view) => true,
439                Update::Removed => false,
440            }
441        } else if self.delete_storage_first {
442            false
443        } else {
444            let key_index = self
445                .context
446                .base_key()
447                .base_tag_index(KeyTag::Index as u8, short_key);
448            self.context.store().contains_key(&key_index).await?
449        })
450    }
451
452    /// Removes an entry. If absent then nothing happens.
453    /// ```rust
454    /// # tokio_test::block_on(async {
455    /// # use linera_views::context::MemoryContext;
456    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
457    /// # use linera_views::register_view::RegisterView;
458    /// # use linera_views::views::View;
459    /// # let context = MemoryContext::new_for_testing(());
460    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
461    ///     ReentrantByteCollectionView::load(context).await.unwrap();
462    /// let mut subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
463    /// let value = subview.get_mut();
464    /// assert_eq!(*value, String::default());
465    /// view.remove_entry(vec![0, 1]);
466    /// let keys = view.keys().await.unwrap();
467    /// assert_eq!(keys.len(), 0);
468    /// # })
469    /// ```
470    pub fn remove_entry(&mut self, short_key: Vec<u8>) {
471        if self.delete_storage_first {
472            // Optimization: No need to mark `short_key` for deletion as we are going to remove all the keys at once.
473            self.updates.remove(&short_key);
474        } else {
475            self.updates.insert(short_key, Update::Removed);
476        }
477    }
478
479    /// Marks the entry so that it is removed in the next flush.
480    /// ```rust
481    /// # tokio_test::block_on(async {
482    /// # use linera_views::context::MemoryContext;
483    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
484    /// # use linera_views::register_view::RegisterView;
485    /// # use linera_views::views::View;
486    /// # let context = MemoryContext::new_for_testing(());
487    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
488    ///     ReentrantByteCollectionView::load(context).await.unwrap();
489    /// {
490    ///     let mut subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
491    ///     let value = subview.get_mut();
492    ///     *value = String::from("Hello");
493    /// }
494    /// view.try_reset_entry_to_default(&[0, 1]).unwrap();
495    /// let mut subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
496    /// let value = subview.get_mut();
497    /// assert_eq!(*value, String::default());
498    /// # })
499    /// ```
500    pub fn try_reset_entry_to_default(&mut self, short_key: &[u8]) -> Result<(), ViewError> {
501        let key = self
502            .context
503            .base_key()
504            .base_tag_index(KeyTag::Subview as u8, short_key);
505        let context = self.context.clone_with_base_key(key);
506        let view = W::new(context)?;
507        let view = Arc::new(RwLock::new(view));
508        let view = Update::Set(view);
509        self.updates.insert(short_key.to_vec(), view);
510        Ok(())
511    }
512
513    /// Gets the extra data.
514    pub fn extra(&self) -> &<W::Context as Context>::Extra {
515        self.context.extra()
516    }
517}
518
519impl<W: View> ReentrantByteCollectionView<W::Context, W> {
520    /// Loads multiple entries for writing at once.
521    /// The entries in `short_keys` have to be all distinct.
522    /// ```rust
523    /// # tokio_test::block_on(async {
524    /// # use linera_views::context::MemoryContext;
525    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
526    /// # use linera_views::register_view::RegisterView;
527    /// # use linera_views::views::View;
528    /// # let context = MemoryContext::new_for_testing(());
529    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
530    ///     ReentrantByteCollectionView::load(context).await.unwrap();
531    /// {
532    ///     let mut subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
533    ///     *subview.get_mut() = "Bonjour".to_string();
534    /// }
535    /// let short_keys = vec![vec![0, 1], vec![2, 3]];
536    /// let subviews = view.try_load_entries_mut(short_keys).await.unwrap();
537    /// let value1 = subviews[0].get();
538    /// let value2 = subviews[1].get();
539    /// assert_eq!(*value1, "Bonjour".to_string());
540    /// assert_eq!(*value2, String::default());
541    /// # })
542    /// ```
543    pub async fn try_load_entries_mut(
544        &mut self,
545        short_keys: Vec<Vec<u8>>,
546    ) -> Result<Vec<WriteGuardedView<W>>, ViewError> {
547        let mut short_keys_to_load = Vec::new();
548        let mut keys = Vec::new();
549        for short_key in &short_keys {
550            let key = self
551                .context
552                .base_key()
553                .base_tag_index(KeyTag::Subview as u8, short_key);
554            let context = self.context.clone_with_base_key(key);
555            match self.updates.entry(short_key.to_vec()) {
556                btree_map::Entry::Occupied(mut entry) => {
557                    if let Update::Removed = entry.get() {
558                        let view = W::new(context)?;
559                        let view = Arc::new(RwLock::new(view));
560                        entry.insert(Update::Set(view));
561                    }
562                }
563                btree_map::Entry::Vacant(entry) => {
564                    if self.delete_storage_first {
565                        let view = W::new(context)?;
566                        let view = Arc::new(RwLock::new(view));
567                        entry.insert(Update::Set(view));
568                    } else {
569                        keys.extend(W::pre_load(&context)?);
570                        short_keys_to_load.push(short_key.to_vec());
571                    }
572                }
573            }
574        }
575        let values = self.context.store().read_multi_values_bytes(&keys).await?;
576        for (loaded_values, short_key) in values
577            .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
578            .zip(short_keys_to_load)
579        {
580            let key = self
581                .context
582                .base_key()
583                .base_tag_index(KeyTag::Subview as u8, &short_key);
584            let context = self.context.clone_with_base_key(key);
585            let view = W::post_load(context, loaded_values)?;
586            let wrapped_view = Arc::new(RwLock::new(view));
587            self.updates
588                .insert(short_key.to_vec(), Update::Set(wrapped_view));
589        }
590
591        short_keys
592            .into_iter()
593            .map(|short_key| {
594                let Some(Update::Set(view)) = self.updates.get(&short_key) else {
595                    unreachable!(
596                        "Entry should have been inserted as Update::Set by try_load_view_mut"
597                    )
598                };
599                Ok(WriteGuardedView(
600                    view.clone()
601                        .try_write_arc()
602                        .ok_or_else(|| ViewError::TryLockError(short_key))?,
603                ))
604            })
605            .collect()
606    }
607
608    /// Loads multiple entries for writing at once with their keys.
609    /// The entries in short_keys have to be all distinct.
610    /// ```rust
611    /// # tokio_test::block_on(async {
612    /// # use linera_views::context::MemoryContext;
613    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
614    /// # use linera_views::register_view::RegisterView;
615    /// # use linera_views::views::View;
616    /// # let context = MemoryContext::new_for_testing(());
617    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
618    ///     ReentrantByteCollectionView::load(context).await.unwrap();
619    /// {
620    ///     let mut subview = view.try_load_entry_mut(&vec![0, 1]).await.unwrap();
621    ///     *subview.get_mut() = "Bonjour".to_string();
622    /// }
623    /// let short_keys = vec![vec![0, 1], vec![2, 3]];
624    /// let subviews = view.try_load_entries_pairs_mut(short_keys).await.unwrap();
625    /// let value1 = subviews[0].1.get();
626    /// let value2 = subviews[1].1.get();
627    /// assert_eq!(*value1, "Bonjour".to_string());
628    /// assert_eq!(*value2, String::default());
629    /// # })
630    /// ```
631    pub async fn try_load_entries_pairs_mut(
632        &mut self,
633        short_keys: Vec<Vec<u8>>,
634    ) -> Result<Vec<(Vec<u8>, WriteGuardedView<W>)>, ViewError> {
635        let values = self.try_load_entries_mut(short_keys.clone()).await?;
636        Ok(short_keys.into_iter().zip(values).collect())
637    }
638
639    /// Loads multiple entries for reading at once.
640    /// The entries in `short_keys` have to be all distinct.
641    /// ```rust
642    /// # tokio_test::block_on(async {
643    /// # use linera_views::context::MemoryContext;
644    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
645    /// # use linera_views::register_view::RegisterView;
646    /// # use linera_views::views::View;
647    /// # let context = MemoryContext::new_for_testing(());
648    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
649    ///     ReentrantByteCollectionView::load(context).await.unwrap();
650    /// {
651    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
652    /// }
653    /// let short_keys = vec![vec![0, 1], vec![2, 3]];
654    /// let subviews = view.try_load_entries(short_keys).await.unwrap();
655    /// assert!(subviews[1].is_none());
656    /// let value0 = subviews[0].as_ref().unwrap().get();
657    /// assert_eq!(*value0, String::default());
658    /// # })
659    /// ```
660    pub async fn try_load_entries(
661        &self,
662        short_keys: Vec<Vec<u8>>,
663    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError> {
664        let mut results = vec![None; short_keys.len()];
665        let mut keys_to_check = Vec::new();
666        let mut keys_to_check_metadata = Vec::new();
667
668        for (position, short_key) in short_keys.into_iter().enumerate() {
669            if let Some(update) = self.updates.get(&short_key) {
670                if let Update::Set(view) = update {
671                    results[position] = Some((short_key, view.clone()));
672                }
673            } else if !self.delete_storage_first {
674                let key_index = self
675                    .context
676                    .base_key()
677                    .base_tag_index(KeyTag::Index as u8, &short_key);
678                keys_to_check.push(key_index);
679                keys_to_check_metadata.push((position, short_key));
680            }
681        }
682
683        let found_keys = self.context.store().contains_keys(&keys_to_check).await?;
684        let entries_to_load = keys_to_check_metadata
685            .into_iter()
686            .zip(found_keys)
687            .filter_map(|(metadata, found)| found.then_some(metadata))
688            .map(|(position, short_key)| {
689                let subview_key = self
690                    .context
691                    .base_key()
692                    .base_tag_index(KeyTag::Subview as u8, &short_key);
693                let subview_context = self.context.clone_with_base_key(subview_key);
694                (position, short_key.to_owned(), subview_context)
695            })
696            .collect::<Vec<_>>();
697        if !entries_to_load.is_empty() {
698            let mut keys_to_load = Vec::with_capacity(entries_to_load.len() * W::NUM_INIT_KEYS);
699            for (_, _, context) in &entries_to_load {
700                keys_to_load.extend(W::pre_load(context)?);
701            }
702            let values = self
703                .context
704                .store()
705                .read_multi_values_bytes(&keys_to_load)
706                .await?;
707            for (loaded_values, (position, short_key, context)) in values
708                .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
709                .zip(entries_to_load)
710            {
711                let view = W::post_load(context, loaded_values)?;
712                let wrapped_view = Arc::new(RwLock::new(view));
713                results[position] = Some((short_key, wrapped_view));
714            }
715        }
716
717        results
718            .into_iter()
719            .map(|maybe_view| match maybe_view {
720                Some((short_key, view)) => Ok(Some(ReadGuardedView(
721                    view.try_read_arc()
722                        .ok_or_else(|| ViewError::TryLockError(short_key))?,
723                ))),
724                None => Ok(None),
725            })
726            .collect()
727    }
728
729    /// Loads multiple entries for reading at once with their keys.
730    /// The entries in short_keys have to be all distinct.
731    /// ```rust
732    /// # tokio_test::block_on(async {
733    /// # use linera_views::context::MemoryContext;
734    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
735    /// # use linera_views::register_view::RegisterView;
736    /// # use linera_views::views::View;
737    /// # let context = MemoryContext::new_for_testing(());
738    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
739    ///     ReentrantByteCollectionView::load(context).await.unwrap();
740    /// {
741    ///     let _subview = view.try_load_entry_mut(&vec![0, 1]).await.unwrap();
742    /// }
743    /// let short_keys = vec![vec![0, 1], vec![0, 2]];
744    /// let subviews = view.try_load_entries_pairs(short_keys).await.unwrap();
745    /// assert!(subviews[1].1.is_none());
746    /// let value0 = subviews[0].1.as_ref().unwrap().get();
747    /// assert_eq!(*value0, String::default());
748    /// # })
749    /// ```
750    pub async fn try_load_entries_pairs(
751        &self,
752        short_keys: Vec<Vec<u8>>,
753    ) -> Result<Vec<(Vec<u8>, Option<ReadGuardedView<W>>)>, ViewError> {
754        let values = self.try_load_entries(short_keys.clone()).await?;
755        Ok(short_keys.into_iter().zip(values).collect())
756    }
757
758    /// Loads all the entries for reading at once.
759    /// ```rust
760    /// # tokio_test::block_on(async {
761    /// # use linera_views::context::MemoryContext;
762    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
763    /// # use linera_views::register_view::RegisterView;
764    /// # use linera_views::views::View;
765    /// # let context = MemoryContext::new_for_testing(());
766    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
767    ///     ReentrantByteCollectionView::load(context).await.unwrap();
768    /// {
769    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
770    /// }
771    /// let subviews = view.try_load_all_entries().await.unwrap();
772    /// assert_eq!(subviews.len(), 1);
773    /// # })
774    /// ```
775    pub async fn try_load_all_entries(
776        &self,
777    ) -> Result<Vec<(Vec<u8>, ReadGuardedView<W>)>, ViewError> {
778        let short_keys = self.keys().await?;
779        let mut loaded_views = vec![None; short_keys.len()];
780
781        // Load views that are not in updates and not deleted
782        if !self.delete_storage_first {
783            let mut keys = Vec::new();
784            let mut short_keys_and_indexes = Vec::new();
785            for (index, short_key) in short_keys.iter().enumerate() {
786                if !self.updates.contains_key(short_key) {
787                    let key = self
788                        .context
789                        .base_key()
790                        .base_tag_index(KeyTag::Subview as u8, short_key);
791                    let context = self.context.clone_with_base_key(key);
792                    keys.extend(W::pre_load(&context)?);
793                    short_keys_and_indexes.push((short_key.to_vec(), index));
794                }
795            }
796            let values = self.context.store().read_multi_values_bytes(&keys).await?;
797            for (loaded_values, (short_key, index)) in values
798                .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
799                .zip(short_keys_and_indexes)
800            {
801                let key = self
802                    .context
803                    .base_key()
804                    .base_tag_index(KeyTag::Subview as u8, &short_key);
805                let context = self.context.clone_with_base_key(key);
806                let view = W::post_load(context, loaded_values)?;
807                let wrapped_view = Arc::new(RwLock::new(view));
808                loaded_views[index] = Some(wrapped_view);
809            }
810        }
811
812        // Create result from updates and loaded views
813        short_keys
814            .into_iter()
815            .zip(loaded_views)
816            .map(|(short_key, loaded_view)| {
817                let view = if let Some(Update::Set(view)) = self.updates.get(&short_key) {
818                    view.clone()
819                } else if let Some(view) = loaded_view {
820                    view
821                } else {
822                    unreachable!("All entries should have been loaded into memory");
823                };
824                let guard = ReadGuardedView(
825                    view.try_read_arc()
826                        .ok_or_else(|| ViewError::TryLockError(short_key.clone()))?,
827                );
828                Ok((short_key, guard))
829            })
830            .collect()
831    }
832
833    /// Loads all the entries for writing at once.
834    /// ```rust
835    /// # tokio_test::block_on(async {
836    /// # use linera_views::context::MemoryContext;
837    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
838    /// # use linera_views::register_view::RegisterView;
839    /// # use linera_views::views::View;
840    /// # let context = MemoryContext::new_for_testing(());
841    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
842    ///     ReentrantByteCollectionView::load(context).await.unwrap();
843    /// {
844    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
845    /// }
846    /// let subviews = view.try_load_all_entries_mut().await.unwrap();
847    /// assert_eq!(subviews.len(), 1);
848    /// # })
849    /// ```
850    pub async fn try_load_all_entries_mut(
851        &mut self,
852    ) -> Result<Vec<(Vec<u8>, WriteGuardedView<W>)>, ViewError> {
853        let short_keys = self.keys().await?;
854        if !self.delete_storage_first {
855            let mut keys = Vec::new();
856            let mut short_keys_to_load = Vec::new();
857
858            for short_key in &short_keys {
859                if !self.updates.contains_key(short_key) {
860                    let key = self
861                        .context
862                        .base_key()
863                        .base_tag_index(KeyTag::Subview as u8, short_key);
864                    let context = self.context.clone_with_base_key(key);
865                    keys.extend(W::pre_load(&context)?);
866                    short_keys_to_load.push(short_key.to_vec());
867                }
868            }
869
870            let values = self.context.store().read_multi_values_bytes(&keys).await?;
871            for (loaded_values, short_key) in values
872                .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
873                .zip(short_keys_to_load)
874            {
875                let key = self
876                    .context
877                    .base_key()
878                    .base_tag_index(KeyTag::Subview as u8, &short_key);
879                let context = self.context.clone_with_base_key(key);
880                let view = W::post_load(context, loaded_values)?;
881                let wrapped_view = Arc::new(RwLock::new(view));
882                self.updates
883                    .insert(short_key.to_vec(), Update::Set(wrapped_view));
884            }
885        }
886        short_keys
887            .into_iter()
888            .map(|short_key| {
889                let Some(Update::Set(view)) = self.updates.get(&short_key) else {
890                    unreachable!("All entries should have been loaded into `updates`")
891                };
892                let guard = WriteGuardedView(
893                    view.clone()
894                        .try_write_arc()
895                        .ok_or_else(|| ViewError::TryLockError(short_key.clone()))?,
896                );
897                Ok((short_key, guard))
898            })
899            .collect()
900    }
901}
902
903impl<W: View> ReentrantByteCollectionView<W::Context, W> {
904    /// Returns the list of indices in the collection in lexicographic order.
905    /// ```rust
906    /// # tokio_test::block_on(async {
907    /// # use linera_views::context::MemoryContext;
908    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
909    /// # use linera_views::register_view::RegisterView;
910    /// # use linera_views::views::View;
911    /// # let context = MemoryContext::new_for_testing(());
912    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
913    ///     ReentrantByteCollectionView::load(context).await.unwrap();
914    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
915    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
916    /// let keys = view.keys().await.unwrap();
917    /// assert_eq!(keys, vec![vec![0, 1], vec![0, 2]]);
918    /// # })
919    /// ```
920    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
921        let mut keys = Vec::new();
922        self.for_each_key(|key| {
923            keys.push(key.to_vec());
924            Ok(())
925        })
926        .await?;
927        Ok(keys)
928    }
929
930    /// Returns the number of indices of the collection.
931    /// ```rust
932    /// # tokio_test::block_on(async {
933    /// # use linera_views::context::MemoryContext;
934    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
935    /// # use linera_views::register_view::RegisterView;
936    /// # use linera_views::views::View;
937    /// # let context = MemoryContext::new_for_testing(());
938    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
939    ///     ReentrantByteCollectionView::load(context).await.unwrap();
940    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
941    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
942    /// assert_eq!(view.iterative_count().await.unwrap(), 2);
943    /// # })
944    /// ```
945    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
946        let mut count = 0;
947        self.for_each_key(|_key| {
948            count += 1;
949            Ok(())
950        })
951        .await?;
952        Ok(count)
953    }
954
955    /// Applies a function f on each index (aka key). Keys are visited in a
956    /// lexicographic order. If the function returns false then the loop
957    /// ends prematurely.
958    /// ```rust
959    /// # tokio_test::block_on(async {
960    /// # use linera_views::context::MemoryContext;
961    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
962    /// # use linera_views::register_view::RegisterView;
963    /// # use linera_views::views::View;
964    /// # let context = MemoryContext::new_for_testing(());
965    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
966    ///     ReentrantByteCollectionView::load(context).await.unwrap();
967    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
968    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
969    /// let mut count = 0;
970    /// view.for_each_key_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_key_while<F>(&self, mut f: F) -> Result<(), ViewError>
980    where
981        F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
982    {
983        let mut updates = self.updates.iter();
984        let mut update = updates.next();
985        if !self.delete_storage_first {
986            let base = self.get_index_key(&[]);
987            for index in self.context.store().find_keys_by_prefix(&base).await? {
988                loop {
989                    match update {
990                        Some((key, value)) if key <= &index => {
991                            if let Update::Set(_) = value {
992                                if !f(key)? {
993                                    return Ok(());
994                                }
995                            }
996                            update = updates.next();
997                            if key == &index {
998                                break;
999                            }
1000                        }
1001                        _ => {
1002                            if !f(&index)? {
1003                                return Ok(());
1004                            }
1005                            break;
1006                        }
1007                    }
1008                }
1009            }
1010        }
1011        while let Some((key, value)) = update {
1012            if let Update::Set(_) = value {
1013                if !f(key)? {
1014                    return Ok(());
1015                }
1016            }
1017            update = updates.next();
1018        }
1019        Ok(())
1020    }
1021
1022    /// Applies a function f on each index (aka key). Keys are visited in a
1023    /// lexicographic order.
1024    /// ```rust
1025    /// # tokio_test::block_on(async {
1026    /// # use linera_views::context::MemoryContext;
1027    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
1028    /// # use linera_views::register_view::RegisterView;
1029    /// # use linera_views::views::View;
1030    /// # let context = MemoryContext::new_for_testing(());
1031    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
1032    ///     ReentrantByteCollectionView::load(context).await.unwrap();
1033    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
1034    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
1035    /// let mut count = 0;
1036    /// view.for_each_key(|_key| {
1037    ///     count += 1;
1038    ///     Ok(())
1039    /// })
1040    /// .await
1041    /// .unwrap();
1042    /// assert_eq!(count, 2);
1043    /// # })
1044    /// ```
1045    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
1046    where
1047        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
1048    {
1049        self.for_each_key_while(|key| {
1050            f(key)?;
1051            Ok(true)
1052        })
1053        .await
1054    }
1055}
1056
1057impl<W: HashableView> HashableView for ReentrantByteCollectionView<W::Context, W> {
1058    type Hasher = sha3::Sha3_256;
1059
1060    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1061        #[cfg(with_metrics)]
1062        let _hash_latency = metrics::REENTRANT_COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
1063        let mut hasher = sha3::Sha3_256::default();
1064        let keys = self.keys().await?;
1065        let count = u32::try_from(keys.len()).map_err(|_| ArithmeticError::Overflow)?;
1066        hasher.update_with_bcs_bytes(&count)?;
1067        for key in keys {
1068            hasher.update_with_bytes(&key)?;
1069            let hash = if let Some(entry) = self.updates.get_mut(&key) {
1070                let Update::Set(view) = entry else {
1071                    unreachable!("Loaded entries in updates should always be Update::Set");
1072                };
1073                let mut view = view
1074                    .try_write_arc()
1075                    .ok_or_else(|| ViewError::TryLockError(key))?;
1076                view.hash_mut().await?
1077            } else {
1078                let key = self
1079                    .context
1080                    .base_key()
1081                    .base_tag_index(KeyTag::Subview as u8, &key);
1082                let context = self.context.clone_with_base_key(key);
1083                let mut view = W::load(context).await?;
1084                view.hash_mut().await?
1085            };
1086            hasher.write_all(hash.as_ref())?;
1087        }
1088        Ok(hasher.finalize())
1089    }
1090
1091    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1092        #[cfg(with_metrics)]
1093        let _hash_latency = metrics::REENTRANT_COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
1094        let mut hasher = sha3::Sha3_256::default();
1095        let keys = self.keys().await?;
1096        let count = u32::try_from(keys.len()).map_err(|_| ArithmeticError::Overflow)?;
1097        hasher.update_with_bcs_bytes(&count)?;
1098        for key in keys {
1099            hasher.update_with_bytes(&key)?;
1100            let hash = if let Some(entry) = self.updates.get(&key) {
1101                let Update::Set(view) = entry else {
1102                    unreachable!("Loaded entries in updates should always be Update::Set");
1103                };
1104                let view = view
1105                    .try_read_arc()
1106                    .ok_or_else(|| ViewError::TryLockError(key))?;
1107                view.hash().await?
1108            } else {
1109                let key = self
1110                    .context
1111                    .base_key()
1112                    .base_tag_index(KeyTag::Subview as u8, &key);
1113                let context = self.context.clone_with_base_key(key);
1114                let view = W::load(context).await?;
1115                view.hash().await?
1116            };
1117            hasher.write_all(hash.as_ref())?;
1118        }
1119        Ok(hasher.finalize())
1120    }
1121}
1122
1123/// A view that supports accessing a collection of views of the same kind, indexed by keys,
1124/// possibly several subviews at a time.
1125#[derive(Debug, Allocative)]
1126#[allocative(bound = "C, I, W: Allocative")]
1127pub struct ReentrantCollectionView<C, I, W> {
1128    collection: ReentrantByteCollectionView<C, W>,
1129    #[allocative(skip)]
1130    _phantom: PhantomData<I>,
1131}
1132
1133impl<I, W, C2> ReplaceContext<C2> for ReentrantCollectionView<W::Context, I, W>
1134where
1135    W: View + ReplaceContext<C2>,
1136    I: Send + Sync + Serialize + DeserializeOwned,
1137    C2: Context,
1138{
1139    type Target = ReentrantCollectionView<C2, I, <W as ReplaceContext<C2>>::Target>;
1140
1141    async fn with_context(
1142        &mut self,
1143        ctx: impl FnOnce(&Self::Context) -> C2 + Clone,
1144    ) -> Self::Target {
1145        ReentrantCollectionView {
1146            collection: self.collection.with_context(ctx).await,
1147            _phantom: self._phantom,
1148        }
1149    }
1150}
1151
1152impl<I, W> View for ReentrantCollectionView<W::Context, I, W>
1153where
1154    W: View,
1155    I: Send + Sync + Serialize + DeserializeOwned,
1156{
1157    const NUM_INIT_KEYS: usize = ReentrantByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1158
1159    type Context = W::Context;
1160
1161    fn context(&self) -> Self::Context {
1162        self.collection.context()
1163    }
1164
1165    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1166        ReentrantByteCollectionView::<W::Context, W>::pre_load(context)
1167    }
1168
1169    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1170        let collection = ReentrantByteCollectionView::post_load(context, values)?;
1171        Ok(ReentrantCollectionView {
1172            collection,
1173            _phantom: PhantomData,
1174        })
1175    }
1176
1177    fn rollback(&mut self) {
1178        self.collection.rollback()
1179    }
1180
1181    async fn has_pending_changes(&self) -> bool {
1182        self.collection.has_pending_changes().await
1183    }
1184
1185    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
1186        self.collection.pre_save(batch)
1187    }
1188
1189    fn post_save(&mut self) {
1190        self.collection.post_save()
1191    }
1192
1193    fn clear(&mut self) {
1194        self.collection.clear()
1195    }
1196}
1197
1198impl<I, W> ClonableView for ReentrantCollectionView<W::Context, I, W>
1199where
1200    W: ClonableView,
1201    I: Send + Sync + Serialize + DeserializeOwned,
1202{
1203    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1204        Ok(ReentrantCollectionView {
1205            collection: self.collection.clone_unchecked()?,
1206            _phantom: PhantomData,
1207        })
1208    }
1209}
1210
1211impl<I, W> ReentrantCollectionView<W::Context, I, W>
1212where
1213    W: View,
1214    I: Sync + Send + Serialize + DeserializeOwned,
1215{
1216    /// Loads a subview for the data at the given index in the collection. If an entry
1217    /// is absent then a default entry is put on the collection. The obtained view can
1218    /// then be modified.
1219    /// ```rust
1220    /// # tokio_test::block_on(async {
1221    /// # use linera_views::context::MemoryContext;
1222    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1223    /// # use linera_views::register_view::RegisterView;
1224    /// # use linera_views::views::View;
1225    /// # let context = MemoryContext::new_for_testing(());
1226    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1227    ///     ReentrantCollectionView::load(context).await.unwrap();
1228    /// let subview = view.try_load_entry_mut(&23).await.unwrap();
1229    /// let value = subview.get();
1230    /// assert_eq!(*value, String::default());
1231    /// # })
1232    /// ```
1233    pub async fn try_load_entry_mut<Q>(
1234        &mut self,
1235        index: &Q,
1236    ) -> Result<WriteGuardedView<W>, ViewError>
1237    where
1238        I: Borrow<Q>,
1239        Q: Serialize + ?Sized,
1240    {
1241        let short_key = BaseKey::derive_short_key(index)?;
1242        self.collection.try_load_entry_mut(&short_key).await
1243    }
1244
1245    /// Loads a subview at the given index in the collection and gives read-only access to the data.
1246    /// If an entry is absent then `None` is returned.
1247    /// ```rust
1248    /// # tokio_test::block_on(async {
1249    /// # use linera_views::context::MemoryContext;
1250    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1251    /// # use linera_views::register_view::RegisterView;
1252    /// # use linera_views::views::View;
1253    /// # let context = MemoryContext::new_for_testing(());
1254    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1255    ///     ReentrantCollectionView::load(context).await.unwrap();
1256    /// {
1257    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1258    /// }
1259    /// let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1260    /// let value = subview.get();
1261    /// assert_eq!(*value, String::default());
1262    /// # })
1263    /// ```
1264    pub async fn try_load_entry<Q>(
1265        &self,
1266        index: &Q,
1267    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1268    where
1269        I: Borrow<Q>,
1270        Q: Serialize + ?Sized,
1271    {
1272        let short_key = BaseKey::derive_short_key(index)?;
1273        self.collection.try_load_entry(&short_key).await
1274    }
1275
1276    /// Returns `true` if the collection contains a value for the specified key.
1277    /// ```rust
1278    /// # tokio_test::block_on(async {
1279    /// # use linera_views::context::MemoryContext;
1280    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1281    /// # use linera_views::register_view::RegisterView;
1282    /// # use linera_views::views::View;
1283    /// # let context = MemoryContext::new_for_testing(());
1284    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1285    ///     ReentrantCollectionView::load(context).await.unwrap();
1286    /// let _subview = view.try_load_entry_mut(&23).await.unwrap();
1287    /// assert!(view.contains_key(&23).await.unwrap());
1288    /// assert!(!view.contains_key(&24).await.unwrap());
1289    /// # })
1290    /// ```
1291    pub async fn contains_key<Q>(&self, index: &Q) -> Result<bool, ViewError>
1292    where
1293        I: Borrow<Q>,
1294        Q: Serialize + ?Sized,
1295    {
1296        let short_key = BaseKey::derive_short_key(index)?;
1297        self.collection.contains_key(&short_key).await
1298    }
1299
1300    /// Marks the entry so that it is removed in the next flush.
1301    /// ```rust
1302    /// # tokio_test::block_on(async {
1303    /// # use linera_views::context::MemoryContext;
1304    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1305    /// # use linera_views::register_view::RegisterView;
1306    /// # use linera_views::views::View;
1307    /// # let context = MemoryContext::new_for_testing(());
1308    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1309    ///     ReentrantCollectionView::load(context).await.unwrap();
1310    /// let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1311    /// let value = subview.get_mut();
1312    /// assert_eq!(*value, String::default());
1313    /// view.remove_entry(&23);
1314    /// let keys = view.indices().await.unwrap();
1315    /// assert_eq!(keys.len(), 0);
1316    /// # })
1317    /// ```
1318    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1319    where
1320        I: Borrow<Q>,
1321        Q: Serialize + ?Sized,
1322    {
1323        let short_key = BaseKey::derive_short_key(index)?;
1324        self.collection.remove_entry(short_key);
1325        Ok(())
1326    }
1327
1328    /// Marks the entry so that it is removed in the next flush.
1329    /// ```rust
1330    /// # tokio_test::block_on(async {
1331    /// # use linera_views::context::MemoryContext;
1332    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1333    /// # use linera_views::register_view::RegisterView;
1334    /// # use linera_views::views::View;
1335    /// # let context = MemoryContext::new_for_testing(());
1336    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1337    ///     ReentrantCollectionView::load(context).await.unwrap();
1338    /// {
1339    ///     let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1340    ///     let value = subview.get_mut();
1341    ///     *value = String::from("Hello");
1342    /// }
1343    /// view.try_reset_entry_to_default(&23).unwrap();
1344    /// let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1345    /// let value = subview.get_mut();
1346    /// assert_eq!(*value, String::default());
1347    /// # })
1348    /// ```
1349    pub fn try_reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1350    where
1351        I: Borrow<Q>,
1352        Q: Serialize + ?Sized,
1353    {
1354        let short_key = BaseKey::derive_short_key(index)?;
1355        self.collection.try_reset_entry_to_default(&short_key)
1356    }
1357
1358    /// Gets the extra data.
1359    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1360        self.collection.extra()
1361    }
1362}
1363
1364impl<I, W> ReentrantCollectionView<W::Context, I, W>
1365where
1366    W: View,
1367    I: Sync + Send + Serialize + DeserializeOwned,
1368{
1369    /// Load multiple entries for writing at once.
1370    /// The entries in indices have to be all distinct.
1371    /// ```rust
1372    /// # tokio_test::block_on(async {
1373    /// # use linera_views::context::MemoryContext;
1374    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1375    /// # use linera_views::register_view::RegisterView;
1376    /// # use linera_views::views::View;
1377    /// # let context = MemoryContext::new_for_testing(());
1378    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1379    ///     ReentrantCollectionView::load(context).await.unwrap();
1380    /// let indices = vec![23, 42];
1381    /// let subviews = view.try_load_entries_mut(&indices).await.unwrap();
1382    /// let value1 = subviews[0].get();
1383    /// let value2 = subviews[1].get();
1384    /// assert_eq!(*value1, String::default());
1385    /// assert_eq!(*value2, String::default());
1386    /// # })
1387    /// ```
1388    pub async fn try_load_entries_mut<'a, Q>(
1389        &'a mut self,
1390        indices: impl IntoIterator<Item = &'a Q>,
1391    ) -> Result<Vec<WriteGuardedView<W>>, ViewError>
1392    where
1393        I: Borrow<Q>,
1394        Q: Serialize + 'a,
1395    {
1396        let short_keys = indices
1397            .into_iter()
1398            .map(|index| BaseKey::derive_short_key(index))
1399            .collect::<Result<_, _>>()?;
1400        self.collection.try_load_entries_mut(short_keys).await
1401    }
1402
1403    /// Loads multiple entries for writing at once with their keys.
1404    /// The entries in indices have to be all distinct.
1405    /// ```rust
1406    /// # tokio_test::block_on(async {
1407    /// # use linera_views::context::MemoryContext;
1408    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1409    /// # use linera_views::register_view::RegisterView;
1410    /// # use linera_views::views::View;
1411    /// # let context = MemoryContext::new_for_testing(());
1412    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1413    ///     ReentrantCollectionView::load(context).await.unwrap();
1414    /// let indices = [23, 42];
1415    /// let subviews = view.try_load_entries_pairs_mut(indices).await.unwrap();
1416    /// let value1 = subviews[0].1.get();
1417    /// let value2 = subviews[1].1.get();
1418    /// assert_eq!(*value1, String::default());
1419    /// assert_eq!(*value2, String::default());
1420    /// # })
1421    /// ```
1422    pub async fn try_load_entries_pairs_mut<Q>(
1423        &mut self,
1424        indices: impl IntoIterator<Item = Q>,
1425    ) -> Result<Vec<(Q, WriteGuardedView<W>)>, ViewError>
1426    where
1427        I: Borrow<Q>,
1428        Q: Serialize + Clone,
1429    {
1430        let indices_vec: Vec<Q> = indices.into_iter().collect();
1431        let values = self.try_load_entries_mut(indices_vec.iter()).await?;
1432        Ok(indices_vec.into_iter().zip(values).collect())
1433    }
1434
1435    /// Load multiple entries for reading at once.
1436    /// The entries in indices have to be all distinct.
1437    /// ```rust
1438    /// # tokio_test::block_on(async {
1439    /// # use linera_views::context::MemoryContext;
1440    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1441    /// # use linera_views::register_view::RegisterView;
1442    /// # use linera_views::views::View;
1443    /// # let context = MemoryContext::new_for_testing(());
1444    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1445    ///     ReentrantCollectionView::load(context).await.unwrap();
1446    /// {
1447    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1448    /// }
1449    /// let indices = vec![23, 42];
1450    /// let subviews = view.try_load_entries(&indices).await.unwrap();
1451    /// assert!(subviews[1].is_none());
1452    /// let value0 = subviews[0].as_ref().unwrap().get();
1453    /// assert_eq!(*value0, String::default());
1454    /// # })
1455    /// ```
1456    pub async fn try_load_entries<'a, Q>(
1457        &'a self,
1458        indices: impl IntoIterator<Item = &'a Q>,
1459    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError>
1460    where
1461        I: Borrow<Q>,
1462        Q: Serialize + 'a,
1463    {
1464        let short_keys = indices
1465            .into_iter()
1466            .map(|index| BaseKey::derive_short_key(index))
1467            .collect::<Result<_, _>>()?;
1468        self.collection.try_load_entries(short_keys).await
1469    }
1470
1471    /// Loads multiple entries for reading at once with their keys.
1472    /// The entries in indices have to be all distinct.
1473    /// ```rust
1474    /// # tokio_test::block_on(async {
1475    /// # use linera_views::context::MemoryContext;
1476    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1477    /// # use linera_views::register_view::RegisterView;
1478    /// # use linera_views::views::View;
1479    /// # let context = MemoryContext::new_for_testing(());
1480    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1481    ///     ReentrantCollectionView::load(context).await.unwrap();
1482    /// {
1483    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1484    /// }
1485    /// let indices = [23, 42];
1486    /// let subviews = view.try_load_entries_pairs(indices).await.unwrap();
1487    /// assert!(subviews[1].1.is_none());
1488    /// let value0 = subviews[0].1.as_ref().unwrap().get();
1489    /// assert_eq!(*value0, String::default());
1490    /// # })
1491    /// ```
1492    pub async fn try_load_entries_pairs<Q>(
1493        &self,
1494        indices: impl IntoIterator<Item = Q>,
1495    ) -> Result<Vec<(Q, Option<ReadGuardedView<W>>)>, ViewError>
1496    where
1497        I: Borrow<Q>,
1498        Q: Serialize + Clone,
1499    {
1500        let indices_vec: Vec<Q> = indices.into_iter().collect();
1501        let values = self.try_load_entries(indices_vec.iter()).await?;
1502        Ok(indices_vec.into_iter().zip(values).collect())
1503    }
1504
1505    /// Loads all entries for writing at once.
1506    /// The entries in indices have to be all distinct.
1507    /// ```rust
1508    /// # tokio_test::block_on(async {
1509    /// # use linera_views::context::MemoryContext;
1510    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1511    /// # use linera_views::register_view::RegisterView;
1512    /// # use linera_views::views::View;
1513    /// # let context = MemoryContext::new_for_testing(());
1514    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1515    ///     ReentrantCollectionView::load(context).await.unwrap();
1516    /// {
1517    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1518    /// }
1519    /// let subviews = view.try_load_all_entries_mut().await.unwrap();
1520    /// assert_eq!(subviews.len(), 1);
1521    /// # })
1522    /// ```
1523    pub async fn try_load_all_entries_mut(
1524        &mut self,
1525    ) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError> {
1526        let results = self.collection.try_load_all_entries_mut().await?;
1527        results
1528            .into_iter()
1529            .map(|(short_key, view)| {
1530                let index = BaseKey::deserialize_value(&short_key)?;
1531                Ok((index, view))
1532            })
1533            .collect()
1534    }
1535
1536    /// Load multiple entries for reading at once.
1537    /// The entries in indices have to be all distinct.
1538    /// ```rust
1539    /// # tokio_test::block_on(async {
1540    /// # use linera_views::context::MemoryContext;
1541    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1542    /// # use linera_views::register_view::RegisterView;
1543    /// # use linera_views::views::View;
1544    /// # let context = MemoryContext::new_for_testing(());
1545    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1546    ///     ReentrantCollectionView::load(context).await.unwrap();
1547    /// {
1548    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1549    /// }
1550    /// let subviews = view.try_load_all_entries().await.unwrap();
1551    /// assert_eq!(subviews.len(), 1);
1552    /// # })
1553    /// ```
1554    pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError> {
1555        let results = self.collection.try_load_all_entries().await?;
1556        results
1557            .into_iter()
1558            .map(|(short_key, view)| {
1559                let index = BaseKey::deserialize_value(&short_key)?;
1560                Ok((index, view))
1561            })
1562            .collect()
1563    }
1564}
1565
1566impl<I, W> ReentrantCollectionView<W::Context, I, W>
1567where
1568    W: View,
1569    I: Sync + Send + Serialize + DeserializeOwned,
1570{
1571    /// Returns the list of indices in the collection in an order determined
1572    /// by serialization.
1573    /// ```rust
1574    /// # tokio_test::block_on(async {
1575    /// # use linera_views::context::MemoryContext;
1576    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1577    /// # use linera_views::register_view::RegisterView;
1578    /// # use linera_views::views::View;
1579    /// # let context = MemoryContext::new_for_testing(());
1580    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1581    ///     ReentrantCollectionView::load(context).await.unwrap();
1582    /// view.try_load_entry_mut(&23).await.unwrap();
1583    /// view.try_load_entry_mut(&25).await.unwrap();
1584    /// let indices = view.indices().await.unwrap();
1585    /// assert_eq!(indices.len(), 2);
1586    /// # })
1587    /// ```
1588    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
1589        let mut indices = Vec::new();
1590        self.for_each_index(|index| {
1591            indices.push(index);
1592            Ok(())
1593        })
1594        .await?;
1595        Ok(indices)
1596    }
1597
1598    /// Returns the number of indices in the collection.
1599    /// ```rust
1600    /// # tokio_test::block_on(async {
1601    /// # use linera_views::context::MemoryContext;
1602    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1603    /// # use linera_views::register_view::RegisterView;
1604    /// # use linera_views::views::View;
1605    /// # let context = MemoryContext::new_for_testing(());
1606    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1607    ///     ReentrantCollectionView::load(context).await.unwrap();
1608    /// view.try_load_entry_mut(&23).await.unwrap();
1609    /// view.try_load_entry_mut(&25).await.unwrap();
1610    /// assert_eq!(view.iterative_count().await.unwrap(), 2);
1611    /// # })
1612    /// ```
1613    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
1614        self.collection.iterative_count().await
1615    }
1616
1617    /// Applies a function f on each index. Indices are visited in an order
1618    /// determined by the serialization. If the function f returns false then
1619    /// the loop ends prematurely.
1620    /// ```rust
1621    /// # tokio_test::block_on(async {
1622    /// # use linera_views::context::MemoryContext;
1623    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1624    /// # use linera_views::register_view::RegisterView;
1625    /// # use linera_views::views::View;
1626    /// # let context = MemoryContext::new_for_testing(());
1627    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1628    ///     ReentrantCollectionView::load(context).await.unwrap();
1629    /// view.try_load_entry_mut(&23).await.unwrap();
1630    /// view.try_load_entry_mut(&24).await.unwrap();
1631    /// let mut count = 0;
1632    /// view.for_each_index_while(|_key| {
1633    ///     count += 1;
1634    ///     Ok(count < 1)
1635    /// })
1636    /// .await
1637    /// .unwrap();
1638    /// assert_eq!(count, 1);
1639    /// # })
1640    /// ```
1641    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1642    where
1643        F: FnMut(I) -> Result<bool, ViewError> + Send,
1644    {
1645        self.collection
1646            .for_each_key_while(|key| {
1647                let index = BaseKey::deserialize_value(key)?;
1648                f(index)
1649            })
1650            .await?;
1651        Ok(())
1652    }
1653
1654    /// Applies a function f on each index. Indices are visited in an order
1655    /// determined by the serialization.
1656    /// ```rust
1657    /// # tokio_test::block_on(async {
1658    /// # use linera_views::context::MemoryContext;
1659    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1660    /// # use linera_views::register_view::RegisterView;
1661    /// # use linera_views::views::View;
1662    /// # let context = MemoryContext::new_for_testing(());
1663    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1664    ///     ReentrantCollectionView::load(context).await.unwrap();
1665    /// view.try_load_entry_mut(&23).await.unwrap();
1666    /// view.try_load_entry_mut(&28).await.unwrap();
1667    /// let mut count = 0;
1668    /// view.for_each_index(|_key| {
1669    ///     count += 1;
1670    ///     Ok(())
1671    /// })
1672    /// .await
1673    /// .unwrap();
1674    /// assert_eq!(count, 2);
1675    /// # })
1676    /// ```
1677    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1678    where
1679        F: FnMut(I) -> Result<(), ViewError> + Send,
1680    {
1681        self.collection
1682            .for_each_key(|key| {
1683                let index = BaseKey::deserialize_value(key)?;
1684                f(index)
1685            })
1686            .await?;
1687        Ok(())
1688    }
1689}
1690
1691impl<I, W> HashableView for ReentrantCollectionView<W::Context, I, W>
1692where
1693    W: HashableView,
1694    I: Send + Sync + Serialize + DeserializeOwned,
1695{
1696    type Hasher = sha3::Sha3_256;
1697
1698    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1699        self.collection.hash_mut().await
1700    }
1701
1702    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1703        self.collection.hash().await
1704    }
1705}
1706
1707/// A view that supports accessing a collection of views of the same kind, indexed by an ordered key,
1708/// possibly several subviews at a time.
1709#[derive(Debug, Allocative)]
1710#[allocative(bound = "C, I, W: Allocative")]
1711pub struct ReentrantCustomCollectionView<C, I, W> {
1712    collection: ReentrantByteCollectionView<C, W>,
1713    #[allocative(skip)]
1714    _phantom: PhantomData<I>,
1715}
1716
1717impl<I, W> View for ReentrantCustomCollectionView<W::Context, I, W>
1718where
1719    W: View,
1720    I: Send + Sync + CustomSerialize,
1721{
1722    const NUM_INIT_KEYS: usize = ReentrantByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1723
1724    type Context = W::Context;
1725
1726    fn context(&self) -> Self::Context {
1727        self.collection.context()
1728    }
1729
1730    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1731        ReentrantByteCollectionView::<_, W>::pre_load(context)
1732    }
1733
1734    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1735        let collection = ReentrantByteCollectionView::post_load(context, values)?;
1736        Ok(ReentrantCustomCollectionView {
1737            collection,
1738            _phantom: PhantomData,
1739        })
1740    }
1741
1742    fn rollback(&mut self) {
1743        self.collection.rollback()
1744    }
1745
1746    async fn has_pending_changes(&self) -> bool {
1747        self.collection.has_pending_changes().await
1748    }
1749
1750    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
1751        self.collection.pre_save(batch)
1752    }
1753
1754    fn post_save(&mut self) {
1755        self.collection.post_save()
1756    }
1757
1758    fn clear(&mut self) {
1759        self.collection.clear()
1760    }
1761}
1762
1763impl<I, W> ClonableView for ReentrantCustomCollectionView<W::Context, I, W>
1764where
1765    W: ClonableView,
1766    Self: View,
1767{
1768    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1769        Ok(ReentrantCustomCollectionView {
1770            collection: self.collection.clone_unchecked()?,
1771            _phantom: PhantomData,
1772        })
1773    }
1774}
1775
1776impl<I, W> ReentrantCustomCollectionView<W::Context, I, W>
1777where
1778    W: View,
1779    I: Sync + Send + CustomSerialize,
1780{
1781    /// Loads a subview for the data at the given index in the collection. If an entry
1782    /// is absent then a default entry is put in the collection on this index.
1783    /// ```rust
1784    /// # tokio_test::block_on(async {
1785    /// # use linera_views::context::MemoryContext;
1786    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1787    /// # use linera_views::register_view::RegisterView;
1788    /// # use linera_views::views::View;
1789    /// # let context = MemoryContext::new_for_testing(());
1790    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1791    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1792    /// let subview = view.try_load_entry_mut(&23).await.unwrap();
1793    /// let value = subview.get();
1794    /// assert_eq!(*value, String::default());
1795    /// # })
1796    /// ```
1797    pub async fn try_load_entry_mut<Q>(
1798        &mut self,
1799        index: &Q,
1800    ) -> Result<WriteGuardedView<W>, ViewError>
1801    where
1802        I: Borrow<Q>,
1803        Q: CustomSerialize,
1804    {
1805        let short_key = index.to_custom_bytes()?;
1806        self.collection.try_load_entry_mut(&short_key).await
1807    }
1808
1809    /// Loads a subview at the given index in the collection and gives read-only access to the data.
1810    /// If an entry is absent then `None` is returned.
1811    /// ```rust
1812    /// # tokio_test::block_on(async {
1813    /// # use linera_views::context::MemoryContext;
1814    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1815    /// # use linera_views::register_view::RegisterView;
1816    /// # use linera_views::views::View;
1817    /// # let context = MemoryContext::new_for_testing(());
1818    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1819    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1820    /// {
1821    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1822    /// }
1823    /// let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1824    /// let value = subview.get();
1825    /// assert_eq!(*value, String::default());
1826    /// # })
1827    /// ```
1828    pub async fn try_load_entry<Q>(
1829        &self,
1830        index: &Q,
1831    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1832    where
1833        I: Borrow<Q>,
1834        Q: CustomSerialize,
1835    {
1836        let short_key = index.to_custom_bytes()?;
1837        self.collection.try_load_entry(&short_key).await
1838    }
1839
1840    /// Returns `true` if the collection contains a value for the specified key.
1841    /// ```rust
1842    /// # tokio_test::block_on(async {
1843    /// # use linera_views::context::MemoryContext;
1844    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1845    /// # use linera_views::register_view::RegisterView;
1846    /// # use linera_views::views::View;
1847    /// # let context = MemoryContext::new_for_testing(());
1848    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1849    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1850    /// let _subview = view.try_load_entry_mut(&23).await.unwrap();
1851    /// assert!(view.contains_key(&23).await.unwrap());
1852    /// assert!(!view.contains_key(&24).await.unwrap());
1853    /// # })
1854    /// ```
1855    pub async fn contains_key<Q>(&self, index: &Q) -> Result<bool, ViewError>
1856    where
1857        I: Borrow<Q>,
1858        Q: CustomSerialize,
1859    {
1860        let short_key = index.to_custom_bytes()?;
1861        self.collection.contains_key(&short_key).await
1862    }
1863
1864    /// Removes an entry. If absent then nothing happens.
1865    /// ```rust
1866    /// # tokio_test::block_on(async {
1867    /// # use linera_views::context::MemoryContext;
1868    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1869    /// # use linera_views::register_view::RegisterView;
1870    /// # use linera_views::views::View;
1871    /// # let context = MemoryContext::new_for_testing(());
1872    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1873    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1874    /// let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1875    /// let value = subview.get_mut();
1876    /// assert_eq!(*value, String::default());
1877    /// view.remove_entry(&23);
1878    /// let keys = view.indices().await.unwrap();
1879    /// assert_eq!(keys.len(), 0);
1880    /// # })
1881    /// ```
1882    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1883    where
1884        I: Borrow<Q>,
1885        Q: CustomSerialize,
1886    {
1887        let short_key = index.to_custom_bytes()?;
1888        self.collection.remove_entry(short_key);
1889        Ok(())
1890    }
1891
1892    /// Marks the entry so that it is removed in the next flush.
1893    /// ```rust
1894    /// # tokio_test::block_on(async {
1895    /// # use linera_views::context::MemoryContext;
1896    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1897    /// # use linera_views::register_view::RegisterView;
1898    /// # use linera_views::views::View;
1899    /// # let context = MemoryContext::new_for_testing(());
1900    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1901    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1902    /// {
1903    ///     let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1904    ///     let value = subview.get_mut();
1905    ///     *value = String::from("Hello");
1906    /// }
1907    /// {
1908    ///     view.try_reset_entry_to_default(&23).unwrap();
1909    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1910    ///     let value = subview.get();
1911    ///     assert_eq!(*value, String::default());
1912    /// }
1913    /// # })
1914    /// ```
1915    pub fn try_reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1916    where
1917        I: Borrow<Q>,
1918        Q: CustomSerialize,
1919    {
1920        let short_key = index.to_custom_bytes()?;
1921        self.collection.try_reset_entry_to_default(&short_key)
1922    }
1923
1924    /// Gets the extra data.
1925    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1926        self.collection.extra()
1927    }
1928}
1929
1930impl<I, W: View> ReentrantCustomCollectionView<W::Context, I, W>
1931where
1932    I: Sync + Send + CustomSerialize,
1933{
1934    /// Load multiple entries for writing at once.
1935    /// The entries in indices have to be all distinct.
1936    /// ```rust
1937    /// # tokio_test::block_on(async {
1938    /// # use linera_views::context::MemoryContext;
1939    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1940    /// # use linera_views::register_view::RegisterView;
1941    /// # use linera_views::views::View;
1942    /// # let context = MemoryContext::new_for_testing(());
1943    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1944    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1945    /// let subviews = view.try_load_entries_mut(&[23, 42]).await.unwrap();
1946    /// let value1 = subviews[0].get();
1947    /// let value2 = subviews[1].get();
1948    /// assert_eq!(*value1, String::default());
1949    /// assert_eq!(*value2, String::default());
1950    /// # })
1951    /// ```
1952    pub async fn try_load_entries_mut<'a, Q>(
1953        &mut self,
1954        indices: impl IntoIterator<Item = &'a Q>,
1955    ) -> Result<Vec<WriteGuardedView<W>>, ViewError>
1956    where
1957        I: Borrow<Q>,
1958        Q: CustomSerialize + 'a,
1959    {
1960        let short_keys = indices
1961            .into_iter()
1962            .map(|index| index.to_custom_bytes())
1963            .collect::<Result<_, _>>()?;
1964        self.collection.try_load_entries_mut(short_keys).await
1965    }
1966
1967    /// Loads multiple entries for writing at once with their keys.
1968    /// The entries in indices have to be all distinct.
1969    /// ```rust
1970    /// # tokio_test::block_on(async {
1971    /// # use linera_views::context::MemoryContext;
1972    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1973    /// # use linera_views::register_view::RegisterView;
1974    /// # use linera_views::views::View;
1975    /// # let context = MemoryContext::new_for_testing(());
1976    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1977    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1978    /// let indices = [23, 42];
1979    /// let subviews = view.try_load_entries_pairs_mut(indices).await.unwrap();
1980    /// let value1 = subviews[0].1.get();
1981    /// let value2 = subviews[1].1.get();
1982    /// assert_eq!(*value1, String::default());
1983    /// assert_eq!(*value2, String::default());
1984    /// # })
1985    /// ```
1986    pub async fn try_load_entries_pairs_mut<Q>(
1987        &mut self,
1988        indices: impl IntoIterator<Item = Q>,
1989    ) -> Result<Vec<(Q, WriteGuardedView<W>)>, ViewError>
1990    where
1991        I: Borrow<Q>,
1992        Q: CustomSerialize + Clone,
1993    {
1994        let indices_vec: Vec<Q> = indices.into_iter().collect();
1995        let values = self.try_load_entries_mut(indices_vec.iter()).await?;
1996        Ok(indices_vec.into_iter().zip(values).collect())
1997    }
1998
1999    /// Load multiple entries for reading at once.
2000    /// The entries in indices have to be all distinct.
2001    /// ```rust
2002    /// # tokio_test::block_on(async {
2003    /// # use linera_views::context::MemoryContext;
2004    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2005    /// # use linera_views::register_view::RegisterView;
2006    /// # use linera_views::views::View;
2007    /// # let context = MemoryContext::new_for_testing(());
2008    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2009    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2010    /// {
2011    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2012    /// }
2013    /// let subviews = view.try_load_entries(&[23, 42]).await.unwrap();
2014    /// assert!(subviews[1].is_none());
2015    /// let value0 = subviews[0].as_ref().unwrap().get();
2016    /// assert_eq!(*value0, String::default());
2017    /// # })
2018    /// ```
2019    pub async fn try_load_entries<'a, Q>(
2020        &self,
2021        indices: impl IntoIterator<Item = &'a Q>,
2022    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError>
2023    where
2024        I: Borrow<Q>,
2025        Q: CustomSerialize + 'a,
2026    {
2027        let short_keys = indices
2028            .into_iter()
2029            .map(|index| index.to_custom_bytes())
2030            .collect::<Result<_, _>>()?;
2031        self.collection.try_load_entries(short_keys).await
2032    }
2033
2034    /// Loads multiple entries for reading at once with their keys.
2035    /// The entries in indices have to be all distinct.
2036    /// ```rust
2037    /// # tokio_test::block_on(async {
2038    /// # use linera_views::context::MemoryContext;
2039    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2040    /// # use linera_views::register_view::RegisterView;
2041    /// # use linera_views::views::View;
2042    /// # let context = MemoryContext::new_for_testing(());
2043    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2044    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2045    /// {
2046    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2047    /// }
2048    /// let indices = [23, 42];
2049    /// let subviews = view.try_load_entries_pairs(indices).await.unwrap();
2050    /// assert!(subviews[1].1.is_none());
2051    /// let value0 = subviews[0].1.as_ref().unwrap().get();
2052    /// assert_eq!(*value0, String::default());
2053    /// # })
2054    /// ```
2055    pub async fn try_load_entries_pairs<Q>(
2056        &self,
2057        indices: impl IntoIterator<Item = Q>,
2058    ) -> Result<Vec<(Q, Option<ReadGuardedView<W>>)>, ViewError>
2059    where
2060        I: Borrow<Q>,
2061        Q: CustomSerialize + Clone,
2062    {
2063        let indices_vec: Vec<Q> = indices.into_iter().collect();
2064        let values = self.try_load_entries(indices_vec.iter()).await?;
2065        Ok(indices_vec.into_iter().zip(values).collect())
2066    }
2067
2068    /// Loads all entries for writing at once.
2069    /// The entries in indices have to be all distinct.
2070    /// ```rust
2071    /// # tokio_test::block_on(async {
2072    /// # use linera_views::context::MemoryContext;
2073    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2074    /// # use linera_views::register_view::RegisterView;
2075    /// # use linera_views::views::View;
2076    /// # let context = MemoryContext::new_for_testing(());
2077    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2078    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2079    /// {
2080    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2081    /// }
2082    /// let subviews = view.try_load_all_entries_mut().await.unwrap();
2083    /// assert_eq!(subviews.len(), 1);
2084    /// # })
2085    /// ```
2086    pub async fn try_load_all_entries_mut(
2087        &mut self,
2088    ) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError> {
2089        let results = self.collection.try_load_all_entries_mut().await?;
2090        results
2091            .into_iter()
2092            .map(|(short_key, view)| {
2093                let index = I::from_custom_bytes(&short_key)?;
2094                Ok((index, view))
2095            })
2096            .collect()
2097    }
2098
2099    /// Load multiple entries for reading at once.
2100    /// The entries in indices have to be all distinct.
2101    /// ```rust
2102    /// # tokio_test::block_on(async {
2103    /// # use linera_views::context::MemoryContext;
2104    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2105    /// # use linera_views::register_view::RegisterView;
2106    /// # use linera_views::views::View;
2107    /// # let context = MemoryContext::new_for_testing(());
2108    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2109    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2110    /// {
2111    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2112    /// }
2113    /// let subviews = view.try_load_all_entries().await.unwrap();
2114    /// assert_eq!(subviews.len(), 1);
2115    /// # })
2116    /// ```
2117    pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError> {
2118        let results = self.collection.try_load_all_entries().await?;
2119        results
2120            .into_iter()
2121            .map(|(short_key, view)| {
2122                let index = I::from_custom_bytes(&short_key)?;
2123                Ok((index, view))
2124            })
2125            .collect()
2126    }
2127}
2128
2129impl<I, W> ReentrantCustomCollectionView<W::Context, I, W>
2130where
2131    W: View,
2132    I: Sync + Send + CustomSerialize,
2133{
2134    /// Returns the list of indices in the collection. The order is determined by
2135    /// the custom serialization.
2136    /// ```rust
2137    /// # tokio_test::block_on(async {
2138    /// # use linera_views::context::MemoryContext;
2139    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2140    /// # use linera_views::register_view::RegisterView;
2141    /// # use linera_views::views::View;
2142    /// # let context = MemoryContext::new_for_testing(());
2143    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2144    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2145    /// view.try_load_entry_mut(&23).await.unwrap();
2146    /// view.try_load_entry_mut(&25).await.unwrap();
2147    /// let indices = view.indices().await.unwrap();
2148    /// assert_eq!(indices, vec![23, 25]);
2149    /// # })
2150    /// ```
2151    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
2152        let mut indices = Vec::new();
2153        self.for_each_index(|index| {
2154            indices.push(index);
2155            Ok(())
2156        })
2157        .await?;
2158        Ok(indices)
2159    }
2160
2161    /// Returns the number of entries in the collection.
2162    /// ```rust
2163    /// # tokio_test::block_on(async {
2164    /// # use linera_views::context::MemoryContext;
2165    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2166    /// # use linera_views::register_view::RegisterView;
2167    /// # use linera_views::views::View;
2168    /// # let context = MemoryContext::new_for_testing(());
2169    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2170    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2171    /// view.try_load_entry_mut(&23).await.unwrap();
2172    /// view.try_load_entry_mut(&25).await.unwrap();
2173    /// assert_eq!(view.iterative_count().await.unwrap(), 2);
2174    /// # })
2175    /// ```
2176    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
2177        self.collection.iterative_count().await
2178    }
2179
2180    /// Applies a function f on each index. Indices are visited in an order
2181    /// determined by the custom serialization. If the function f returns false
2182    /// then the loop ends prematurely.
2183    /// ```rust
2184    /// # tokio_test::block_on(async {
2185    /// # use linera_views::context::MemoryContext;
2186    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2187    /// # use linera_views::register_view::RegisterView;
2188    /// # use linera_views::views::View;
2189    /// # let context = MemoryContext::new_for_testing(());
2190    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2191    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2192    /// view.try_load_entry_mut(&28).await.unwrap();
2193    /// view.try_load_entry_mut(&24).await.unwrap();
2194    /// view.try_load_entry_mut(&23).await.unwrap();
2195    /// let mut part_indices = Vec::new();
2196    /// view.for_each_index_while(|index| {
2197    ///     part_indices.push(index);
2198    ///     Ok(part_indices.len() < 2)
2199    /// })
2200    /// .await
2201    /// .unwrap();
2202    /// assert_eq!(part_indices, vec![23, 24]);
2203    /// # })
2204    /// ```
2205    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
2206    where
2207        F: FnMut(I) -> Result<bool, ViewError> + Send,
2208    {
2209        self.collection
2210            .for_each_key_while(|key| {
2211                let index = I::from_custom_bytes(key)?;
2212                f(index)
2213            })
2214            .await?;
2215        Ok(())
2216    }
2217
2218    /// Applies a function f on each index. Indices are visited in an order
2219    /// determined by the custom serialization.
2220    /// ```rust
2221    /// # tokio_test::block_on(async {
2222    /// # use linera_views::context::MemoryContext;
2223    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2224    /// # use linera_views::register_view::RegisterView;
2225    /// # use linera_views::views::View;
2226    /// # let context = MemoryContext::new_for_testing(());
2227    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2228    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2229    /// view.try_load_entry_mut(&28).await.unwrap();
2230    /// view.try_load_entry_mut(&24).await.unwrap();
2231    /// view.try_load_entry_mut(&23).await.unwrap();
2232    /// let mut indices = Vec::new();
2233    /// view.for_each_index(|index| {
2234    ///     indices.push(index);
2235    ///     Ok(())
2236    /// })
2237    /// .await
2238    /// .unwrap();
2239    /// assert_eq!(indices, vec![23, 24, 28]);
2240    /// # })
2241    /// ```
2242    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
2243    where
2244        F: FnMut(I) -> Result<(), ViewError> + Send,
2245    {
2246        self.collection
2247            .for_each_key(|key| {
2248                let index = I::from_custom_bytes(key)?;
2249                f(index)
2250            })
2251            .await?;
2252        Ok(())
2253    }
2254}
2255
2256impl<I, W> HashableView for ReentrantCustomCollectionView<W::Context, I, W>
2257where
2258    W: HashableView,
2259    I: Send + Sync + CustomSerialize,
2260{
2261    type Hasher = sha3::Sha3_256;
2262
2263    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
2264        self.collection.hash_mut().await
2265    }
2266
2267    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
2268        self.collection.hash().await
2269    }
2270}
2271
2272/// Type wrapping `ReentrantByteCollectionView` while memoizing the hash.
2273pub type HashedReentrantByteCollectionView<C, W> =
2274    WrappedHashableContainerView<C, ReentrantByteCollectionView<C, W>, HasherOutput>;
2275
2276/// Type wrapping `ReentrantCollectionView` while memoizing the hash.
2277pub type HashedReentrantCollectionView<C, I, W> =
2278    WrappedHashableContainerView<C, ReentrantCollectionView<C, I, W>, HasherOutput>;
2279
2280/// Type wrapping `ReentrantCustomCollectionView` while memoizing the hash.
2281pub type HashedReentrantCustomCollectionView<C, I, W> =
2282    WrappedHashableContainerView<C, ReentrantCustomCollectionView<C, I, W>, HasherOutput>;
2283
2284/// Wrapper around `ReentrantByteCollectionView` to compute hashes based on the history of changes.
2285pub type HistoricallyHashedReentrantByteCollectionView<C, W> =
2286    HistoricallyHashableView<C, ReentrantByteCollectionView<C, W>>;
2287
2288/// Wrapper around `ReentrantCollectionView` to compute hashes based on the history of changes.
2289pub type HistoricallyHashedReentrantCollectionView<C, I, W> =
2290    HistoricallyHashableView<C, ReentrantCollectionView<C, I, W>>;
2291
2292/// Wrapper around `ReentrantCustomCollectionView` to compute hashes based on the history of changes.
2293pub type HistoricallyHashedReentrantCustomCollectionView<C, I, W> =
2294    HistoricallyHashableView<C, ReentrantCustomCollectionView<C, I, W>>;
2295
2296#[cfg(with_graphql)]
2297mod graphql {
2298    use std::borrow::Cow;
2299
2300    use super::{ReadGuardedView, ReentrantCollectionView};
2301    use crate::{
2302        graphql::{hash_name, mangle, missing_key_error, Entry, MapInput},
2303        views::View,
2304    };
2305
2306    impl<T: async_graphql::OutputType> async_graphql::OutputType for ReadGuardedView<T> {
2307        fn type_name() -> Cow<'static, str> {
2308            T::type_name()
2309        }
2310
2311        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
2312            T::create_type_info(registry)
2313        }
2314
2315        async fn resolve(
2316            &self,
2317            ctx: &async_graphql::ContextSelectionSet<'_>,
2318            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
2319        ) -> async_graphql::ServerResult<async_graphql::Value> {
2320            (**self).resolve(ctx, field).await
2321        }
2322    }
2323
2324    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
2325        async_graphql::TypeName for ReentrantCollectionView<C, K, V>
2326    {
2327        fn type_name() -> Cow<'static, str> {
2328            format!(
2329                "ReentrantCollectionView_{}_{}_{:08x}",
2330                mangle(K::type_name()),
2331                mangle(V::type_name()),
2332                hash_name::<(K, V)>(),
2333            )
2334            .into()
2335        }
2336    }
2337
2338    #[async_graphql::Object(cache_control(no_cache), name_type)]
2339    impl<K, V> ReentrantCollectionView<V::Context, K, V>
2340    where
2341        K: async_graphql::InputType
2342            + async_graphql::OutputType
2343            + serde::ser::Serialize
2344            + serde::de::DeserializeOwned
2345            + std::fmt::Debug,
2346        V: View + async_graphql::OutputType,
2347    {
2348        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
2349            Ok(self.indices().await?)
2350        }
2351
2352        #[graphql(derived(name = "count"))]
2353        async fn count_(&self) -> Result<u32, async_graphql::Error> {
2354            let count = self.iterative_count().await?;
2355            u32::try_from(count).map_err(|_| async_graphql::Error::new("count exceeds u32"))
2356        }
2357
2358        async fn entry(
2359            &self,
2360            key: K,
2361        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
2362            let value = self
2363                .try_load_entry(&key)
2364                .await?
2365                .ok_or_else(|| missing_key_error(&key))?;
2366            Ok(Entry { value, key })
2367        }
2368
2369        async fn entries(
2370            &self,
2371            input: Option<MapInput<K>>,
2372        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
2373            let keys = if let Some(keys) = input
2374                .and_then(|input| input.filters)
2375                .and_then(|filters| filters.keys)
2376            {
2377                keys
2378            } else {
2379                self.indices().await?
2380            };
2381
2382            let values = self.try_load_entries(&keys).await?;
2383            Ok(values
2384                .into_iter()
2385                .zip(keys)
2386                .filter_map(|(value, key)| value.map(|value| Entry { value, key }))
2387                .collect())
2388        }
2389    }
2390
2391    use crate::reentrant_collection_view::ReentrantCustomCollectionView;
2392    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
2393        async_graphql::TypeName for ReentrantCustomCollectionView<C, K, V>
2394    {
2395        fn type_name() -> Cow<'static, str> {
2396            format!(
2397                "ReentrantCustomCollectionView_{}_{}_{:08x}",
2398                mangle(K::type_name()),
2399                mangle(V::type_name()),
2400                hash_name::<(K, V)>(),
2401            )
2402            .into()
2403        }
2404    }
2405
2406    #[async_graphql::Object(cache_control(no_cache), name_type)]
2407    impl<K, V> ReentrantCustomCollectionView<V::Context, K, V>
2408    where
2409        K: async_graphql::InputType
2410            + async_graphql::OutputType
2411            + crate::common::CustomSerialize
2412            + std::fmt::Debug,
2413        V: View + async_graphql::OutputType,
2414    {
2415        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
2416            Ok(self.indices().await?)
2417        }
2418
2419        async fn entry(
2420            &self,
2421            key: K,
2422        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
2423            let value = self
2424                .try_load_entry(&key)
2425                .await?
2426                .ok_or_else(|| missing_key_error(&key))?;
2427            Ok(Entry { value, key })
2428        }
2429
2430        async fn entries(
2431            &self,
2432            input: Option<MapInput<K>>,
2433        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
2434            let keys = if let Some(keys) = input
2435                .and_then(|input| input.filters)
2436                .and_then(|filters| filters.keys)
2437            {
2438                keys
2439            } else {
2440                self.indices().await?
2441            };
2442
2443            let values = self.try_load_entries(&keys).await?;
2444            Ok(values
2445                .into_iter()
2446                .zip(keys)
2447                .filter_map(|(value, key)| value.map(|value| Entry { value, key }))
2448                .collect())
2449        }
2450    }
2451}