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