linera_views/views/
set_view.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::{borrow::Borrow, collections::BTreeMap, marker::PhantomData, mem};
5
6#[cfg(with_metrics)]
7use linera_base::prometheus_util::MeasureLatency as _;
8use serde::{de::DeserializeOwned, Serialize};
9
10use crate::{
11    batch::Batch,
12    common::{CustomSerialize, HasherOutput, Update},
13    context::{BaseKey, Context},
14    hashable_wrapper::WrappedHashableContainerView,
15    store::ReadableKeyValueStore as _,
16    views::{ClonableView, HashableView, Hasher, View, ViewError},
17};
18
19#[cfg(with_metrics)]
20mod metrics {
21    use std::sync::LazyLock;
22
23    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
24    use prometheus::HistogramVec;
25
26    /// The runtime of hash computation
27    pub static SET_VIEW_HASH_RUNTIME: LazyLock<HistogramVec> = LazyLock::new(|| {
28        register_histogram_vec(
29            "set_view_hash_runtime",
30            "SetView hash runtime",
31            &[],
32            exponential_bucket_latencies(5.0),
33        )
34    });
35}
36
37/// A [`View`] that supports inserting and removing values indexed by a key.
38#[derive(Debug)]
39pub struct ByteSetView<C> {
40    context: C,
41    delete_storage_first: bool,
42    updates: BTreeMap<Vec<u8>, Update<()>>,
43}
44
45impl<C: Context> View for ByteSetView<C> {
46    const NUM_INIT_KEYS: usize = 0;
47
48    type Context = C;
49
50    fn context(&self) -> &C {
51        &self.context
52    }
53
54    fn pre_load(_context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
55        Ok(Vec::new())
56    }
57
58    fn post_load(context: C, _values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
59        Ok(Self {
60            context,
61            delete_storage_first: false,
62            updates: BTreeMap::new(),
63        })
64    }
65
66    async fn load(context: C) -> Result<Self, ViewError> {
67        Self::post_load(context, &[])
68    }
69
70    fn rollback(&mut self) {
71        self.delete_storage_first = false;
72        self.updates.clear();
73    }
74
75    async fn has_pending_changes(&self) -> bool {
76        if self.delete_storage_first {
77            return true;
78        }
79        !self.updates.is_empty()
80    }
81
82    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
83        let mut delete_view = false;
84        if self.delete_storage_first {
85            delete_view = true;
86            batch.delete_key_prefix(self.context.base_key().bytes.clone());
87            for (index, update) in mem::take(&mut self.updates) {
88                if let Update::Set(_) = update {
89                    let key = self.context.base_key().base_index(&index);
90                    batch.put_key_value_bytes(key, Vec::new());
91                    delete_view = false;
92                }
93            }
94        } else {
95            for (index, update) in mem::take(&mut self.updates) {
96                let key = self.context.base_key().base_index(&index);
97                match update {
98                    Update::Removed => batch.delete_key(key),
99                    Update::Set(_) => batch.put_key_value_bytes(key, Vec::new()),
100                }
101            }
102        }
103        self.delete_storage_first = false;
104        Ok(delete_view)
105    }
106
107    fn clear(&mut self) {
108        self.delete_storage_first = true;
109        self.updates.clear();
110    }
111}
112
113impl<C: Context> ClonableView for ByteSetView<C> {
114    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
115        Ok(ByteSetView {
116            context: self.context.clone(),
117            delete_storage_first: self.delete_storage_first,
118            updates: self.updates.clone(),
119        })
120    }
121}
122
123impl<C: Context> ByteSetView<C> {
124    /// Insert a value. If already present then it has no effect.
125    /// ```rust
126    /// # tokio_test::block_on(async {
127    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
128    /// # use linera_views::views::View;
129    /// # let context = MemoryContext::new_for_testing(());
130    /// let mut set = ByteSetView::load(context).await.unwrap();
131    /// set.insert(vec![0, 1]);
132    /// assert_eq!(set.contains(&[0, 1]).await.unwrap(), true);
133    /// # })
134    /// ```
135    pub fn insert(&mut self, short_key: Vec<u8>) {
136        self.updates.insert(short_key, Update::Set(()));
137    }
138
139    /// Removes a value from the set. If absent then no effect.
140    /// ```rust
141    /// # tokio_test::block_on(async {
142    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
143    /// # use linera_views::views::View;
144    /// # let context = MemoryContext::new_for_testing(());
145    /// let mut set = ByteSetView::load(context).await.unwrap();
146    /// set.remove(vec![0, 1]);
147    /// assert_eq!(set.contains(&[0, 1]).await.unwrap(), false);
148    /// # })
149    /// ```
150    pub fn remove(&mut self, short_key: Vec<u8>) {
151        if self.delete_storage_first {
152            // Optimization: No need to mark `short_key` for deletion as we are going to remove all the keys at once.
153            self.updates.remove(&short_key);
154        } else {
155            self.updates.insert(short_key, Update::Removed);
156        }
157    }
158
159    /// Gets the extra data.
160    pub fn extra(&self) -> &C::Extra {
161        self.context.extra()
162    }
163}
164
165impl<C: Context> ByteSetView<C> {
166    /// Returns true if the given index exists in the set.
167    /// ```rust
168    /// # tokio_test::block_on(async {
169    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
170    /// # use linera_views::views::View;
171    /// # let context = MemoryContext::new_for_testing(());
172    /// let mut set = ByteSetView::load(context).await.unwrap();
173    /// set.insert(vec![0, 1]);
174    /// assert_eq!(set.contains(&[34]).await.unwrap(), false);
175    /// assert_eq!(set.contains(&[0, 1]).await.unwrap(), true);
176    /// # })
177    /// ```
178    pub async fn contains(&self, short_key: &[u8]) -> Result<bool, ViewError> {
179        if let Some(update) = self.updates.get(short_key) {
180            let value = match update {
181                Update::Removed => false,
182                Update::Set(()) => true,
183            };
184            return Ok(value);
185        }
186        if self.delete_storage_first {
187            return Ok(false);
188        }
189        let key = self.context.base_key().base_index(short_key);
190        Ok(self.context.store().contains_key(&key).await?)
191    }
192}
193
194impl<C: Context> ByteSetView<C> {
195    /// Returns the list of keys in the set. The order is lexicographic.
196    /// ```rust
197    /// # tokio_test::block_on(async {
198    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
199    /// # use linera_views::views::View;
200    /// # let context = MemoryContext::new_for_testing(());
201    /// let mut set = ByteSetView::load(context).await.unwrap();
202    /// set.insert(vec![0, 1]);
203    /// set.insert(vec![0, 2]);
204    /// assert_eq!(set.keys().await.unwrap(), vec![vec![0, 1], vec![0, 2]]);
205    /// # })
206    /// ```
207    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
208        let mut keys = Vec::new();
209        self.for_each_key(|key| {
210            keys.push(key.to_vec());
211            Ok(())
212        })
213        .await?;
214        Ok(keys)
215    }
216
217    /// Returns the number of entries in the set.
218    /// ```rust
219    /// # tokio_test::block_on(async {
220    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
221    /// # use linera_views::views::View;
222    /// # let context = MemoryContext::new_for_testing(());
223    /// let mut set = ByteSetView::load(context).await.unwrap();
224    /// set.insert(vec![0, 1]);
225    /// set.insert(vec![0, 2]);
226    /// assert_eq!(set.keys().await.unwrap(), vec![vec![0, 1], vec![0, 2]]);
227    /// # })
228    /// ```
229    pub async fn count(&self) -> Result<usize, ViewError> {
230        let mut count = 0;
231        self.for_each_key(|_key| {
232            count += 1;
233            Ok(())
234        })
235        .await?;
236        Ok(count)
237    }
238
239    /// Applies a function f on each index (aka key). Keys are visited in a
240    /// lexicographic order. If the function returns false, then the loop ends
241    /// prematurely.
242    /// ```rust
243    /// # tokio_test::block_on(async {
244    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
245    /// # use linera_views::views::View;
246    /// # let context = MemoryContext::new_for_testing(());
247    /// let mut set = ByteSetView::load(context).await.unwrap();
248    /// set.insert(vec![0, 1]);
249    /// set.insert(vec![0, 2]);
250    /// set.insert(vec![3]);
251    /// let mut count = 0;
252    /// set.for_each_key_while(|_key| {
253    ///     count += 1;
254    ///     Ok(count < 2)
255    /// })
256    /// .await
257    /// .unwrap();
258    /// assert_eq!(count, 2);
259    /// # })
260    /// ```
261    pub async fn for_each_key_while<F>(&self, mut f: F) -> Result<(), ViewError>
262    where
263        F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
264    {
265        let mut updates = self.updates.iter();
266        let mut update = updates.next();
267        if !self.delete_storage_first {
268            let base = &self.context.base_key().bytes;
269            for index in self.context.store().find_keys_by_prefix(base).await? {
270                loop {
271                    match update {
272                        Some((key, value)) if key <= &index => {
273                            if let Update::Set(_) = value {
274                                if !f(key)? {
275                                    return Ok(());
276                                }
277                            }
278                            update = updates.next();
279                            if key == &index {
280                                break;
281                            }
282                        }
283                        _ => {
284                            if !f(&index)? {
285                                return Ok(());
286                            }
287                            break;
288                        }
289                    }
290                }
291            }
292        }
293        while let Some((key, value)) = update {
294            if let Update::Set(_) = value {
295                if !f(key)? {
296                    return Ok(());
297                }
298            }
299            update = updates.next();
300        }
301        Ok(())
302    }
303
304    /// Applies a function f on each serialized index (aka key). Keys are visited in a
305    /// lexicographic order.
306    /// ```rust
307    /// # tokio_test::block_on(async {
308    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
309    /// # use linera_views::views::View;
310    /// # let context = MemoryContext::new_for_testing(());
311    /// let mut set = ByteSetView::load(context).await.unwrap();
312    /// set.insert(vec![0, 1]);
313    /// set.insert(vec![0, 2]);
314    /// set.insert(vec![3]);
315    /// let mut count = 0;
316    /// set.for_each_key(|_key| {
317    ///     count += 1;
318    ///     Ok(())
319    /// })
320    /// .await
321    /// .unwrap();
322    /// assert_eq!(count, 3);
323    /// # })
324    /// ```
325    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
326    where
327        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
328    {
329        self.for_each_key_while(|key| {
330            f(key)?;
331            Ok(true)
332        })
333        .await
334    }
335}
336
337impl<C: Context> HashableView for ByteSetView<C> {
338    type Hasher = sha3::Sha3_256;
339
340    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
341        self.hash().await
342    }
343
344    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
345        #[cfg(with_metrics)]
346        let _hash_latency = metrics::SET_VIEW_HASH_RUNTIME.measure_latency();
347        let mut hasher = sha3::Sha3_256::default();
348        let mut count = 0u32;
349        self.for_each_key(|key| {
350            count += 1;
351            hasher.update_with_bytes(key)?;
352            Ok(())
353        })
354        .await?;
355        hasher.update_with_bcs_bytes(&count)?;
356        Ok(hasher.finalize())
357    }
358}
359
360/// A [`View`] implementing the set functionality with the index `I` being any serializable type.
361#[derive(Debug)]
362pub struct SetView<C, I> {
363    set: ByteSetView<C>,
364    _phantom: PhantomData<I>,
365}
366
367impl<C: Context, I: Send + Sync + Serialize> View for SetView<C, I> {
368    const NUM_INIT_KEYS: usize = ByteSetView::<C>::NUM_INIT_KEYS;
369
370    type Context = C;
371
372    fn context(&self) -> &C {
373        self.set.context()
374    }
375
376    fn pre_load(context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
377        ByteSetView::<C>::pre_load(context)
378    }
379
380    fn post_load(context: C, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
381        let set = ByteSetView::post_load(context, values)?;
382        Ok(Self {
383            set,
384            _phantom: PhantomData,
385        })
386    }
387
388    async fn load(context: C) -> Result<Self, ViewError> {
389        Self::post_load(context, &[])
390    }
391
392    fn rollback(&mut self) {
393        self.set.rollback()
394    }
395
396    async fn has_pending_changes(&self) -> bool {
397        self.set.has_pending_changes().await
398    }
399
400    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
401        self.set.flush(batch)
402    }
403
404    fn clear(&mut self) {
405        self.set.clear()
406    }
407}
408
409impl<C, I> ClonableView for SetView<C, I>
410where
411    C: Context,
412    I: Send + Sync + Serialize,
413{
414    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
415        Ok(SetView {
416            set: self.set.clone_unchecked()?,
417            _phantom: PhantomData,
418        })
419    }
420}
421
422impl<C: Context, I: Serialize> SetView<C, I> {
423    /// Inserts a value. If already present then no effect.
424    /// ```rust
425    /// # tokio_test::block_on(async {
426    /// # use linera_views::context::MemoryContext;
427    /// # use linera_views::set_view::SetView;
428    /// # use linera_views::views::View;
429    /// # let context = MemoryContext::new_for_testing(());
430    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
431    /// set.insert(&(34 as u32));
432    /// assert_eq!(set.indices().await.unwrap().len(), 1);
433    /// # })
434    /// ```
435    pub fn insert<Q>(&mut self, index: &Q) -> Result<(), ViewError>
436    where
437        I: Borrow<Q>,
438        Q: Serialize + ?Sized,
439    {
440        let short_key = BaseKey::derive_short_key(index)?;
441        self.set.insert(short_key);
442        Ok(())
443    }
444
445    /// Removes a value. If absent then nothing is done.
446    /// ```rust
447    /// # tokio_test::block_on(async {
448    /// # use linera_views::{context::MemoryContext, set_view::SetView};
449    /// # use linera_views::views::View;
450    /// # let context = MemoryContext::new_for_testing(());
451    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
452    /// set.remove(&(34 as u32));
453    /// assert_eq!(set.indices().await.unwrap().len(), 0);
454    /// # })
455    /// ```
456    pub fn remove<Q>(&mut self, index: &Q) -> Result<(), ViewError>
457    where
458        I: Borrow<Q>,
459        Q: Serialize + ?Sized,
460    {
461        let short_key = BaseKey::derive_short_key(index)?;
462        self.set.remove(short_key);
463        Ok(())
464    }
465
466    /// Obtains the extra data.
467    pub fn extra(&self) -> &C::Extra {
468        self.set.extra()
469    }
470}
471
472impl<C: Context, I: Serialize> SetView<C, I> {
473    /// Returns true if the given index exists in the set.
474    /// ```rust
475    /// # tokio_test::block_on(async {
476    /// # use linera_views::{context::MemoryContext, set_view::SetView};
477    /// # use linera_views::views::View;
478    /// # let context = MemoryContext::new_for_testing(());
479    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
480    /// set.insert(&(34 as u32));
481    /// assert_eq!(set.contains(&(34 as u32)).await.unwrap(), true);
482    /// assert_eq!(set.contains(&(45 as u32)).await.unwrap(), false);
483    /// # })
484    /// ```
485    pub async fn contains<Q>(&self, index: &Q) -> Result<bool, ViewError>
486    where
487        I: Borrow<Q>,
488        Q: Serialize + ?Sized,
489    {
490        let short_key = BaseKey::derive_short_key(index)?;
491        self.set.contains(&short_key).await
492    }
493}
494
495impl<C: Context, I: Serialize + DeserializeOwned + Send> SetView<C, I> {
496    /// Returns the list of indices in the set. The order is determined by serialization.
497    /// ```rust
498    /// # tokio_test::block_on(async {
499    /// # use linera_views::{context::MemoryContext, set_view::SetView};
500    /// # use linera_views::views::View;
501    /// # let context = MemoryContext::new_for_testing(());
502    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
503    /// set.insert(&(34 as u32));
504    /// assert_eq!(set.indices().await.unwrap(), vec![34 as u32]);
505    /// # })
506    /// ```
507    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
508        let mut indices = Vec::new();
509        self.for_each_index(|index| {
510            indices.push(index);
511            Ok(())
512        })
513        .await?;
514        Ok(indices)
515    }
516
517    /// Returns the number of entries in the set.
518    /// ```rust
519    /// # tokio_test::block_on(async {
520    /// # use linera_views::{context::MemoryContext, set_view::SetView};
521    /// # use linera_views::views::View;
522    /// # let context = MemoryContext::new_for_testing(());
523    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
524    /// set.insert(&(34 as u32));
525    /// assert_eq!(set.count().await.unwrap(), 1);
526    /// # })
527    /// ```
528    pub async fn count(&self) -> Result<usize, ViewError> {
529        self.set.count().await
530    }
531
532    /// Applies a function f on each index. Indices are visited in an order
533    /// determined by the serialization. If the function returns false, then the
534    /// loop ends prematurely.
535    /// ```rust
536    /// # tokio_test::block_on(async {
537    /// # use linera_views::context::MemoryContext;
538    /// # use linera_views::set_view::SetView;
539    /// # use linera_views::views::View;
540    /// # let context = MemoryContext::new_for_testing(());
541    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
542    /// set.insert(&(34 as u32));
543    /// set.insert(&(37 as u32));
544    /// set.insert(&(42 as u32));
545    /// let mut count = 0;
546    /// set.for_each_index_while(|_key| {
547    ///     count += 1;
548    ///     Ok(count < 2)
549    /// })
550    /// .await
551    /// .unwrap();
552    /// assert_eq!(count, 2);
553    /// # })
554    /// ```
555    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
556    where
557        F: FnMut(I) -> Result<bool, ViewError> + Send,
558    {
559        self.set
560            .for_each_key_while(|key| {
561                let index = BaseKey::deserialize_value(key)?;
562                f(index)
563            })
564            .await?;
565        Ok(())
566    }
567
568    /// Applies a function f on each index. Indices are visited in an order
569    /// determined by the serialization.
570    /// ```rust
571    /// # tokio_test::block_on(async {
572    /// # use linera_views::context::MemoryContext;
573    /// # use linera_views::set_view::SetView;
574    /// # use linera_views::views::View;
575    /// # let context = MemoryContext::new_for_testing(());
576    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
577    /// set.insert(&(34 as u32));
578    /// set.insert(&(37 as u32));
579    /// set.insert(&(42 as u32));
580    /// let mut count = 0;
581    /// set.for_each_index(|_key| {
582    ///     count += 1;
583    ///     Ok(())
584    /// })
585    /// .await
586    /// .unwrap();
587    /// assert_eq!(count, 3);
588    /// # })
589    /// ```
590    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
591    where
592        F: FnMut(I) -> Result<(), ViewError> + Send,
593    {
594        self.set
595            .for_each_key(|key| {
596                let index = BaseKey::deserialize_value(key)?;
597                f(index)
598            })
599            .await?;
600        Ok(())
601    }
602}
603
604impl<C, I> HashableView for SetView<C, I>
605where
606    Self: View,
607    ByteSetView<C>: HashableView,
608{
609    type Hasher = <ByteSetView<C> as HashableView>::Hasher;
610
611    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
612        self.set.hash_mut().await
613    }
614
615    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
616        self.set.hash().await
617    }
618}
619
620/// A [`View`] implementing the set functionality with the index `I` being a type with a custom
621/// serialization format.
622#[derive(Debug)]
623pub struct CustomSetView<C, I> {
624    set: ByteSetView<C>,
625    _phantom: PhantomData<I>,
626}
627
628impl<C, I> View for CustomSetView<C, I>
629where
630    C: Context,
631    I: Send + Sync + CustomSerialize,
632{
633    const NUM_INIT_KEYS: usize = ByteSetView::<C>::NUM_INIT_KEYS;
634
635    type Context = C;
636
637    fn context(&self) -> &C {
638        self.set.context()
639    }
640
641    fn pre_load(context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
642        ByteSetView::pre_load(context)
643    }
644
645    fn post_load(context: C, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
646        let set = ByteSetView::post_load(context, values)?;
647        Ok(Self {
648            set,
649            _phantom: PhantomData,
650        })
651    }
652
653    async fn load(context: C) -> Result<Self, ViewError> {
654        Self::post_load(context, &[])
655    }
656
657    fn rollback(&mut self) {
658        self.set.rollback()
659    }
660
661    async fn has_pending_changes(&self) -> bool {
662        self.set.has_pending_changes().await
663    }
664
665    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
666        self.set.flush(batch)
667    }
668
669    fn clear(&mut self) {
670        self.set.clear()
671    }
672}
673
674impl<C, I> ClonableView for CustomSetView<C, I>
675where
676    C: Context,
677    I: Send + Sync + CustomSerialize,
678{
679    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
680        Ok(CustomSetView {
681            set: self.set.clone_unchecked()?,
682            _phantom: PhantomData,
683        })
684    }
685}
686
687impl<C: Context, I: CustomSerialize> CustomSetView<C, I> {
688    /// Inserts a value. If present then it has no effect.
689    /// ```rust
690    /// # tokio_test::block_on(async {
691    /// # use linera_views::context::MemoryContext;
692    /// # use linera_views::set_view::CustomSetView;
693    /// # use linera_views::views::View;
694    /// # let context = MemoryContext::new_for_testing(());
695    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
696    /// set.insert(&(34 as u128));
697    /// assert_eq!(set.indices().await.unwrap().len(), 1);
698    /// # })
699    /// ```
700    pub fn insert<Q>(&mut self, index: &Q) -> Result<(), ViewError>
701    where
702        I: Borrow<Q>,
703        Q: CustomSerialize,
704    {
705        let short_key = index.to_custom_bytes()?;
706        self.set.insert(short_key);
707        Ok(())
708    }
709
710    /// Removes a value. If absent then nothing is done.
711    /// ```rust
712    /// # tokio_test::block_on(async {
713    /// # use linera_views::context::MemoryContext;
714    /// # use linera_views::set_view::CustomSetView;
715    /// # use linera_views::views::View;
716    /// # let context = MemoryContext::new_for_testing(());
717    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
718    /// set.remove(&(34 as u128));
719    /// assert_eq!(set.indices().await.unwrap().len(), 0);
720    /// # })
721    /// ```
722    pub fn remove<Q>(&mut self, index: &Q) -> Result<(), ViewError>
723    where
724        I: Borrow<Q>,
725        Q: CustomSerialize,
726    {
727        let short_key = index.to_custom_bytes()?;
728        self.set.remove(short_key);
729        Ok(())
730    }
731
732    /// Obtains the extra data.
733    pub fn extra(&self) -> &C::Extra {
734        self.set.extra()
735    }
736}
737
738impl<C, I> CustomSetView<C, I>
739where
740    C: Context,
741    I: CustomSerialize,
742{
743    /// Returns true if the given index exists in the set.
744    /// ```rust
745    /// # tokio_test::block_on(async {
746    /// # use linera_views::context::MemoryContext;
747    /// # use linera_views::set_view::CustomSetView;
748    /// # use linera_views::views::View;
749    /// # let context = MemoryContext::new_for_testing(());
750    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
751    /// set.insert(&(34 as u128));
752    /// assert_eq!(set.contains(&(34 as u128)).await.unwrap(), true);
753    /// assert_eq!(set.contains(&(37 as u128)).await.unwrap(), false);
754    /// # })
755    /// ```
756    pub async fn contains<Q>(&self, index: &Q) -> Result<bool, ViewError>
757    where
758        I: Borrow<Q>,
759        Q: CustomSerialize,
760    {
761        let short_key = index.to_custom_bytes()?;
762        self.set.contains(&short_key).await
763    }
764}
765
766impl<C, I> CustomSetView<C, I>
767where
768    C: Context,
769    I: Sync + Clone + Send + CustomSerialize,
770{
771    /// Returns the list of indices in the set. The order is determined by the custom
772    /// serialization.
773    /// ```rust
774    /// # tokio_test::block_on(async {
775    /// # use linera_views::context::MemoryContext;
776    /// # use linera_views::set_view::CustomSetView;
777    /// # use linera_views::views::View;
778    /// # let context = MemoryContext::new_for_testing(());
779    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
780    /// set.insert(&(34 as u128));
781    /// set.insert(&(37 as u128));
782    /// assert_eq!(set.indices().await.unwrap(), vec![34 as u128, 37 as u128]);
783    /// # })
784    /// ```
785    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
786        let mut indices = Vec::new();
787        self.for_each_index(|index| {
788            indices.push(index);
789            Ok(())
790        })
791        .await?;
792        Ok(indices)
793    }
794
795    /// Returns the number of entries of the set.
796    /// ```rust
797    /// # tokio_test::block_on(async {
798    /// # use linera_views::context::MemoryContext;
799    /// # use linera_views::set_view::CustomSetView;
800    /// # use linera_views::views::View;
801    /// # let context = MemoryContext::new_for_testing(());
802    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
803    /// set.insert(&(34 as u128));
804    /// set.insert(&(37 as u128));
805    /// assert_eq!(set.count().await.unwrap(), 2);
806    /// # })
807    /// ```
808    pub async fn count(&self) -> Result<usize, ViewError> {
809        self.set.count().await
810    }
811
812    /// Applies a function f on each index. Indices are visited in an order
813    /// determined by the custom serialization. If the function does return
814    /// false, then the loop prematurely ends.
815    /// ```rust
816    /// # tokio_test::block_on(async {
817    /// # use linera_views::context::MemoryContext;
818    /// # use linera_views::set_view::CustomSetView;
819    /// # use linera_views::views::View;
820    /// # let context = MemoryContext::new_for_testing(());
821    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
822    /// set.insert(&(34 as u128));
823    /// set.insert(&(37 as u128));
824    /// set.insert(&(42 as u128));
825    /// let mut count = 0;
826    /// set.for_each_index_while(|_key| {
827    ///     count += 1;
828    ///     Ok(count < 5)
829    /// })
830    /// .await
831    /// .unwrap();
832    /// assert_eq!(count, 3);
833    /// # })
834    /// ```
835    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
836    where
837        F: FnMut(I) -> Result<bool, ViewError> + Send,
838    {
839        self.set
840            .for_each_key_while(|key| {
841                let index = I::from_custom_bytes(key)?;
842                f(index)
843            })
844            .await?;
845        Ok(())
846    }
847
848    /// Applies a function f on each index. Indices are visited in an order
849    /// determined by the custom serialization.
850    /// ```rust
851    /// # tokio_test::block_on(async {
852    /// # use linera_views::context::MemoryContext;
853    /// # use linera_views::set_view::CustomSetView;
854    /// # use linera_views::views::View;
855    /// # let context = MemoryContext::new_for_testing(());
856    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
857    /// set.insert(&(34 as u128));
858    /// set.insert(&(37 as u128));
859    /// set.insert(&(42 as u128));
860    /// let mut count = 0;
861    /// set.for_each_index(|_key| {
862    ///     count += 1;
863    ///     Ok(())
864    /// })
865    /// .await
866    /// .unwrap();
867    /// assert_eq!(count, 3);
868    /// # })
869    /// ```
870    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
871    where
872        F: FnMut(I) -> Result<(), ViewError> + Send,
873    {
874        self.set
875            .for_each_key(|key| {
876                let index = I::from_custom_bytes(key)?;
877                f(index)
878            })
879            .await?;
880        Ok(())
881    }
882}
883
884impl<C: Context, I> HashableView for CustomSetView<C, I>
885where
886    Self: View,
887{
888    type Hasher = sha3::Sha3_256;
889
890    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
891        self.set.hash_mut().await
892    }
893
894    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
895        self.set.hash().await
896    }
897}
898
899/// Type wrapping `ByteSetView` while memoizing the hash.
900pub type HashedByteSetView<C> = WrappedHashableContainerView<C, ByteSetView<C>, HasherOutput>;
901
902/// Type wrapping `SetView` while memoizing the hash.
903pub type HashedSetView<C, I> = WrappedHashableContainerView<C, SetView<C, I>, HasherOutput>;
904
905/// Type wrapping `CustomSetView` while memoizing the hash.
906pub type HashedCustomSetView<C, I> =
907    WrappedHashableContainerView<C, CustomSetView<C, I>, HasherOutput>;
908
909#[cfg(with_graphql)]
910mod graphql {
911    use std::borrow::Cow;
912
913    use super::{CustomSetView, SetView};
914    use crate::context::Context;
915
916    impl<C: Context, I: async_graphql::OutputType> async_graphql::OutputType for SetView<C, I>
917    where
918        I: serde::ser::Serialize + serde::de::DeserializeOwned + Clone + Send + Sync,
919    {
920        fn type_name() -> Cow<'static, str> {
921            format!("[{}]", I::qualified_type_name()).into()
922        }
923
924        fn qualified_type_name() -> String {
925            format!("[{}]!", I::qualified_type_name())
926        }
927
928        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
929            I::create_type_info(registry);
930            Self::qualified_type_name()
931        }
932
933        async fn resolve(
934            &self,
935            ctx: &async_graphql::ContextSelectionSet<'_>,
936            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
937        ) -> async_graphql::ServerResult<async_graphql::Value> {
938            let indices = self
939                .indices()
940                .await
941                .map_err(|e| async_graphql::Error::from(e).into_server_error(ctx.item.pos))?;
942            let indices_len = indices.len();
943            async_graphql::resolver_utils::resolve_list(ctx, field, indices, Some(indices_len))
944                .await
945        }
946    }
947
948    impl<C: Context, I: async_graphql::OutputType> async_graphql::OutputType for CustomSetView<C, I>
949    where
950        I: crate::common::CustomSerialize + Clone + Send + Sync,
951    {
952        fn type_name() -> Cow<'static, str> {
953            format!("[{}]", I::qualified_type_name()).into()
954        }
955
956        fn qualified_type_name() -> String {
957            format!("[{}]!", I::qualified_type_name())
958        }
959
960        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
961            I::create_type_info(registry);
962            Self::qualified_type_name()
963        }
964
965        async fn resolve(
966            &self,
967            ctx: &async_graphql::ContextSelectionSet<'_>,
968            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
969        ) -> async_graphql::ServerResult<async_graphql::Value> {
970            let indices = self
971                .indices()
972                .await
973                .map_err(|e| async_graphql::Error::from(e).into_server_error(ctx.item.pos))?;
974            let indices_len = indices.len();
975            async_graphql::resolver_utils::resolve_list(ctx, field, indices, Some(indices_len))
976                .await
977        }
978    }
979}