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