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                        "Entry should have been inserted as Update::Set by try_load_view_mut"
596                    )
597                };
598                Ok(WriteGuardedView(
599                    view.clone()
600                        .try_write_arc()
601                        .ok_or_else(|| ViewError::TryLockError(short_key))?,
602                ))
603            })
604            .collect()
605    }
606
607    /// Loads multiple entries for writing at once with their keys.
608    /// The entries in short_keys have to be all distinct.
609    /// ```rust
610    /// # tokio_test::block_on(async {
611    /// # use linera_views::context::MemoryContext;
612    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
613    /// # use linera_views::register_view::RegisterView;
614    /// # use linera_views::views::View;
615    /// # let context = MemoryContext::new_for_testing(());
616    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
617    ///     ReentrantByteCollectionView::load(context).await.unwrap();
618    /// {
619    ///     let mut subview = view.try_load_entry_mut(&vec![0, 1]).await.unwrap();
620    ///     *subview.get_mut() = "Bonjour".to_string();
621    /// }
622    /// let short_keys = vec![vec![0, 1], vec![2, 3]];
623    /// let subviews = view.try_load_entries_pairs_mut(short_keys).await.unwrap();
624    /// let value1 = subviews[0].1.get();
625    /// let value2 = subviews[1].1.get();
626    /// assert_eq!(*value1, "Bonjour".to_string());
627    /// assert_eq!(*value2, String::default());
628    /// # })
629    /// ```
630    pub async fn try_load_entries_pairs_mut(
631        &mut self,
632        short_keys: Vec<Vec<u8>>,
633    ) -> Result<Vec<(Vec<u8>, WriteGuardedView<W>)>, ViewError> {
634        let values = self.try_load_entries_mut(short_keys.clone()).await?;
635        Ok(short_keys.into_iter().zip(values).collect())
636    }
637
638    /// Loads multiple entries for reading at once.
639    /// The entries in `short_keys` have to be all distinct.
640    /// ```rust
641    /// # tokio_test::block_on(async {
642    /// # use linera_views::context::MemoryContext;
643    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
644    /// # use linera_views::register_view::RegisterView;
645    /// # use linera_views::views::View;
646    /// # let context = MemoryContext::new_for_testing(());
647    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
648    ///     ReentrantByteCollectionView::load(context).await.unwrap();
649    /// {
650    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
651    /// }
652    /// let short_keys = vec![vec![0, 1], vec![2, 3]];
653    /// let subviews = view.try_load_entries(short_keys).await.unwrap();
654    /// assert!(subviews[1].is_none());
655    /// let value0 = subviews[0].as_ref().unwrap().get();
656    /// assert_eq!(*value0, String::default());
657    /// # })
658    /// ```
659    pub async fn try_load_entries(
660        &self,
661        short_keys: Vec<Vec<u8>>,
662    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError> {
663        let mut results = vec![None; short_keys.len()];
664        let mut keys_to_check = Vec::new();
665        let mut keys_to_check_metadata = Vec::new();
666
667        for (position, short_key) in short_keys.into_iter().enumerate() {
668            if let Some(update) = self.updates.get(&short_key) {
669                if let Update::Set(view) = update {
670                    results[position] = Some((short_key, view.clone()));
671                }
672            } else if !self.delete_storage_first {
673                let key_index = self
674                    .context
675                    .base_key()
676                    .base_tag_index(KeyTag::Index as u8, &short_key);
677                keys_to_check.push(key_index);
678                keys_to_check_metadata.push((position, short_key));
679            }
680        }
681
682        let found_keys = self.context.store().contains_keys(&keys_to_check).await?;
683        let entries_to_load = keys_to_check_metadata
684            .into_iter()
685            .zip(found_keys)
686            .filter_map(|(metadata, found)| found.then_some(metadata))
687            .map(|(position, short_key)| {
688                let subview_key = self
689                    .context
690                    .base_key()
691                    .base_tag_index(KeyTag::Subview as u8, &short_key);
692                let subview_context = self.context.clone_with_base_key(subview_key);
693                (position, short_key.to_owned(), subview_context)
694            })
695            .collect::<Vec<_>>();
696        if !entries_to_load.is_empty() {
697            let mut keys_to_load = Vec::with_capacity(entries_to_load.len() * W::NUM_INIT_KEYS);
698            for (_, _, context) in &entries_to_load {
699                keys_to_load.extend(W::pre_load(context)?);
700            }
701            let values = self
702                .context
703                .store()
704                .read_multi_values_bytes(&keys_to_load)
705                .await?;
706            for (loaded_values, (position, short_key, context)) in values
707                .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
708                .zip(entries_to_load)
709            {
710                let view = W::post_load(context, loaded_values)?;
711                let wrapped_view = Arc::new(RwLock::new(view));
712                results[position] = Some((short_key, wrapped_view));
713            }
714        }
715
716        results
717            .into_iter()
718            .map(|maybe_view| match maybe_view {
719                Some((short_key, view)) => Ok(Some(ReadGuardedView(
720                    view.try_read_arc()
721                        .ok_or_else(|| ViewError::TryLockError(short_key))?,
722                ))),
723                None => Ok(None),
724            })
725            .collect()
726    }
727
728    /// Loads multiple entries for reading at once with their keys.
729    /// The entries in short_keys have to be all distinct.
730    /// ```rust
731    /// # tokio_test::block_on(async {
732    /// # use linera_views::context::MemoryContext;
733    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
734    /// # use linera_views::register_view::RegisterView;
735    /// # use linera_views::views::View;
736    /// # let context = MemoryContext::new_for_testing(());
737    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
738    ///     ReentrantByteCollectionView::load(context).await.unwrap();
739    /// {
740    ///     let _subview = view.try_load_entry_mut(&vec![0, 1]).await.unwrap();
741    /// }
742    /// let short_keys = vec![vec![0, 1], vec![0, 2]];
743    /// let subviews = view.try_load_entries_pairs(short_keys).await.unwrap();
744    /// assert!(subviews[1].1.is_none());
745    /// let value0 = subviews[0].1.as_ref().unwrap().get();
746    /// assert_eq!(*value0, String::default());
747    /// # })
748    /// ```
749    pub async fn try_load_entries_pairs(
750        &self,
751        short_keys: Vec<Vec<u8>>,
752    ) -> Result<Vec<(Vec<u8>, Option<ReadGuardedView<W>>)>, ViewError> {
753        let values = self.try_load_entries(short_keys.clone()).await?;
754        Ok(short_keys.into_iter().zip(values).collect())
755    }
756
757    /// Loads all the entries for reading at once.
758    /// ```rust
759    /// # tokio_test::block_on(async {
760    /// # use linera_views::context::MemoryContext;
761    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
762    /// # use linera_views::register_view::RegisterView;
763    /// # use linera_views::views::View;
764    /// # let context = MemoryContext::new_for_testing(());
765    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
766    ///     ReentrantByteCollectionView::load(context).await.unwrap();
767    /// {
768    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
769    /// }
770    /// let subviews = view.try_load_all_entries().await.unwrap();
771    /// assert_eq!(subviews.len(), 1);
772    /// # })
773    /// ```
774    pub async fn try_load_all_entries(
775        &self,
776    ) -> Result<Vec<(Vec<u8>, ReadGuardedView<W>)>, ViewError> {
777        let short_keys = self.keys().await?;
778        let mut loaded_views = vec![None; short_keys.len()];
779
780        // Load views that are not in updates and not deleted
781        if !self.delete_storage_first {
782            let mut keys = Vec::new();
783            let mut short_keys_and_indexes = Vec::new();
784            for (index, short_key) in short_keys.iter().enumerate() {
785                if !self.updates.contains_key(short_key) {
786                    let key = self
787                        .context
788                        .base_key()
789                        .base_tag_index(KeyTag::Subview as u8, short_key);
790                    let context = self.context.clone_with_base_key(key);
791                    keys.extend(W::pre_load(&context)?);
792                    short_keys_and_indexes.push((short_key.to_vec(), index));
793                }
794            }
795            let values = self.context.store().read_multi_values_bytes(&keys).await?;
796            for (loaded_values, (short_key, index)) in values
797                .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
798                .zip(short_keys_and_indexes)
799            {
800                let key = self
801                    .context
802                    .base_key()
803                    .base_tag_index(KeyTag::Subview as u8, &short_key);
804                let context = self.context.clone_with_base_key(key);
805                let view = W::post_load(context, loaded_values)?;
806                let wrapped_view = Arc::new(RwLock::new(view));
807                loaded_views[index] = Some(wrapped_view);
808            }
809        }
810
811        // Create result from updates and loaded views
812        short_keys
813            .into_iter()
814            .zip(loaded_views)
815            .map(|(short_key, loaded_view)| {
816                let view = if let Some(Update::Set(view)) = self.updates.get(&short_key) {
817                    view.clone()
818                } else if let Some(view) = loaded_view {
819                    view
820                } else {
821                    unreachable!("All entries should have been loaded into memory");
822                };
823                let guard = ReadGuardedView(
824                    view.try_read_arc()
825                        .ok_or_else(|| ViewError::TryLockError(short_key.clone()))?,
826                );
827                Ok((short_key, guard))
828            })
829            .collect()
830    }
831
832    /// Loads all the entries for writing at once.
833    /// ```rust
834    /// # tokio_test::block_on(async {
835    /// # use linera_views::context::MemoryContext;
836    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
837    /// # use linera_views::register_view::RegisterView;
838    /// # use linera_views::views::View;
839    /// # let context = MemoryContext::new_for_testing(());
840    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
841    ///     ReentrantByteCollectionView::load(context).await.unwrap();
842    /// {
843    ///     let _subview = view.try_load_entry_mut(&[0, 1]).await.unwrap();
844    /// }
845    /// let subviews = view.try_load_all_entries_mut().await.unwrap();
846    /// assert_eq!(subviews.len(), 1);
847    /// # })
848    /// ```
849    pub async fn try_load_all_entries_mut(
850        &mut self,
851    ) -> Result<Vec<(Vec<u8>, WriteGuardedView<W>)>, ViewError> {
852        let short_keys = self.keys().await?;
853        if !self.delete_storage_first {
854            let mut keys = Vec::new();
855            let mut short_keys_to_load = Vec::new();
856
857            for short_key in &short_keys {
858                if !self.updates.contains_key(short_key) {
859                    let key = self
860                        .context
861                        .base_key()
862                        .base_tag_index(KeyTag::Subview as u8, short_key);
863                    let context = self.context.clone_with_base_key(key);
864                    keys.extend(W::pre_load(&context)?);
865                    short_keys_to_load.push(short_key.to_vec());
866                }
867            }
868
869            let values = self.context.store().read_multi_values_bytes(&keys).await?;
870            for (loaded_values, short_key) in values
871                .chunks_exact_or_repeat(W::NUM_INIT_KEYS)
872                .zip(short_keys_to_load)
873            {
874                let key = self
875                    .context
876                    .base_key()
877                    .base_tag_index(KeyTag::Subview as u8, &short_key);
878                let context = self.context.clone_with_base_key(key);
879                let view = W::post_load(context, loaded_values)?;
880                let wrapped_view = Arc::new(RwLock::new(view));
881                self.updates
882                    .insert(short_key.to_vec(), Update::Set(wrapped_view));
883            }
884        }
885        short_keys
886            .into_iter()
887            .map(|short_key| {
888                let Some(Update::Set(view)) = self.updates.get(&short_key) else {
889                    unreachable!("All entries should have been loaded into `updates`")
890                };
891                let guard = WriteGuardedView(
892                    view.clone()
893                        .try_write_arc()
894                        .ok_or_else(|| ViewError::TryLockError(short_key.clone()))?,
895                );
896                Ok((short_key, guard))
897            })
898            .collect()
899    }
900}
901
902impl<W: View> ReentrantByteCollectionView<W::Context, W> {
903    /// Returns the list of indices in the collection in lexicographic order.
904    /// ```rust
905    /// # tokio_test::block_on(async {
906    /// # use linera_views::context::MemoryContext;
907    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
908    /// # use linera_views::register_view::RegisterView;
909    /// # use linera_views::views::View;
910    /// # let context = MemoryContext::new_for_testing(());
911    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
912    ///     ReentrantByteCollectionView::load(context).await.unwrap();
913    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
914    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
915    /// let keys = view.keys().await.unwrap();
916    /// assert_eq!(keys, vec![vec![0, 1], vec![0, 2]]);
917    /// # })
918    /// ```
919    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
920        let mut keys = Vec::new();
921        self.for_each_key(|key| {
922            keys.push(key.to_vec());
923            Ok(())
924        })
925        .await?;
926        Ok(keys)
927    }
928
929    /// Returns the number of indices of the collection.
930    /// ```rust
931    /// # tokio_test::block_on(async {
932    /// # use linera_views::context::MemoryContext;
933    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
934    /// # use linera_views::register_view::RegisterView;
935    /// # use linera_views::views::View;
936    /// # let context = MemoryContext::new_for_testing(());
937    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
938    ///     ReentrantByteCollectionView::load(context).await.unwrap();
939    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
940    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
941    /// assert_eq!(view.iterative_count().await.unwrap(), 2);
942    /// # })
943    /// ```
944    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
945        let mut count = 0;
946        self.for_each_key(|_key| {
947            count += 1;
948            Ok(())
949        })
950        .await?;
951        Ok(count)
952    }
953
954    /// Applies a function f on each index (aka key). Keys are visited in a
955    /// lexicographic order. If the function returns false then the loop
956    /// ends prematurely.
957    /// ```rust
958    /// # tokio_test::block_on(async {
959    /// # use linera_views::context::MemoryContext;
960    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
961    /// # use linera_views::register_view::RegisterView;
962    /// # use linera_views::views::View;
963    /// # let context = MemoryContext::new_for_testing(());
964    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
965    ///     ReentrantByteCollectionView::load(context).await.unwrap();
966    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
967    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
968    /// let mut count = 0;
969    /// view.for_each_key_while(|_key| {
970    ///     count += 1;
971    ///     Ok(count < 1)
972    /// })
973    /// .await
974    /// .unwrap();
975    /// assert_eq!(count, 1);
976    /// # })
977    /// ```
978    pub async fn for_each_key_while<F>(&self, mut f: F) -> Result<(), ViewError>
979    where
980        F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
981    {
982        let mut updates = self.updates.iter();
983        let mut update = updates.next();
984        if !self.delete_storage_first {
985            let base = self.get_index_key(&[]);
986            for index in self.context.store().find_keys_by_prefix(&base).await? {
987                loop {
988                    match update {
989                        Some((key, value)) if key <= &index => {
990                            if let Update::Set(_) = value {
991                                if !f(key)? {
992                                    return Ok(());
993                                }
994                            }
995                            update = updates.next();
996                            if key == &index {
997                                break;
998                            }
999                        }
1000                        _ => {
1001                            if !f(&index)? {
1002                                return Ok(());
1003                            }
1004                            break;
1005                        }
1006                    }
1007                }
1008            }
1009        }
1010        while let Some((key, value)) = update {
1011            if let Update::Set(_) = value {
1012                if !f(key)? {
1013                    return Ok(());
1014                }
1015            }
1016            update = updates.next();
1017        }
1018        Ok(())
1019    }
1020
1021    /// Applies a function f on each index (aka key). Keys are visited in a
1022    /// lexicographic order.
1023    /// ```rust
1024    /// # tokio_test::block_on(async {
1025    /// # use linera_views::context::MemoryContext;
1026    /// # use linera_views::reentrant_collection_view::ReentrantByteCollectionView;
1027    /// # use linera_views::register_view::RegisterView;
1028    /// # use linera_views::views::View;
1029    /// # let context = MemoryContext::new_for_testing(());
1030    /// let mut view: ReentrantByteCollectionView<_, RegisterView<_, String>> =
1031    ///     ReentrantByteCollectionView::load(context).await.unwrap();
1032    /// view.try_load_entry_mut(&[0, 1]).await.unwrap();
1033    /// view.try_load_entry_mut(&[0, 2]).await.unwrap();
1034    /// let mut count = 0;
1035    /// view.for_each_key(|_key| {
1036    ///     count += 1;
1037    ///     Ok(())
1038    /// })
1039    /// .await
1040    /// .unwrap();
1041    /// assert_eq!(count, 2);
1042    /// # })
1043    /// ```
1044    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
1045    where
1046        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
1047    {
1048        self.for_each_key_while(|key| {
1049            f(key)?;
1050            Ok(true)
1051        })
1052        .await
1053    }
1054}
1055
1056impl<W: HashableView> HashableView for ReentrantByteCollectionView<W::Context, W> {
1057    type Hasher = sha3::Sha3_256;
1058
1059    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1060        #[cfg(with_metrics)]
1061        let _hash_latency = metrics::REENTRANT_COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
1062        let mut hasher = sha3::Sha3_256::default();
1063        let keys = self.keys().await?;
1064        let count = keys.len() as u32;
1065        hasher.update_with_bcs_bytes(&count)?;
1066        for key in keys {
1067            hasher.update_with_bytes(&key)?;
1068            let hash = if let Some(entry) = self.updates.get_mut(&key) {
1069                let Update::Set(view) = entry else {
1070                    unreachable!("Loaded entries in updates should always be Update::Set");
1071                };
1072                let mut view = view
1073                    .try_write_arc()
1074                    .ok_or_else(|| ViewError::TryLockError(key))?;
1075                view.hash_mut().await?
1076            } else {
1077                let key = self
1078                    .context
1079                    .base_key()
1080                    .base_tag_index(KeyTag::Subview as u8, &key);
1081                let context = self.context.clone_with_base_key(key);
1082                let mut view = W::load(context).await?;
1083                view.hash_mut().await?
1084            };
1085            hasher.write_all(hash.as_ref())?;
1086        }
1087        Ok(hasher.finalize())
1088    }
1089
1090    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1091        #[cfg(with_metrics)]
1092        let _hash_latency = metrics::REENTRANT_COLLECTION_VIEW_HASH_RUNTIME.measure_latency();
1093        let mut hasher = sha3::Sha3_256::default();
1094        let keys = self.keys().await?;
1095        let count = keys.len() as u32;
1096        hasher.update_with_bcs_bytes(&count)?;
1097        for key in keys {
1098            hasher.update_with_bytes(&key)?;
1099            let hash = if let Some(entry) = self.updates.get(&key) {
1100                let Update::Set(view) = entry else {
1101                    unreachable!("Loaded entries in updates should always be Update::Set");
1102                };
1103                let view = view
1104                    .try_read_arc()
1105                    .ok_or_else(|| ViewError::TryLockError(key))?;
1106                view.hash().await?
1107            } else {
1108                let key = self
1109                    .context
1110                    .base_key()
1111                    .base_tag_index(KeyTag::Subview as u8, &key);
1112                let context = self.context.clone_with_base_key(key);
1113                let view = W::load(context).await?;
1114                view.hash().await?
1115            };
1116            hasher.write_all(hash.as_ref())?;
1117        }
1118        Ok(hasher.finalize())
1119    }
1120}
1121
1122/// A view that supports accessing a collection of views of the same kind, indexed by keys,
1123/// possibly several subviews at a time.
1124#[derive(Debug, Allocative)]
1125#[allocative(bound = "C, I, W: Allocative")]
1126pub struct ReentrantCollectionView<C, I, W> {
1127    collection: ReentrantByteCollectionView<C, W>,
1128    #[allocative(skip)]
1129    _phantom: PhantomData<I>,
1130}
1131
1132impl<I, W, C2> ReplaceContext<C2> for ReentrantCollectionView<W::Context, I, W>
1133where
1134    W: View + ReplaceContext<C2>,
1135    I: Send + Sync + Serialize + DeserializeOwned,
1136    C2: Context,
1137{
1138    type Target = ReentrantCollectionView<C2, I, <W as ReplaceContext<C2>>::Target>;
1139
1140    async fn with_context(
1141        &mut self,
1142        ctx: impl FnOnce(&Self::Context) -> C2 + Clone,
1143    ) -> Self::Target {
1144        ReentrantCollectionView {
1145            collection: self.collection.with_context(ctx).await,
1146            _phantom: self._phantom,
1147        }
1148    }
1149}
1150
1151impl<I, W> View for ReentrantCollectionView<W::Context, I, W>
1152where
1153    W: View,
1154    I: Send + Sync + Serialize + DeserializeOwned,
1155{
1156    const NUM_INIT_KEYS: usize = ReentrantByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1157
1158    type Context = W::Context;
1159
1160    fn context(&self) -> Self::Context {
1161        self.collection.context()
1162    }
1163
1164    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1165        ReentrantByteCollectionView::<W::Context, W>::pre_load(context)
1166    }
1167
1168    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1169        let collection = ReentrantByteCollectionView::post_load(context, values)?;
1170        Ok(ReentrantCollectionView {
1171            collection,
1172            _phantom: PhantomData,
1173        })
1174    }
1175
1176    fn rollback(&mut self) {
1177        self.collection.rollback()
1178    }
1179
1180    async fn has_pending_changes(&self) -> bool {
1181        self.collection.has_pending_changes().await
1182    }
1183
1184    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
1185        self.collection.pre_save(batch)
1186    }
1187
1188    fn post_save(&mut self) {
1189        self.collection.post_save()
1190    }
1191
1192    fn clear(&mut self) {
1193        self.collection.clear()
1194    }
1195}
1196
1197impl<I, W> ClonableView for ReentrantCollectionView<W::Context, I, W>
1198where
1199    W: ClonableView,
1200    I: Send + Sync + Serialize + DeserializeOwned,
1201{
1202    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1203        Ok(ReentrantCollectionView {
1204            collection: self.collection.clone_unchecked()?,
1205            _phantom: PhantomData,
1206        })
1207    }
1208}
1209
1210impl<I, W> ReentrantCollectionView<W::Context, I, W>
1211where
1212    W: View,
1213    I: Sync + Send + Serialize + DeserializeOwned,
1214{
1215    /// Loads a subview for the data at the given index in the collection. If an entry
1216    /// is absent then a default entry is put on the collection. The obtained view can
1217    /// then be modified.
1218    /// ```rust
1219    /// # tokio_test::block_on(async {
1220    /// # use linera_views::context::MemoryContext;
1221    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1222    /// # use linera_views::register_view::RegisterView;
1223    /// # use linera_views::views::View;
1224    /// # let context = MemoryContext::new_for_testing(());
1225    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1226    ///     ReentrantCollectionView::load(context).await.unwrap();
1227    /// let subview = view.try_load_entry_mut(&23).await.unwrap();
1228    /// let value = subview.get();
1229    /// assert_eq!(*value, String::default());
1230    /// # })
1231    /// ```
1232    pub async fn try_load_entry_mut<Q>(
1233        &mut self,
1234        index: &Q,
1235    ) -> Result<WriteGuardedView<W>, ViewError>
1236    where
1237        I: Borrow<Q>,
1238        Q: Serialize + ?Sized,
1239    {
1240        let short_key = BaseKey::derive_short_key(index)?;
1241        self.collection.try_load_entry_mut(&short_key).await
1242    }
1243
1244    /// Loads a subview at the given index in the collection and gives read-only access to the data.
1245    /// If an entry is absent then `None` is returned.
1246    /// ```rust
1247    /// # tokio_test::block_on(async {
1248    /// # use linera_views::context::MemoryContext;
1249    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1250    /// # use linera_views::register_view::RegisterView;
1251    /// # use linera_views::views::View;
1252    /// # let context = MemoryContext::new_for_testing(());
1253    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1254    ///     ReentrantCollectionView::load(context).await.unwrap();
1255    /// {
1256    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1257    /// }
1258    /// let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1259    /// let value = subview.get();
1260    /// assert_eq!(*value, String::default());
1261    /// # })
1262    /// ```
1263    pub async fn try_load_entry<Q>(
1264        &self,
1265        index: &Q,
1266    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1267    where
1268        I: Borrow<Q>,
1269        Q: Serialize + ?Sized,
1270    {
1271        let short_key = BaseKey::derive_short_key(index)?;
1272        self.collection.try_load_entry(&short_key).await
1273    }
1274
1275    /// Returns `true` if the collection contains a value for the specified key.
1276    /// ```rust
1277    /// # tokio_test::block_on(async {
1278    /// # use linera_views::context::MemoryContext;
1279    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1280    /// # use linera_views::register_view::RegisterView;
1281    /// # use linera_views::views::View;
1282    /// # let context = MemoryContext::new_for_testing(());
1283    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1284    ///     ReentrantCollectionView::load(context).await.unwrap();
1285    /// let _subview = view.try_load_entry_mut(&23).await.unwrap();
1286    /// assert!(view.contains_key(&23).await.unwrap());
1287    /// assert!(!view.contains_key(&24).await.unwrap());
1288    /// # })
1289    /// ```
1290    pub async fn contains_key<Q>(&self, index: &Q) -> Result<bool, ViewError>
1291    where
1292        I: Borrow<Q>,
1293        Q: Serialize + ?Sized,
1294    {
1295        let short_key = BaseKey::derive_short_key(index)?;
1296        self.collection.contains_key(&short_key).await
1297    }
1298
1299    /// Marks the entry so that it is removed in the next flush.
1300    /// ```rust
1301    /// # tokio_test::block_on(async {
1302    /// # use linera_views::context::MemoryContext;
1303    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1304    /// # use linera_views::register_view::RegisterView;
1305    /// # use linera_views::views::View;
1306    /// # let context = MemoryContext::new_for_testing(());
1307    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1308    ///     ReentrantCollectionView::load(context).await.unwrap();
1309    /// let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1310    /// let value = subview.get_mut();
1311    /// assert_eq!(*value, String::default());
1312    /// view.remove_entry(&23);
1313    /// let keys = view.indices().await.unwrap();
1314    /// assert_eq!(keys.len(), 0);
1315    /// # })
1316    /// ```
1317    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1318    where
1319        I: Borrow<Q>,
1320        Q: Serialize + ?Sized,
1321    {
1322        let short_key = BaseKey::derive_short_key(index)?;
1323        self.collection.remove_entry(short_key);
1324        Ok(())
1325    }
1326
1327    /// Marks the entry so that it is removed in the next flush.
1328    /// ```rust
1329    /// # tokio_test::block_on(async {
1330    /// # use linera_views::context::MemoryContext;
1331    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1332    /// # use linera_views::register_view::RegisterView;
1333    /// # use linera_views::views::View;
1334    /// # let context = MemoryContext::new_for_testing(());
1335    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1336    ///     ReentrantCollectionView::load(context).await.unwrap();
1337    /// {
1338    ///     let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1339    ///     let value = subview.get_mut();
1340    ///     *value = String::from("Hello");
1341    /// }
1342    /// view.try_reset_entry_to_default(&23).unwrap();
1343    /// let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1344    /// let value = subview.get_mut();
1345    /// assert_eq!(*value, String::default());
1346    /// # })
1347    /// ```
1348    pub fn try_reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1349    where
1350        I: Borrow<Q>,
1351        Q: Serialize + ?Sized,
1352    {
1353        let short_key = BaseKey::derive_short_key(index)?;
1354        self.collection.try_reset_entry_to_default(&short_key)
1355    }
1356
1357    /// Gets the extra data.
1358    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1359        self.collection.extra()
1360    }
1361}
1362
1363impl<I, W> ReentrantCollectionView<W::Context, I, W>
1364where
1365    W: View,
1366    I: Sync + Send + Serialize + DeserializeOwned,
1367{
1368    /// Load multiple entries for writing at once.
1369    /// The entries in indices have to be all distinct.
1370    /// ```rust
1371    /// # tokio_test::block_on(async {
1372    /// # use linera_views::context::MemoryContext;
1373    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1374    /// # use linera_views::register_view::RegisterView;
1375    /// # use linera_views::views::View;
1376    /// # let context = MemoryContext::new_for_testing(());
1377    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1378    ///     ReentrantCollectionView::load(context).await.unwrap();
1379    /// let indices = vec![23, 42];
1380    /// let subviews = view.try_load_entries_mut(&indices).await.unwrap();
1381    /// let value1 = subviews[0].get();
1382    /// let value2 = subviews[1].get();
1383    /// assert_eq!(*value1, String::default());
1384    /// assert_eq!(*value2, String::default());
1385    /// # })
1386    /// ```
1387    pub async fn try_load_entries_mut<'a, Q>(
1388        &'a mut self,
1389        indices: impl IntoIterator<Item = &'a Q>,
1390    ) -> Result<Vec<WriteGuardedView<W>>, ViewError>
1391    where
1392        I: Borrow<Q>,
1393        Q: Serialize + 'a,
1394    {
1395        let short_keys = indices
1396            .into_iter()
1397            .map(|index| BaseKey::derive_short_key(index))
1398            .collect::<Result<_, _>>()?;
1399        self.collection.try_load_entries_mut(short_keys).await
1400    }
1401
1402    /// Loads multiple entries for writing at once with their keys.
1403    /// The entries in indices have to be all distinct.
1404    /// ```rust
1405    /// # tokio_test::block_on(async {
1406    /// # use linera_views::context::MemoryContext;
1407    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1408    /// # use linera_views::register_view::RegisterView;
1409    /// # use linera_views::views::View;
1410    /// # let context = MemoryContext::new_for_testing(());
1411    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1412    ///     ReentrantCollectionView::load(context).await.unwrap();
1413    /// let indices = [23, 42];
1414    /// let subviews = view.try_load_entries_pairs_mut(indices).await.unwrap();
1415    /// let value1 = subviews[0].1.get();
1416    /// let value2 = subviews[1].1.get();
1417    /// assert_eq!(*value1, String::default());
1418    /// assert_eq!(*value2, String::default());
1419    /// # })
1420    /// ```
1421    pub async fn try_load_entries_pairs_mut<Q>(
1422        &mut self,
1423        indices: impl IntoIterator<Item = Q>,
1424    ) -> Result<Vec<(Q, WriteGuardedView<W>)>, ViewError>
1425    where
1426        I: Borrow<Q>,
1427        Q: Serialize + Clone,
1428    {
1429        let indices_vec: Vec<Q> = indices.into_iter().collect();
1430        let values = self.try_load_entries_mut(indices_vec.iter()).await?;
1431        Ok(indices_vec.into_iter().zip(values).collect())
1432    }
1433
1434    /// Load multiple entries for reading at once.
1435    /// The entries in indices have to be all distinct.
1436    /// ```rust
1437    /// # tokio_test::block_on(async {
1438    /// # use linera_views::context::MemoryContext;
1439    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1440    /// # use linera_views::register_view::RegisterView;
1441    /// # use linera_views::views::View;
1442    /// # let context = MemoryContext::new_for_testing(());
1443    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1444    ///     ReentrantCollectionView::load(context).await.unwrap();
1445    /// {
1446    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1447    /// }
1448    /// let indices = vec![23, 42];
1449    /// let subviews = view.try_load_entries(&indices).await.unwrap();
1450    /// assert!(subviews[1].is_none());
1451    /// let value0 = subviews[0].as_ref().unwrap().get();
1452    /// assert_eq!(*value0, String::default());
1453    /// # })
1454    /// ```
1455    pub async fn try_load_entries<'a, Q>(
1456        &'a self,
1457        indices: impl IntoIterator<Item = &'a Q>,
1458    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError>
1459    where
1460        I: Borrow<Q>,
1461        Q: Serialize + 'a,
1462    {
1463        let short_keys = indices
1464            .into_iter()
1465            .map(|index| BaseKey::derive_short_key(index))
1466            .collect::<Result<_, _>>()?;
1467        self.collection.try_load_entries(short_keys).await
1468    }
1469
1470    /// Loads multiple entries for reading at once with their keys.
1471    /// The entries in indices have to be all distinct.
1472    /// ```rust
1473    /// # tokio_test::block_on(async {
1474    /// # use linera_views::context::MemoryContext;
1475    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1476    /// # use linera_views::register_view::RegisterView;
1477    /// # use linera_views::views::View;
1478    /// # let context = MemoryContext::new_for_testing(());
1479    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1480    ///     ReentrantCollectionView::load(context).await.unwrap();
1481    /// {
1482    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1483    /// }
1484    /// let indices = [23, 42];
1485    /// let subviews = view.try_load_entries_pairs(indices).await.unwrap();
1486    /// assert!(subviews[1].1.is_none());
1487    /// let value0 = subviews[0].1.as_ref().unwrap().get();
1488    /// assert_eq!(*value0, String::default());
1489    /// # })
1490    /// ```
1491    pub async fn try_load_entries_pairs<Q>(
1492        &self,
1493        indices: impl IntoIterator<Item = Q>,
1494    ) -> Result<Vec<(Q, Option<ReadGuardedView<W>>)>, ViewError>
1495    where
1496        I: Borrow<Q>,
1497        Q: Serialize + Clone,
1498    {
1499        let indices_vec: Vec<Q> = indices.into_iter().collect();
1500        let values = self.try_load_entries(indices_vec.iter()).await?;
1501        Ok(indices_vec.into_iter().zip(values).collect())
1502    }
1503
1504    /// Loads all entries for writing at once.
1505    /// The entries in indices have to be all distinct.
1506    /// ```rust
1507    /// # tokio_test::block_on(async {
1508    /// # use linera_views::context::MemoryContext;
1509    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1510    /// # use linera_views::register_view::RegisterView;
1511    /// # use linera_views::views::View;
1512    /// # let context = MemoryContext::new_for_testing(());
1513    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1514    ///     ReentrantCollectionView::load(context).await.unwrap();
1515    /// {
1516    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1517    /// }
1518    /// let subviews = view.try_load_all_entries_mut().await.unwrap();
1519    /// assert_eq!(subviews.len(), 1);
1520    /// # })
1521    /// ```
1522    pub async fn try_load_all_entries_mut(
1523        &mut self,
1524    ) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError> {
1525        let results = self.collection.try_load_all_entries_mut().await?;
1526        results
1527            .into_iter()
1528            .map(|(short_key, view)| {
1529                let index = BaseKey::deserialize_value(&short_key)?;
1530                Ok((index, view))
1531            })
1532            .collect()
1533    }
1534
1535    /// Load multiple entries for reading at once.
1536    /// The entries in indices have to be all distinct.
1537    /// ```rust
1538    /// # tokio_test::block_on(async {
1539    /// # use linera_views::context::MemoryContext;
1540    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1541    /// # use linera_views::register_view::RegisterView;
1542    /// # use linera_views::views::View;
1543    /// # let context = MemoryContext::new_for_testing(());
1544    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1545    ///     ReentrantCollectionView::load(context).await.unwrap();
1546    /// {
1547    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1548    /// }
1549    /// let subviews = view.try_load_all_entries().await.unwrap();
1550    /// assert_eq!(subviews.len(), 1);
1551    /// # })
1552    /// ```
1553    pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError> {
1554        let results = self.collection.try_load_all_entries().await?;
1555        results
1556            .into_iter()
1557            .map(|(short_key, view)| {
1558                let index = BaseKey::deserialize_value(&short_key)?;
1559                Ok((index, view))
1560            })
1561            .collect()
1562    }
1563}
1564
1565impl<I, W> ReentrantCollectionView<W::Context, I, W>
1566where
1567    W: View,
1568    I: Sync + Send + Serialize + DeserializeOwned,
1569{
1570    /// Returns the list of indices in the collection in an order determined
1571    /// by serialization.
1572    /// ```rust
1573    /// # tokio_test::block_on(async {
1574    /// # use linera_views::context::MemoryContext;
1575    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1576    /// # use linera_views::register_view::RegisterView;
1577    /// # use linera_views::views::View;
1578    /// # let context = MemoryContext::new_for_testing(());
1579    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1580    ///     ReentrantCollectionView::load(context).await.unwrap();
1581    /// view.try_load_entry_mut(&23).await.unwrap();
1582    /// view.try_load_entry_mut(&25).await.unwrap();
1583    /// let indices = view.indices().await.unwrap();
1584    /// assert_eq!(indices.len(), 2);
1585    /// # })
1586    /// ```
1587    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
1588        let mut indices = Vec::new();
1589        self.for_each_index(|index| {
1590            indices.push(index);
1591            Ok(())
1592        })
1593        .await?;
1594        Ok(indices)
1595    }
1596
1597    /// Returns the number of indices in the collection.
1598    /// ```rust
1599    /// # tokio_test::block_on(async {
1600    /// # use linera_views::context::MemoryContext;
1601    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1602    /// # use linera_views::register_view::RegisterView;
1603    /// # use linera_views::views::View;
1604    /// # let context = MemoryContext::new_for_testing(());
1605    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1606    ///     ReentrantCollectionView::load(context).await.unwrap();
1607    /// view.try_load_entry_mut(&23).await.unwrap();
1608    /// view.try_load_entry_mut(&25).await.unwrap();
1609    /// assert_eq!(view.iterative_count().await.unwrap(), 2);
1610    /// # })
1611    /// ```
1612    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
1613        self.collection.iterative_count().await
1614    }
1615
1616    /// Applies a function f on each index. Indices are visited in an order
1617    /// determined by the serialization. If the function f returns false then
1618    /// the loop ends prematurely.
1619    /// ```rust
1620    /// # tokio_test::block_on(async {
1621    /// # use linera_views::context::MemoryContext;
1622    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1623    /// # use linera_views::register_view::RegisterView;
1624    /// # use linera_views::views::View;
1625    /// # let context = MemoryContext::new_for_testing(());
1626    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1627    ///     ReentrantCollectionView::load(context).await.unwrap();
1628    /// view.try_load_entry_mut(&23).await.unwrap();
1629    /// view.try_load_entry_mut(&24).await.unwrap();
1630    /// let mut count = 0;
1631    /// view.for_each_index_while(|_key| {
1632    ///     count += 1;
1633    ///     Ok(count < 1)
1634    /// })
1635    /// .await
1636    /// .unwrap();
1637    /// assert_eq!(count, 1);
1638    /// # })
1639    /// ```
1640    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1641    where
1642        F: FnMut(I) -> Result<bool, ViewError> + Send,
1643    {
1644        self.collection
1645            .for_each_key_while(|key| {
1646                let index = BaseKey::deserialize_value(key)?;
1647                f(index)
1648            })
1649            .await?;
1650        Ok(())
1651    }
1652
1653    /// Applies a function f on each index. Indices are visited in an order
1654    /// determined by the serialization.
1655    /// ```rust
1656    /// # tokio_test::block_on(async {
1657    /// # use linera_views::context::MemoryContext;
1658    /// # use linera_views::reentrant_collection_view::ReentrantCollectionView;
1659    /// # use linera_views::register_view::RegisterView;
1660    /// # use linera_views::views::View;
1661    /// # let context = MemoryContext::new_for_testing(());
1662    /// let mut view: ReentrantCollectionView<_, u64, RegisterView<_, String>> =
1663    ///     ReentrantCollectionView::load(context).await.unwrap();
1664    /// view.try_load_entry_mut(&23).await.unwrap();
1665    /// view.try_load_entry_mut(&28).await.unwrap();
1666    /// let mut count = 0;
1667    /// view.for_each_index(|_key| {
1668    ///     count += 1;
1669    ///     Ok(())
1670    /// })
1671    /// .await
1672    /// .unwrap();
1673    /// assert_eq!(count, 2);
1674    /// # })
1675    /// ```
1676    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
1677    where
1678        F: FnMut(I) -> Result<(), ViewError> + Send,
1679    {
1680        self.collection
1681            .for_each_key(|key| {
1682                let index = BaseKey::deserialize_value(key)?;
1683                f(index)
1684            })
1685            .await?;
1686        Ok(())
1687    }
1688}
1689
1690impl<I, W> HashableView for ReentrantCollectionView<W::Context, I, W>
1691where
1692    W: HashableView,
1693    I: Send + Sync + Serialize + DeserializeOwned,
1694{
1695    type Hasher = sha3::Sha3_256;
1696
1697    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1698        self.collection.hash_mut().await
1699    }
1700
1701    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
1702        self.collection.hash().await
1703    }
1704}
1705
1706/// A view that supports accessing a collection of views of the same kind, indexed by an ordered key,
1707/// possibly several subviews at a time.
1708#[derive(Debug, Allocative)]
1709#[allocative(bound = "C, I, W: Allocative")]
1710pub struct ReentrantCustomCollectionView<C, I, W> {
1711    collection: ReentrantByteCollectionView<C, W>,
1712    #[allocative(skip)]
1713    _phantom: PhantomData<I>,
1714}
1715
1716impl<I, W> View for ReentrantCustomCollectionView<W::Context, I, W>
1717where
1718    W: View,
1719    I: Send + Sync + CustomSerialize,
1720{
1721    const NUM_INIT_KEYS: usize = ReentrantByteCollectionView::<W::Context, W>::NUM_INIT_KEYS;
1722
1723    type Context = W::Context;
1724
1725    fn context(&self) -> Self::Context {
1726        self.collection.context()
1727    }
1728
1729    fn pre_load(context: &Self::Context) -> Result<Vec<Vec<u8>>, ViewError> {
1730        ReentrantByteCollectionView::<_, W>::pre_load(context)
1731    }
1732
1733    fn post_load(context: Self::Context, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
1734        let collection = ReentrantByteCollectionView::post_load(context, values)?;
1735        Ok(ReentrantCustomCollectionView {
1736            collection,
1737            _phantom: PhantomData,
1738        })
1739    }
1740
1741    fn rollback(&mut self) {
1742        self.collection.rollback()
1743    }
1744
1745    async fn has_pending_changes(&self) -> bool {
1746        self.collection.has_pending_changes().await
1747    }
1748
1749    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
1750        self.collection.pre_save(batch)
1751    }
1752
1753    fn post_save(&mut self) {
1754        self.collection.post_save()
1755    }
1756
1757    fn clear(&mut self) {
1758        self.collection.clear()
1759    }
1760}
1761
1762impl<I, W> ClonableView for ReentrantCustomCollectionView<W::Context, I, W>
1763where
1764    W: ClonableView,
1765    Self: View,
1766{
1767    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
1768        Ok(ReentrantCustomCollectionView {
1769            collection: self.collection.clone_unchecked()?,
1770            _phantom: PhantomData,
1771        })
1772    }
1773}
1774
1775impl<I, W> ReentrantCustomCollectionView<W::Context, I, W>
1776where
1777    W: View,
1778    I: Sync + Send + CustomSerialize,
1779{
1780    /// Loads a subview for the data at the given index in the collection. If an entry
1781    /// is absent then a default entry is put in the collection on this index.
1782    /// ```rust
1783    /// # tokio_test::block_on(async {
1784    /// # use linera_views::context::MemoryContext;
1785    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1786    /// # use linera_views::register_view::RegisterView;
1787    /// # use linera_views::views::View;
1788    /// # let context = MemoryContext::new_for_testing(());
1789    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1790    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1791    /// let subview = view.try_load_entry_mut(&23).await.unwrap();
1792    /// let value = subview.get();
1793    /// assert_eq!(*value, String::default());
1794    /// # })
1795    /// ```
1796    pub async fn try_load_entry_mut<Q>(
1797        &mut self,
1798        index: &Q,
1799    ) -> Result<WriteGuardedView<W>, ViewError>
1800    where
1801        I: Borrow<Q>,
1802        Q: CustomSerialize,
1803    {
1804        let short_key = index.to_custom_bytes()?;
1805        self.collection.try_load_entry_mut(&short_key).await
1806    }
1807
1808    /// Loads a subview at the given index in the collection and gives read-only access to the data.
1809    /// If an entry is absent then `None` is returned.
1810    /// ```rust
1811    /// # tokio_test::block_on(async {
1812    /// # use linera_views::context::MemoryContext;
1813    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1814    /// # use linera_views::register_view::RegisterView;
1815    /// # use linera_views::views::View;
1816    /// # let context = MemoryContext::new_for_testing(());
1817    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1818    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1819    /// {
1820    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
1821    /// }
1822    /// let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1823    /// let value = subview.get();
1824    /// assert_eq!(*value, String::default());
1825    /// # })
1826    /// ```
1827    pub async fn try_load_entry<Q>(
1828        &self,
1829        index: &Q,
1830    ) -> Result<Option<ReadGuardedView<W>>, ViewError>
1831    where
1832        I: Borrow<Q>,
1833        Q: CustomSerialize,
1834    {
1835        let short_key = index.to_custom_bytes()?;
1836        self.collection.try_load_entry(&short_key).await
1837    }
1838
1839    /// Returns `true` if the collection contains a value for the specified key.
1840    /// ```rust
1841    /// # tokio_test::block_on(async {
1842    /// # use linera_views::context::MemoryContext;
1843    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1844    /// # use linera_views::register_view::RegisterView;
1845    /// # use linera_views::views::View;
1846    /// # let context = MemoryContext::new_for_testing(());
1847    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1848    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1849    /// let _subview = view.try_load_entry_mut(&23).await.unwrap();
1850    /// assert!(view.contains_key(&23).await.unwrap());
1851    /// assert!(!view.contains_key(&24).await.unwrap());
1852    /// # })
1853    /// ```
1854    pub async fn contains_key<Q>(&self, index: &Q) -> Result<bool, ViewError>
1855    where
1856        I: Borrow<Q>,
1857        Q: CustomSerialize,
1858    {
1859        let short_key = index.to_custom_bytes()?;
1860        self.collection.contains_key(&short_key).await
1861    }
1862
1863    /// Removes an entry. If absent then nothing happens.
1864    /// ```rust
1865    /// # tokio_test::block_on(async {
1866    /// # use linera_views::context::MemoryContext;
1867    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1868    /// # use linera_views::register_view::RegisterView;
1869    /// # use linera_views::views::View;
1870    /// # let context = MemoryContext::new_for_testing(());
1871    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1872    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1873    /// let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1874    /// let value = subview.get_mut();
1875    /// assert_eq!(*value, String::default());
1876    /// view.remove_entry(&23);
1877    /// let keys = view.indices().await.unwrap();
1878    /// assert_eq!(keys.len(), 0);
1879    /// # })
1880    /// ```
1881    pub fn remove_entry<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1882    where
1883        I: Borrow<Q>,
1884        Q: CustomSerialize,
1885    {
1886        let short_key = index.to_custom_bytes()?;
1887        self.collection.remove_entry(short_key);
1888        Ok(())
1889    }
1890
1891    /// Marks the entry so that it is removed in the next flush.
1892    /// ```rust
1893    /// # tokio_test::block_on(async {
1894    /// # use linera_views::context::MemoryContext;
1895    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1896    /// # use linera_views::register_view::RegisterView;
1897    /// # use linera_views::views::View;
1898    /// # let context = MemoryContext::new_for_testing(());
1899    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1900    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1901    /// {
1902    ///     let mut subview = view.try_load_entry_mut(&23).await.unwrap();
1903    ///     let value = subview.get_mut();
1904    ///     *value = String::from("Hello");
1905    /// }
1906    /// {
1907    ///     view.try_reset_entry_to_default(&23).unwrap();
1908    ///     let subview = view.try_load_entry(&23).await.unwrap().unwrap();
1909    ///     let value = subview.get();
1910    ///     assert_eq!(*value, String::default());
1911    /// }
1912    /// # })
1913    /// ```
1914    pub fn try_reset_entry_to_default<Q>(&mut self, index: &Q) -> Result<(), ViewError>
1915    where
1916        I: Borrow<Q>,
1917        Q: CustomSerialize,
1918    {
1919        let short_key = index.to_custom_bytes()?;
1920        self.collection.try_reset_entry_to_default(&short_key)
1921    }
1922
1923    /// Gets the extra data.
1924    pub fn extra(&self) -> &<W::Context as Context>::Extra {
1925        self.collection.extra()
1926    }
1927}
1928
1929impl<I, W: View> ReentrantCustomCollectionView<W::Context, I, W>
1930where
1931    I: Sync + Send + CustomSerialize,
1932{
1933    /// Load multiple entries for writing at once.
1934    /// The entries in indices have to be all distinct.
1935    /// ```rust
1936    /// # tokio_test::block_on(async {
1937    /// # use linera_views::context::MemoryContext;
1938    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1939    /// # use linera_views::register_view::RegisterView;
1940    /// # use linera_views::views::View;
1941    /// # let context = MemoryContext::new_for_testing(());
1942    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1943    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1944    /// let subviews = view.try_load_entries_mut(&[23, 42]).await.unwrap();
1945    /// let value1 = subviews[0].get();
1946    /// let value2 = subviews[1].get();
1947    /// assert_eq!(*value1, String::default());
1948    /// assert_eq!(*value2, String::default());
1949    /// # })
1950    /// ```
1951    pub async fn try_load_entries_mut<'a, Q>(
1952        &mut self,
1953        indices: impl IntoIterator<Item = &'a Q>,
1954    ) -> Result<Vec<WriteGuardedView<W>>, ViewError>
1955    where
1956        I: Borrow<Q>,
1957        Q: CustomSerialize + 'a,
1958    {
1959        let short_keys = indices
1960            .into_iter()
1961            .map(|index| index.to_custom_bytes())
1962            .collect::<Result<_, _>>()?;
1963        self.collection.try_load_entries_mut(short_keys).await
1964    }
1965
1966    /// Loads multiple entries for writing at once with their keys.
1967    /// The entries in indices have to be all distinct.
1968    /// ```rust
1969    /// # tokio_test::block_on(async {
1970    /// # use linera_views::context::MemoryContext;
1971    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
1972    /// # use linera_views::register_view::RegisterView;
1973    /// # use linera_views::views::View;
1974    /// # let context = MemoryContext::new_for_testing(());
1975    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
1976    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
1977    /// let indices = [23, 42];
1978    /// let subviews = view.try_load_entries_pairs_mut(indices).await.unwrap();
1979    /// let value1 = subviews[0].1.get();
1980    /// let value2 = subviews[1].1.get();
1981    /// assert_eq!(*value1, String::default());
1982    /// assert_eq!(*value2, String::default());
1983    /// # })
1984    /// ```
1985    pub async fn try_load_entries_pairs_mut<Q>(
1986        &mut self,
1987        indices: impl IntoIterator<Item = Q>,
1988    ) -> Result<Vec<(Q, WriteGuardedView<W>)>, ViewError>
1989    where
1990        I: Borrow<Q>,
1991        Q: CustomSerialize + Clone,
1992    {
1993        let indices_vec: Vec<Q> = indices.into_iter().collect();
1994        let values = self.try_load_entries_mut(indices_vec.iter()).await?;
1995        Ok(indices_vec.into_iter().zip(values).collect())
1996    }
1997
1998    /// Load multiple entries for reading at once.
1999    /// The entries in indices have to be all distinct.
2000    /// ```rust
2001    /// # tokio_test::block_on(async {
2002    /// # use linera_views::context::MemoryContext;
2003    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2004    /// # use linera_views::register_view::RegisterView;
2005    /// # use linera_views::views::View;
2006    /// # let context = MemoryContext::new_for_testing(());
2007    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2008    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2009    /// {
2010    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2011    /// }
2012    /// let subviews = view.try_load_entries(&[23, 42]).await.unwrap();
2013    /// assert!(subviews[1].is_none());
2014    /// let value0 = subviews[0].as_ref().unwrap().get();
2015    /// assert_eq!(*value0, String::default());
2016    /// # })
2017    /// ```
2018    pub async fn try_load_entries<'a, Q>(
2019        &self,
2020        indices: impl IntoIterator<Item = &'a Q>,
2021    ) -> Result<Vec<Option<ReadGuardedView<W>>>, ViewError>
2022    where
2023        I: Borrow<Q>,
2024        Q: CustomSerialize + 'a,
2025    {
2026        let short_keys = indices
2027            .into_iter()
2028            .map(|index| index.to_custom_bytes())
2029            .collect::<Result<_, _>>()?;
2030        self.collection.try_load_entries(short_keys).await
2031    }
2032
2033    /// Loads multiple entries for reading at once with their keys.
2034    /// The entries in indices have to be all distinct.
2035    /// ```rust
2036    /// # tokio_test::block_on(async {
2037    /// # use linera_views::context::MemoryContext;
2038    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2039    /// # use linera_views::register_view::RegisterView;
2040    /// # use linera_views::views::View;
2041    /// # let context = MemoryContext::new_for_testing(());
2042    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2043    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2044    /// {
2045    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2046    /// }
2047    /// let indices = [23, 42];
2048    /// let subviews = view.try_load_entries_pairs(indices).await.unwrap();
2049    /// assert!(subviews[1].1.is_none());
2050    /// let value0 = subviews[0].1.as_ref().unwrap().get();
2051    /// assert_eq!(*value0, String::default());
2052    /// # })
2053    /// ```
2054    pub async fn try_load_entries_pairs<Q>(
2055        &self,
2056        indices: impl IntoIterator<Item = Q>,
2057    ) -> Result<Vec<(Q, Option<ReadGuardedView<W>>)>, ViewError>
2058    where
2059        I: Borrow<Q>,
2060        Q: CustomSerialize + Clone,
2061    {
2062        let indices_vec: Vec<Q> = indices.into_iter().collect();
2063        let values = self.try_load_entries(indices_vec.iter()).await?;
2064        Ok(indices_vec.into_iter().zip(values).collect())
2065    }
2066
2067    /// Loads all entries for writing at once.
2068    /// The entries in indices have to be all distinct.
2069    /// ```rust
2070    /// # tokio_test::block_on(async {
2071    /// # use linera_views::context::MemoryContext;
2072    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2073    /// # use linera_views::register_view::RegisterView;
2074    /// # use linera_views::views::View;
2075    /// # let context = MemoryContext::new_for_testing(());
2076    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2077    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2078    /// {
2079    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2080    /// }
2081    /// let subviews = view.try_load_all_entries_mut().await.unwrap();
2082    /// assert_eq!(subviews.len(), 1);
2083    /// # })
2084    /// ```
2085    pub async fn try_load_all_entries_mut(
2086        &mut self,
2087    ) -> Result<Vec<(I, WriteGuardedView<W>)>, ViewError> {
2088        let results = self.collection.try_load_all_entries_mut().await?;
2089        results
2090            .into_iter()
2091            .map(|(short_key, view)| {
2092                let index = I::from_custom_bytes(&short_key)?;
2093                Ok((index, view))
2094            })
2095            .collect()
2096    }
2097
2098    /// Load multiple entries for reading at once.
2099    /// The entries in indices have to be all distinct.
2100    /// ```rust
2101    /// # tokio_test::block_on(async {
2102    /// # use linera_views::context::MemoryContext;
2103    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2104    /// # use linera_views::register_view::RegisterView;
2105    /// # use linera_views::views::View;
2106    /// # let context = MemoryContext::new_for_testing(());
2107    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2108    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2109    /// {
2110    ///     let _subview = view.try_load_entry_mut(&23).await.unwrap();
2111    /// }
2112    /// let subviews = view.try_load_all_entries().await.unwrap();
2113    /// assert_eq!(subviews.len(), 1);
2114    /// # })
2115    /// ```
2116    pub async fn try_load_all_entries(&self) -> Result<Vec<(I, ReadGuardedView<W>)>, ViewError> {
2117        let results = self.collection.try_load_all_entries().await?;
2118        results
2119            .into_iter()
2120            .map(|(short_key, view)| {
2121                let index = I::from_custom_bytes(&short_key)?;
2122                Ok((index, view))
2123            })
2124            .collect()
2125    }
2126}
2127
2128impl<I, W> ReentrantCustomCollectionView<W::Context, I, W>
2129where
2130    W: View,
2131    I: Sync + Send + CustomSerialize,
2132{
2133    /// Returns the list of indices in the collection. The order is determined by
2134    /// the custom serialization.
2135    /// ```rust
2136    /// # tokio_test::block_on(async {
2137    /// # use linera_views::context::MemoryContext;
2138    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2139    /// # use linera_views::register_view::RegisterView;
2140    /// # use linera_views::views::View;
2141    /// # let context = MemoryContext::new_for_testing(());
2142    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2143    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2144    /// view.try_load_entry_mut(&23).await.unwrap();
2145    /// view.try_load_entry_mut(&25).await.unwrap();
2146    /// let indices = view.indices().await.unwrap();
2147    /// assert_eq!(indices, vec![23, 25]);
2148    /// # })
2149    /// ```
2150    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
2151        let mut indices = Vec::new();
2152        self.for_each_index(|index| {
2153            indices.push(index);
2154            Ok(())
2155        })
2156        .await?;
2157        Ok(indices)
2158    }
2159
2160    /// Returns the number of entries in the collection.
2161    /// ```rust
2162    /// # tokio_test::block_on(async {
2163    /// # use linera_views::context::MemoryContext;
2164    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2165    /// # use linera_views::register_view::RegisterView;
2166    /// # use linera_views::views::View;
2167    /// # let context = MemoryContext::new_for_testing(());
2168    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2169    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2170    /// view.try_load_entry_mut(&23).await.unwrap();
2171    /// view.try_load_entry_mut(&25).await.unwrap();
2172    /// assert_eq!(view.iterative_count().await.unwrap(), 2);
2173    /// # })
2174    /// ```
2175    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
2176        self.collection.iterative_count().await
2177    }
2178
2179    /// Applies a function f on each index. Indices are visited in an order
2180    /// determined by the custom serialization. If the function f returns false
2181    /// then the loop ends prematurely.
2182    /// ```rust
2183    /// # tokio_test::block_on(async {
2184    /// # use linera_views::context::MemoryContext;
2185    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2186    /// # use linera_views::register_view::RegisterView;
2187    /// # use linera_views::views::View;
2188    /// # let context = MemoryContext::new_for_testing(());
2189    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2190    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2191    /// view.try_load_entry_mut(&28).await.unwrap();
2192    /// view.try_load_entry_mut(&24).await.unwrap();
2193    /// view.try_load_entry_mut(&23).await.unwrap();
2194    /// let mut part_indices = Vec::new();
2195    /// view.for_each_index_while(|index| {
2196    ///     part_indices.push(index);
2197    ///     Ok(part_indices.len() < 2)
2198    /// })
2199    /// .await
2200    /// .unwrap();
2201    /// assert_eq!(part_indices, vec![23, 24]);
2202    /// # })
2203    /// ```
2204    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
2205    where
2206        F: FnMut(I) -> Result<bool, ViewError> + Send,
2207    {
2208        self.collection
2209            .for_each_key_while(|key| {
2210                let index = I::from_custom_bytes(key)?;
2211                f(index)
2212            })
2213            .await?;
2214        Ok(())
2215    }
2216
2217    /// Applies a function f on each index. Indices are visited in an order
2218    /// determined by the custom serialization.
2219    /// ```rust
2220    /// # tokio_test::block_on(async {
2221    /// # use linera_views::context::MemoryContext;
2222    /// # use linera_views::reentrant_collection_view::ReentrantCustomCollectionView;
2223    /// # use linera_views::register_view::RegisterView;
2224    /// # use linera_views::views::View;
2225    /// # let context = MemoryContext::new_for_testing(());
2226    /// let mut view: ReentrantCustomCollectionView<_, u128, RegisterView<_, String>> =
2227    ///     ReentrantCustomCollectionView::load(context).await.unwrap();
2228    /// view.try_load_entry_mut(&28).await.unwrap();
2229    /// view.try_load_entry_mut(&24).await.unwrap();
2230    /// view.try_load_entry_mut(&23).await.unwrap();
2231    /// let mut indices = Vec::new();
2232    /// view.for_each_index(|index| {
2233    ///     indices.push(index);
2234    ///     Ok(())
2235    /// })
2236    /// .await
2237    /// .unwrap();
2238    /// assert_eq!(indices, vec![23, 24, 28]);
2239    /// # })
2240    /// ```
2241    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
2242    where
2243        F: FnMut(I) -> Result<(), ViewError> + Send,
2244    {
2245        self.collection
2246            .for_each_key(|key| {
2247                let index = I::from_custom_bytes(key)?;
2248                f(index)
2249            })
2250            .await?;
2251        Ok(())
2252    }
2253}
2254
2255impl<I, W> HashableView for ReentrantCustomCollectionView<W::Context, I, W>
2256where
2257    W: HashableView,
2258    I: Send + Sync + CustomSerialize,
2259{
2260    type Hasher = sha3::Sha3_256;
2261
2262    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
2263        self.collection.hash_mut().await
2264    }
2265
2266    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
2267        self.collection.hash().await
2268    }
2269}
2270
2271/// Type wrapping `ReentrantByteCollectionView` while memoizing the hash.
2272pub type HashedReentrantByteCollectionView<C, W> =
2273    WrappedHashableContainerView<C, ReentrantByteCollectionView<C, W>, HasherOutput>;
2274
2275/// Type wrapping `ReentrantCollectionView` while memoizing the hash.
2276pub type HashedReentrantCollectionView<C, I, W> =
2277    WrappedHashableContainerView<C, ReentrantCollectionView<C, I, W>, HasherOutput>;
2278
2279/// Type wrapping `ReentrantCustomCollectionView` while memoizing the hash.
2280pub type HashedReentrantCustomCollectionView<C, I, W> =
2281    WrappedHashableContainerView<C, ReentrantCustomCollectionView<C, I, W>, HasherOutput>;
2282
2283/// Wrapper around `ReentrantByteCollectionView` to compute hashes based on the history of changes.
2284pub type HistoricallyHashedReentrantByteCollectionView<C, W> =
2285    HistoricallyHashableView<C, ReentrantByteCollectionView<C, W>>;
2286
2287/// Wrapper around `ReentrantCollectionView` to compute hashes based on the history of changes.
2288pub type HistoricallyHashedReentrantCollectionView<C, I, W> =
2289    HistoricallyHashableView<C, ReentrantCollectionView<C, I, W>>;
2290
2291/// Wrapper around `ReentrantCustomCollectionView` to compute hashes based on the history of changes.
2292pub type HistoricallyHashedReentrantCustomCollectionView<C, I, W> =
2293    HistoricallyHashableView<C, ReentrantCustomCollectionView<C, I, W>>;
2294
2295#[cfg(with_graphql)]
2296mod graphql {
2297    use std::borrow::Cow;
2298
2299    use super::{ReadGuardedView, ReentrantCollectionView};
2300    use crate::{
2301        graphql::{hash_name, mangle, missing_key_error, Entry, MapInput},
2302        views::View,
2303    };
2304
2305    impl<T: async_graphql::OutputType> async_graphql::OutputType for ReadGuardedView<T> {
2306        fn type_name() -> Cow<'static, str> {
2307            T::type_name()
2308        }
2309
2310        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
2311            T::create_type_info(registry)
2312        }
2313
2314        async fn resolve(
2315            &self,
2316            ctx: &async_graphql::ContextSelectionSet<'_>,
2317            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
2318        ) -> async_graphql::ServerResult<async_graphql::Value> {
2319            (**self).resolve(ctx, field).await
2320        }
2321    }
2322
2323    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
2324        async_graphql::TypeName for ReentrantCollectionView<C, K, V>
2325    {
2326        fn type_name() -> Cow<'static, str> {
2327            format!(
2328                "ReentrantCollectionView_{}_{}_{:08x}",
2329                mangle(K::type_name()),
2330                mangle(V::type_name()),
2331                hash_name::<(K, V)>(),
2332            )
2333            .into()
2334        }
2335    }
2336
2337    #[async_graphql::Object(cache_control(no_cache), name_type)]
2338    impl<K, V> ReentrantCollectionView<V::Context, K, V>
2339    where
2340        K: async_graphql::InputType
2341            + async_graphql::OutputType
2342            + serde::ser::Serialize
2343            + serde::de::DeserializeOwned
2344            + std::fmt::Debug,
2345        V: View + async_graphql::OutputType,
2346    {
2347        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
2348            Ok(self.indices().await?)
2349        }
2350
2351        #[graphql(derived(name = "count"))]
2352        async fn count_(&self) -> Result<u32, async_graphql::Error> {
2353            Ok(self.iterative_count().await? as u32)
2354        }
2355
2356        async fn entry(
2357            &self,
2358            key: K,
2359        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
2360            let value = self
2361                .try_load_entry(&key)
2362                .await?
2363                .ok_or_else(|| missing_key_error(&key))?;
2364            Ok(Entry { value, key })
2365        }
2366
2367        async fn entries(
2368            &self,
2369            input: Option<MapInput<K>>,
2370        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
2371            let keys = if let Some(keys) = input
2372                .and_then(|input| input.filters)
2373                .and_then(|filters| filters.keys)
2374            {
2375                keys
2376            } else {
2377                self.indices().await?
2378            };
2379
2380            let values = self.try_load_entries(&keys).await?;
2381            Ok(values
2382                .into_iter()
2383                .zip(keys)
2384                .filter_map(|(value, key)| value.map(|value| Entry { value, key }))
2385                .collect())
2386        }
2387    }
2388
2389    use crate::reentrant_collection_view::ReentrantCustomCollectionView;
2390    impl<C: Send + Sync, K: async_graphql::OutputType, V: async_graphql::OutputType>
2391        async_graphql::TypeName for ReentrantCustomCollectionView<C, K, V>
2392    {
2393        fn type_name() -> Cow<'static, str> {
2394            format!(
2395                "ReentrantCustomCollectionView_{}_{}_{:08x}",
2396                mangle(K::type_name()),
2397                mangle(V::type_name()),
2398                hash_name::<(K, V)>(),
2399            )
2400            .into()
2401        }
2402    }
2403
2404    #[async_graphql::Object(cache_control(no_cache), name_type)]
2405    impl<K, V> ReentrantCustomCollectionView<V::Context, K, V>
2406    where
2407        K: async_graphql::InputType
2408            + async_graphql::OutputType
2409            + crate::common::CustomSerialize
2410            + std::fmt::Debug,
2411        V: View + async_graphql::OutputType,
2412    {
2413        async fn keys(&self) -> Result<Vec<K>, async_graphql::Error> {
2414            Ok(self.indices().await?)
2415        }
2416
2417        async fn entry(
2418            &self,
2419            key: K,
2420        ) -> Result<Entry<K, ReadGuardedView<V>>, async_graphql::Error> {
2421            let value = self
2422                .try_load_entry(&key)
2423                .await?
2424                .ok_or_else(|| missing_key_error(&key))?;
2425            Ok(Entry { value, key })
2426        }
2427
2428        async fn entries(
2429            &self,
2430            input: Option<MapInput<K>>,
2431        ) -> Result<Vec<Entry<K, ReadGuardedView<V>>>, async_graphql::Error> {
2432            let keys = if let Some(keys) = input
2433                .and_then(|input| input.filters)
2434                .and_then(|filters| filters.keys)
2435            {
2436                keys
2437            } else {
2438                self.indices().await?
2439            };
2440
2441            let values = self.try_load_entries(&keys).await?;
2442            Ok(values
2443                .into_iter()
2444                .zip(keys)
2445                .filter_map(|(value, key)| value.map(|value| Entry { value, key }))
2446                .collect())
2447        }
2448    }
2449}