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}