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::{KeyIterable, 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
270                .context
271                .store()
272                .find_keys_by_prefix(base)
273                .await?
274                .iterator()
275            {
276                let index = index?;
277                loop {
278                    match update {
279                        Some((key, value)) if key.as_slice() <= index => {
280                            if let Update::Set(_) = value {
281                                if !f(key)? {
282                                    return Ok(());
283                                }
284                            }
285                            update = updates.next();
286                            if key == index {
287                                break;
288                            }
289                        }
290                        _ => {
291                            if !f(index)? {
292                                return Ok(());
293                            }
294                            break;
295                        }
296                    }
297                }
298            }
299        }
300        while let Some((key, value)) = update {
301            if let Update::Set(_) = value {
302                if !f(key)? {
303                    return Ok(());
304                }
305            }
306            update = updates.next();
307        }
308        Ok(())
309    }
310
311    /// Applies a function f on each serialized index (aka key). Keys are visited in a
312    /// lexicographic order.
313    /// ```rust
314    /// # tokio_test::block_on(async {
315    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
316    /// # use linera_views::views::View;
317    /// # let context = MemoryContext::new_for_testing(());
318    /// let mut set = ByteSetView::load(context).await.unwrap();
319    /// set.insert(vec![0, 1]);
320    /// set.insert(vec![0, 2]);
321    /// set.insert(vec![3]);
322    /// let mut count = 0;
323    /// set.for_each_key(|_key| {
324    ///     count += 1;
325    ///     Ok(())
326    /// })
327    /// .await
328    /// .unwrap();
329    /// assert_eq!(count, 3);
330    /// # })
331    /// ```
332    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
333    where
334        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
335    {
336        self.for_each_key_while(|key| {
337            f(key)?;
338            Ok(true)
339        })
340        .await
341    }
342}
343
344impl<C: Context> HashableView for ByteSetView<C> {
345    type Hasher = sha3::Sha3_256;
346
347    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
348        self.hash().await
349    }
350
351    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
352        #[cfg(with_metrics)]
353        let _hash_latency = metrics::SET_VIEW_HASH_RUNTIME.measure_latency();
354        let mut hasher = sha3::Sha3_256::default();
355        let mut count = 0u32;
356        self.for_each_key(|key| {
357            count += 1;
358            hasher.update_with_bytes(key)?;
359            Ok(())
360        })
361        .await?;
362        hasher.update_with_bcs_bytes(&count)?;
363        Ok(hasher.finalize())
364    }
365}
366
367/// A [`View`] implementing the set functionality with the index `I` being any serializable type.
368#[derive(Debug)]
369pub struct SetView<C, I> {
370    set: ByteSetView<C>,
371    _phantom: PhantomData<I>,
372}
373
374impl<C: Context, I: Send + Sync + Serialize> View for SetView<C, I> {
375    const NUM_INIT_KEYS: usize = ByteSetView::<C>::NUM_INIT_KEYS;
376
377    type Context = C;
378
379    fn context(&self) -> &C {
380        self.set.context()
381    }
382
383    fn pre_load(context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
384        ByteSetView::<C>::pre_load(context)
385    }
386
387    fn post_load(context: C, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
388        let set = ByteSetView::post_load(context, values)?;
389        Ok(Self {
390            set,
391            _phantom: PhantomData,
392        })
393    }
394
395    async fn load(context: C) -> Result<Self, ViewError> {
396        Self::post_load(context, &[])
397    }
398
399    fn rollback(&mut self) {
400        self.set.rollback()
401    }
402
403    async fn has_pending_changes(&self) -> bool {
404        self.set.has_pending_changes().await
405    }
406
407    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
408        self.set.flush(batch)
409    }
410
411    fn clear(&mut self) {
412        self.set.clear()
413    }
414}
415
416impl<C, I> ClonableView for SetView<C, I>
417where
418    C: Context,
419    I: Send + Sync + Serialize,
420{
421    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
422        Ok(SetView {
423            set: self.set.clone_unchecked()?,
424            _phantom: PhantomData,
425        })
426    }
427}
428
429impl<C: Context, I: Serialize> SetView<C, I> {
430    /// Inserts a value. If already present then no effect.
431    /// ```rust
432    /// # tokio_test::block_on(async {
433    /// # use linera_views::context::MemoryContext;
434    /// # use linera_views::set_view::SetView;
435    /// # use linera_views::views::View;
436    /// # let context = MemoryContext::new_for_testing(());
437    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
438    /// set.insert(&(34 as u32));
439    /// assert_eq!(set.indices().await.unwrap().len(), 1);
440    /// # })
441    /// ```
442    pub fn insert<Q>(&mut self, index: &Q) -> Result<(), ViewError>
443    where
444        I: Borrow<Q>,
445        Q: Serialize + ?Sized,
446    {
447        let short_key = BaseKey::derive_short_key(index)?;
448        self.set.insert(short_key);
449        Ok(())
450    }
451
452    /// Removes a value. If absent then nothing is done.
453    /// ```rust
454    /// # tokio_test::block_on(async {
455    /// # use linera_views::{context::MemoryContext, set_view::SetView};
456    /// # use linera_views::views::View;
457    /// # let context = MemoryContext::new_for_testing(());
458    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
459    /// set.remove(&(34 as u32));
460    /// assert_eq!(set.indices().await.unwrap().len(), 0);
461    /// # })
462    /// ```
463    pub fn remove<Q>(&mut self, index: &Q) -> Result<(), ViewError>
464    where
465        I: Borrow<Q>,
466        Q: Serialize + ?Sized,
467    {
468        let short_key = BaseKey::derive_short_key(index)?;
469        self.set.remove(short_key);
470        Ok(())
471    }
472
473    /// Obtains the extra data.
474    pub fn extra(&self) -> &C::Extra {
475        self.set.extra()
476    }
477}
478
479impl<C: Context, I: Serialize> SetView<C, I> {
480    /// Returns true if the given index exists in the set.
481    /// ```rust
482    /// # tokio_test::block_on(async {
483    /// # use linera_views::{context::MemoryContext, set_view::SetView};
484    /// # use linera_views::views::View;
485    /// # let context = MemoryContext::new_for_testing(());
486    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
487    /// set.insert(&(34 as u32));
488    /// assert_eq!(set.contains(&(34 as u32)).await.unwrap(), true);
489    /// assert_eq!(set.contains(&(45 as u32)).await.unwrap(), false);
490    /// # })
491    /// ```
492    pub async fn contains<Q>(&self, index: &Q) -> Result<bool, ViewError>
493    where
494        I: Borrow<Q>,
495        Q: Serialize + ?Sized,
496    {
497        let short_key = BaseKey::derive_short_key(index)?;
498        self.set.contains(&short_key).await
499    }
500}
501
502impl<C: Context, I: Serialize + DeserializeOwned + Send> SetView<C, I> {
503    /// Returns the list of indices in the set. The order is determined by serialization.
504    /// ```rust
505    /// # tokio_test::block_on(async {
506    /// # use linera_views::{context::MemoryContext, set_view::SetView};
507    /// # use linera_views::views::View;
508    /// # let context = MemoryContext::new_for_testing(());
509    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
510    /// set.insert(&(34 as u32));
511    /// assert_eq!(set.indices().await.unwrap(), vec![34 as u32]);
512    /// # })
513    /// ```
514    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
515        let mut indices = Vec::new();
516        self.for_each_index(|index| {
517            indices.push(index);
518            Ok(())
519        })
520        .await?;
521        Ok(indices)
522    }
523
524    /// Returns the number of entries in the set.
525    /// ```rust
526    /// # tokio_test::block_on(async {
527    /// # use linera_views::{context::MemoryContext, set_view::SetView};
528    /// # use linera_views::views::View;
529    /// # let context = MemoryContext::new_for_testing(());
530    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
531    /// set.insert(&(34 as u32));
532    /// assert_eq!(set.count().await.unwrap(), 1);
533    /// # })
534    /// ```
535    pub async fn count(&self) -> Result<usize, ViewError> {
536        self.set.count().await
537    }
538
539    /// Applies a function f on each index. Indices are visited in an order
540    /// determined by the serialization. If the function returns false, then the
541    /// loop ends prematurely.
542    /// ```rust
543    /// # tokio_test::block_on(async {
544    /// # use linera_views::context::MemoryContext;
545    /// # use linera_views::set_view::SetView;
546    /// # use linera_views::views::View;
547    /// # let context = MemoryContext::new_for_testing(());
548    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
549    /// set.insert(&(34 as u32));
550    /// set.insert(&(37 as u32));
551    /// set.insert(&(42 as u32));
552    /// let mut count = 0;
553    /// set.for_each_index_while(|_key| {
554    ///     count += 1;
555    ///     Ok(count < 2)
556    /// })
557    /// .await
558    /// .unwrap();
559    /// assert_eq!(count, 2);
560    /// # })
561    /// ```
562    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
563    where
564        F: FnMut(I) -> Result<bool, ViewError> + Send,
565    {
566        self.set
567            .for_each_key_while(|key| {
568                let index = BaseKey::deserialize_value(key)?;
569                f(index)
570            })
571            .await?;
572        Ok(())
573    }
574
575    /// Applies a function f on each index. Indices are visited in an order
576    /// determined by the serialization.
577    /// ```rust
578    /// # tokio_test::block_on(async {
579    /// # use linera_views::context::MemoryContext;
580    /// # use linera_views::set_view::SetView;
581    /// # use linera_views::views::View;
582    /// # let context = MemoryContext::new_for_testing(());
583    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
584    /// set.insert(&(34 as u32));
585    /// set.insert(&(37 as u32));
586    /// set.insert(&(42 as u32));
587    /// let mut count = 0;
588    /// set.for_each_index(|_key| {
589    ///     count += 1;
590    ///     Ok(())
591    /// })
592    /// .await
593    /// .unwrap();
594    /// assert_eq!(count, 3);
595    /// # })
596    /// ```
597    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
598    where
599        F: FnMut(I) -> Result<(), ViewError> + Send,
600    {
601        self.set
602            .for_each_key(|key| {
603                let index = BaseKey::deserialize_value(key)?;
604                f(index)
605            })
606            .await?;
607        Ok(())
608    }
609}
610
611impl<C, I> HashableView for SetView<C, I>
612where
613    Self: View,
614    ByteSetView<C>: HashableView,
615{
616    type Hasher = <ByteSetView<C> as HashableView>::Hasher;
617
618    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
619        self.set.hash_mut().await
620    }
621
622    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
623        self.set.hash().await
624    }
625}
626
627/// A [`View`] implementing the set functionality with the index `I` being a type with a custom
628/// serialization format.
629#[derive(Debug)]
630pub struct CustomSetView<C, I> {
631    set: ByteSetView<C>,
632    _phantom: PhantomData<I>,
633}
634
635impl<C, I> View for CustomSetView<C, I>
636where
637    C: Context,
638    I: Send + Sync + CustomSerialize,
639{
640    const NUM_INIT_KEYS: usize = ByteSetView::<C>::NUM_INIT_KEYS;
641
642    type Context = C;
643
644    fn context(&self) -> &C {
645        self.set.context()
646    }
647
648    fn pre_load(context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
649        ByteSetView::pre_load(context)
650    }
651
652    fn post_load(context: C, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
653        let set = ByteSetView::post_load(context, values)?;
654        Ok(Self {
655            set,
656            _phantom: PhantomData,
657        })
658    }
659
660    async fn load(context: C) -> Result<Self, ViewError> {
661        Self::post_load(context, &[])
662    }
663
664    fn rollback(&mut self) {
665        self.set.rollback()
666    }
667
668    async fn has_pending_changes(&self) -> bool {
669        self.set.has_pending_changes().await
670    }
671
672    fn flush(&mut self, batch: &mut Batch) -> Result<bool, ViewError> {
673        self.set.flush(batch)
674    }
675
676    fn clear(&mut self) {
677        self.set.clear()
678    }
679}
680
681impl<C, I> ClonableView for CustomSetView<C, I>
682where
683    C: Context,
684    I: Send + Sync + CustomSerialize,
685{
686    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
687        Ok(CustomSetView {
688            set: self.set.clone_unchecked()?,
689            _phantom: PhantomData,
690        })
691    }
692}
693
694impl<C: Context, I: CustomSerialize> CustomSetView<C, I> {
695    /// Inserts a value. If present then it has no effect.
696    /// ```rust
697    /// # tokio_test::block_on(async {
698    /// # use linera_views::context::MemoryContext;
699    /// # use linera_views::set_view::CustomSetView;
700    /// # use linera_views::views::View;
701    /// # let context = MemoryContext::new_for_testing(());
702    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
703    /// set.insert(&(34 as u128));
704    /// assert_eq!(set.indices().await.unwrap().len(), 1);
705    /// # })
706    /// ```
707    pub fn insert<Q>(&mut self, index: &Q) -> Result<(), ViewError>
708    where
709        I: Borrow<Q>,
710        Q: CustomSerialize,
711    {
712        let short_key = index.to_custom_bytes()?;
713        self.set.insert(short_key);
714        Ok(())
715    }
716
717    /// Removes a value. If absent then nothing is done.
718    /// ```rust
719    /// # tokio_test::block_on(async {
720    /// # use linera_views::context::MemoryContext;
721    /// # use linera_views::set_view::CustomSetView;
722    /// # use linera_views::views::View;
723    /// # let context = MemoryContext::new_for_testing(());
724    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
725    /// set.remove(&(34 as u128));
726    /// assert_eq!(set.indices().await.unwrap().len(), 0);
727    /// # })
728    /// ```
729    pub fn remove<Q>(&mut self, index: &Q) -> Result<(), ViewError>
730    where
731        I: Borrow<Q>,
732        Q: CustomSerialize,
733    {
734        let short_key = index.to_custom_bytes()?;
735        self.set.remove(short_key);
736        Ok(())
737    }
738
739    /// Obtains the extra data.
740    pub fn extra(&self) -> &C::Extra {
741        self.set.extra()
742    }
743}
744
745impl<C, I> CustomSetView<C, I>
746where
747    C: Context,
748    I: CustomSerialize,
749{
750    /// Returns true if the given index exists in the set.
751    /// ```rust
752    /// # tokio_test::block_on(async {
753    /// # use linera_views::context::MemoryContext;
754    /// # use linera_views::set_view::CustomSetView;
755    /// # use linera_views::views::View;
756    /// # let context = MemoryContext::new_for_testing(());
757    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
758    /// set.insert(&(34 as u128));
759    /// assert_eq!(set.contains(&(34 as u128)).await.unwrap(), true);
760    /// assert_eq!(set.contains(&(37 as u128)).await.unwrap(), false);
761    /// # })
762    /// ```
763    pub async fn contains<Q>(&self, index: &Q) -> Result<bool, ViewError>
764    where
765        I: Borrow<Q>,
766        Q: CustomSerialize,
767    {
768        let short_key = index.to_custom_bytes()?;
769        self.set.contains(&short_key).await
770    }
771}
772
773impl<C, I> CustomSetView<C, I>
774where
775    C: Context,
776    I: Sync + Clone + Send + CustomSerialize,
777{
778    /// Returns the list of indices in the set. The order is determined by the custom
779    /// serialization.
780    /// ```rust
781    /// # tokio_test::block_on(async {
782    /// # use linera_views::context::MemoryContext;
783    /// # use linera_views::set_view::CustomSetView;
784    /// # use linera_views::views::View;
785    /// # let context = MemoryContext::new_for_testing(());
786    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
787    /// set.insert(&(34 as u128));
788    /// set.insert(&(37 as u128));
789    /// assert_eq!(set.indices().await.unwrap(), vec![34 as u128, 37 as u128]);
790    /// # })
791    /// ```
792    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
793        let mut indices = Vec::new();
794        self.for_each_index(|index| {
795            indices.push(index);
796            Ok(())
797        })
798        .await?;
799        Ok(indices)
800    }
801
802    /// Returns the number of entries of the set.
803    /// ```rust
804    /// # tokio_test::block_on(async {
805    /// # use linera_views::context::MemoryContext;
806    /// # use linera_views::set_view::CustomSetView;
807    /// # use linera_views::views::View;
808    /// # let context = MemoryContext::new_for_testing(());
809    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
810    /// set.insert(&(34 as u128));
811    /// set.insert(&(37 as u128));
812    /// assert_eq!(set.count().await.unwrap(), 2);
813    /// # })
814    /// ```
815    pub async fn count(&self) -> Result<usize, ViewError> {
816        self.set.count().await
817    }
818
819    /// Applies a function f on each index. Indices are visited in an order
820    /// determined by the custom serialization. If the function does return
821    /// false, then the loop prematurely ends.
822    /// ```rust
823    /// # tokio_test::block_on(async {
824    /// # use linera_views::context::MemoryContext;
825    /// # use linera_views::set_view::CustomSetView;
826    /// # use linera_views::views::View;
827    /// # let context = MemoryContext::new_for_testing(());
828    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
829    /// set.insert(&(34 as u128));
830    /// set.insert(&(37 as u128));
831    /// set.insert(&(42 as u128));
832    /// let mut count = 0;
833    /// set.for_each_index_while(|_key| {
834    ///     count += 1;
835    ///     Ok(count < 5)
836    /// })
837    /// .await
838    /// .unwrap();
839    /// assert_eq!(count, 3);
840    /// # })
841    /// ```
842    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
843    where
844        F: FnMut(I) -> Result<bool, ViewError> + Send,
845    {
846        self.set
847            .for_each_key_while(|key| {
848                let index = I::from_custom_bytes(key)?;
849                f(index)
850            })
851            .await?;
852        Ok(())
853    }
854
855    /// Applies a function f on each index. Indices are visited in an order
856    /// determined by the custom serialization.
857    /// ```rust
858    /// # tokio_test::block_on(async {
859    /// # use linera_views::context::MemoryContext;
860    /// # use linera_views::set_view::CustomSetView;
861    /// # use linera_views::views::View;
862    /// # let context = MemoryContext::new_for_testing(());
863    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
864    /// set.insert(&(34 as u128));
865    /// set.insert(&(37 as u128));
866    /// set.insert(&(42 as u128));
867    /// let mut count = 0;
868    /// set.for_each_index(|_key| {
869    ///     count += 1;
870    ///     Ok(())
871    /// })
872    /// .await
873    /// .unwrap();
874    /// assert_eq!(count, 3);
875    /// # })
876    /// ```
877    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
878    where
879        F: FnMut(I) -> Result<(), ViewError> + Send,
880    {
881        self.set
882            .for_each_key(|key| {
883                let index = I::from_custom_bytes(key)?;
884                f(index)
885            })
886            .await?;
887        Ok(())
888    }
889}
890
891impl<C: Context, I> HashableView for CustomSetView<C, I>
892where
893    Self: View,
894{
895    type Hasher = sha3::Sha3_256;
896
897    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
898        self.set.hash_mut().await
899    }
900
901    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
902        self.set.hash().await
903    }
904}
905
906/// Type wrapping `ByteSetView` while memoizing the hash.
907pub type HashedByteSetView<C> = WrappedHashableContainerView<C, ByteSetView<C>, HasherOutput>;
908
909/// Type wrapping `SetView` while memoizing the hash.
910pub type HashedSetView<C, I> = WrappedHashableContainerView<C, SetView<C, I>, HasherOutput>;
911
912/// Type wrapping `CustomSetView` while memoizing the hash.
913pub type HashedCustomSetView<C, I> =
914    WrappedHashableContainerView<C, CustomSetView<C, I>, HasherOutput>;
915
916#[cfg(with_graphql)]
917mod graphql {
918    use std::borrow::Cow;
919
920    use super::{CustomSetView, SetView};
921    use crate::context::Context;
922
923    impl<C: Context, I: async_graphql::OutputType> async_graphql::OutputType for SetView<C, I>
924    where
925        I: serde::ser::Serialize + serde::de::DeserializeOwned + Clone + Send + Sync,
926    {
927        fn type_name() -> Cow<'static, str> {
928            format!("[{}]", I::qualified_type_name()).into()
929        }
930
931        fn qualified_type_name() -> String {
932            format!("[{}]!", I::qualified_type_name())
933        }
934
935        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
936            I::create_type_info(registry);
937            Self::qualified_type_name()
938        }
939
940        async fn resolve(
941            &self,
942            ctx: &async_graphql::ContextSelectionSet<'_>,
943            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
944        ) -> async_graphql::ServerResult<async_graphql::Value> {
945            let indices = self
946                .indices()
947                .await
948                .map_err(|e| async_graphql::Error::from(e).into_server_error(ctx.item.pos))?;
949            let indices_len = indices.len();
950            async_graphql::resolver_utils::resolve_list(ctx, field, indices, Some(indices_len))
951                .await
952        }
953    }
954
955    impl<C: Context, I: async_graphql::OutputType> async_graphql::OutputType for CustomSetView<C, I>
956    where
957        I: crate::common::CustomSerialize + Clone + Send + Sync,
958    {
959        fn type_name() -> Cow<'static, str> {
960            format!("[{}]", I::qualified_type_name()).into()
961        }
962
963        fn qualified_type_name() -> String {
964            format!("[{}]!", I::qualified_type_name())
965        }
966
967        fn create_type_info(registry: &mut async_graphql::registry::Registry) -> String {
968            I::create_type_info(registry);
969            Self::qualified_type_name()
970        }
971
972        async fn resolve(
973            &self,
974            ctx: &async_graphql::ContextSelectionSet<'_>,
975            field: &async_graphql::Positioned<async_graphql::parser::types::Field>,
976        ) -> async_graphql::ServerResult<async_graphql::Value> {
977            let indices = self
978                .indices()
979                .await
980                .map_err(|e| async_graphql::Error::from(e).into_server_error(ctx.item.pos))?;
981            let indices_len = indices.len();
982            async_graphql::resolver_utils::resolve_list(ctx, field, indices, Some(indices_len))
983                .await
984        }
985    }
986}