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}