Skip to main content

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};
5
6use allocative::Allocative;
7#[cfg(with_metrics)]
8use linera_base::prometheus_util::MeasureLatency as _;
9use serde::{de::DeserializeOwned, Serialize};
10
11use crate::{
12    batch::Batch,
13    common::{CustomSerialize, HasherOutput, Update},
14    context::{BaseKey, Context},
15    hashable_wrapper::WrappedHashableContainerView,
16    historical_hash_wrapper::HistoricallyHashableView,
17    store::ReadableKeyValueStore as _,
18    views::{ClonableView, HashableView, Hasher, ReplaceContext, View, ViewError},
19};
20
21#[cfg(with_metrics)]
22pub(crate) mod metrics {
23    use linera_base::prometheus_util::{exponential_bucket_latencies, register_histogram_vec};
24    use prometheus::HistogramVec;
25
26    linera_base::declare_metrics! {
27        /// The runtime of hash computation
28        pub static SET_VIEW_HASH_RUNTIME: HistogramVec =
29            register_histogram_vec(
30                "set_view_hash_runtime",
31                "SetView hash runtime",
32                &[],
33                exponential_bucket_latencies(5.0),
34            );
35    }
36}
37
38/// A [`View`] that supports inserting and removing values indexed by a key.
39#[derive(Debug, Allocative)]
40#[allocative(bound = "C")]
41pub struct ByteSetView<C> {
42    /// The view context.
43    #[allocative(skip)]
44    context: C,
45    /// Whether to clear storage before applying updates.
46    delete_storage_first: bool,
47    /// Pending changes not yet persisted to storage.
48    updates: BTreeMap<Vec<u8>, Update<()>>,
49}
50
51impl<C: Context, C2: Context> ReplaceContext<C2> for ByteSetView<C> {
52    type Target = ByteSetView<C2>;
53
54    async fn with_context(
55        &mut self,
56        ctx: impl FnOnce(&Self::Context) -> C2 + Clone,
57    ) -> Self::Target {
58        ByteSetView {
59            context: ctx(&self.context),
60            delete_storage_first: self.delete_storage_first,
61            updates: self.updates.clone(),
62        }
63    }
64}
65
66impl<C: Context> View for ByteSetView<C> {
67    const NUM_INIT_KEYS: usize = 0;
68
69    type Context = C;
70
71    fn context(&self) -> C {
72        self.context.clone()
73    }
74
75    fn pre_load(_context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
76        Ok(Vec::new())
77    }
78
79    fn post_load(context: C, _values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
80        Ok(Self {
81            context,
82            delete_storage_first: false,
83            updates: BTreeMap::new(),
84        })
85    }
86
87    fn rollback(&mut self) {
88        self.delete_storage_first = false;
89        self.updates.clear();
90    }
91
92    async fn has_pending_changes(&self) -> bool {
93        if self.delete_storage_first {
94            return true;
95        }
96        !self.updates.is_empty()
97    }
98
99    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
100        let mut delete_view = false;
101        if self.delete_storage_first {
102            delete_view = true;
103            batch.delete_key_prefix(self.context.base_key().bytes.clone());
104            for (index, update) in self.updates.iter() {
105                if let Update::Set(_) = update {
106                    let key = self.context.base_key().base_index(index);
107                    batch.put_key_value_bytes(key, Vec::new());
108                    delete_view = false;
109                }
110            }
111        } else {
112            for (index, update) in self.updates.iter() {
113                let key = self.context.base_key().base_index(index);
114                match update {
115                    Update::Removed => batch.delete_key(key),
116                    Update::Set(_) => batch.put_key_value_bytes(key, Vec::new()),
117                }
118            }
119        }
120        Ok(delete_view)
121    }
122
123    fn post_save(&mut self) {
124        self.delete_storage_first = false;
125        self.updates.clear();
126    }
127
128    fn clear(&mut self) {
129        self.delete_storage_first = true;
130        self.updates.clear();
131    }
132}
133
134impl<C: Context> ClonableView for ByteSetView<C> {
135    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
136        Ok(ByteSetView {
137            context: self.context.clone(),
138            delete_storage_first: self.delete_storage_first,
139            updates: self.updates.clone(),
140        })
141    }
142}
143
144impl<C: Context> ByteSetView<C> {
145    /// Inserts a value. If already present then it has no effect.
146    /// ```rust
147    /// # tokio_test::block_on(async {
148    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
149    /// # use linera_views::views::View;
150    /// # let context = MemoryContext::new_for_testing(());
151    /// let mut set = ByteSetView::load(context).await.unwrap();
152    /// set.insert(vec![0, 1]);
153    /// assert_eq!(set.contains(&[0, 1]).await.unwrap(), true);
154    /// # })
155    /// ```
156    pub fn insert(&mut self, short_key: Vec<u8>) {
157        self.updates.insert(short_key, Update::Set(()));
158    }
159
160    /// Removes a value from the set. If absent then no effect.
161    /// ```rust
162    /// # tokio_test::block_on(async {
163    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
164    /// # use linera_views::views::View;
165    /// # let context = MemoryContext::new_for_testing(());
166    /// let mut set = ByteSetView::load(context).await.unwrap();
167    /// set.remove(vec![0, 1]);
168    /// assert_eq!(set.contains(&[0, 1]).await.unwrap(), false);
169    /// # })
170    /// ```
171    pub fn remove(&mut self, short_key: Vec<u8>) {
172        if self.delete_storage_first {
173            // Optimization: No need to mark `short_key` for deletion as we are going to remove all the keys at once.
174            self.updates.remove(&short_key);
175        } else {
176            self.updates.insert(short_key, Update::Removed);
177        }
178    }
179
180    /// Gets the extra data.
181    pub fn extra(&self) -> &C::Extra {
182        self.context.extra()
183    }
184}
185
186impl<C: Context> ByteSetView<C> {
187    /// Returns true if the given index exists in the set.
188    /// ```rust
189    /// # tokio_test::block_on(async {
190    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
191    /// # use linera_views::views::View;
192    /// # let context = MemoryContext::new_for_testing(());
193    /// let mut set = ByteSetView::load(context).await.unwrap();
194    /// set.insert(vec![0, 1]);
195    /// assert_eq!(set.contains(&[34]).await.unwrap(), false);
196    /// assert_eq!(set.contains(&[0, 1]).await.unwrap(), true);
197    /// # })
198    /// ```
199    pub async fn contains(&self, short_key: &[u8]) -> Result<bool, ViewError> {
200        if let Some(update) = self.updates.get(short_key) {
201            let value = match update {
202                Update::Removed => false,
203                Update::Set(()) => true,
204            };
205            return Ok(value);
206        }
207        if self.delete_storage_first {
208            return Ok(false);
209        }
210        let key = self.context.base_key().base_index(short_key);
211        Ok(self.context.store().contains_key(&key).await?)
212    }
213}
214
215impl<C: Context> ByteSetView<C> {
216    /// Returns the list of keys in the set. The order is lexicographic.
217    /// ```rust
218    /// # tokio_test::block_on(async {
219    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
220    /// # use linera_views::views::View;
221    /// # let context = MemoryContext::new_for_testing(());
222    /// let mut set = ByteSetView::load(context).await.unwrap();
223    /// set.insert(vec![0, 1]);
224    /// set.insert(vec![0, 2]);
225    /// assert_eq!(set.keys().await.unwrap(), vec![vec![0, 1], vec![0, 2]]);
226    /// # })
227    /// ```
228    pub async fn keys(&self) -> Result<Vec<Vec<u8>>, ViewError> {
229        let mut keys = Vec::new();
230        self.for_each_key(|key| {
231            keys.push(key.to_vec());
232            Ok(())
233        })
234        .await?;
235        Ok(keys)
236    }
237
238    /// Returns the number of entries in the set.
239    /// ```rust
240    /// # tokio_test::block_on(async {
241    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
242    /// # use linera_views::views::View;
243    /// # let context = MemoryContext::new_for_testing(());
244    /// let mut set = ByteSetView::load(context).await.unwrap();
245    /// set.insert(vec![0, 1]);
246    /// set.insert(vec![0, 2]);
247    /// assert_eq!(set.keys().await.unwrap(), vec![vec![0, 1], vec![0, 2]]);
248    /// # })
249    /// ```
250    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
251        let mut count = 0;
252        self.for_each_key(|_key| {
253            count += 1;
254            Ok(())
255        })
256        .await?;
257        Ok(count)
258    }
259
260    /// Applies a function f on each index (aka key). Keys are visited in a
261    /// lexicographic order. If the function returns false, then the loop ends
262    /// prematurely.
263    /// ```rust
264    /// # tokio_test::block_on(async {
265    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
266    /// # use linera_views::views::View;
267    /// # let context = MemoryContext::new_for_testing(());
268    /// let mut set = ByteSetView::load(context).await.unwrap();
269    /// set.insert(vec![0, 1]);
270    /// set.insert(vec![0, 2]);
271    /// set.insert(vec![3]);
272    /// let mut count = 0;
273    /// set.for_each_key_while(|_key| {
274    ///     count += 1;
275    ///     Ok(count < 2)
276    /// })
277    /// .await
278    /// .unwrap();
279    /// assert_eq!(count, 2);
280    /// # })
281    /// ```
282    pub async fn for_each_key_while<F>(&self, mut f: F) -> Result<(), ViewError>
283    where
284        F: FnMut(&[u8]) -> Result<bool, ViewError> + Send,
285    {
286        let mut updates = self.updates.iter();
287        let mut update = updates.next();
288        if !self.delete_storage_first {
289            let base = &self.context.base_key().bytes;
290            for index in self.context.store().find_keys_by_prefix(base).await? {
291                loop {
292                    match update {
293                        Some((key, value)) if key <= &index => {
294                            if let Update::Set(_) = value {
295                                if !f(key)? {
296                                    return Ok(());
297                                }
298                            }
299                            update = updates.next();
300                            if key == &index {
301                                break;
302                            }
303                        }
304                        _ => {
305                            if !f(&index)? {
306                                return Ok(());
307                            }
308                            break;
309                        }
310                    }
311                }
312            }
313        }
314        while let Some((key, value)) = update {
315            if let Update::Set(_) = value {
316                if !f(key)? {
317                    return Ok(());
318                }
319            }
320            update = updates.next();
321        }
322        Ok(())
323    }
324
325    /// Applies a function f on each serialized index (aka key). Keys are visited in a
326    /// lexicographic order.
327    /// ```rust
328    /// # tokio_test::block_on(async {
329    /// # use linera_views::{context::MemoryContext, set_view::ByteSetView};
330    /// # use linera_views::views::View;
331    /// # let context = MemoryContext::new_for_testing(());
332    /// let mut set = ByteSetView::load(context).await.unwrap();
333    /// set.insert(vec![0, 1]);
334    /// set.insert(vec![0, 2]);
335    /// set.insert(vec![3]);
336    /// let mut count = 0;
337    /// set.for_each_key(|_key| {
338    ///     count += 1;
339    ///     Ok(())
340    /// })
341    /// .await
342    /// .unwrap();
343    /// assert_eq!(count, 3);
344    /// # })
345    /// ```
346    pub async fn for_each_key<F>(&self, mut f: F) -> Result<(), ViewError>
347    where
348        F: FnMut(&[u8]) -> Result<(), ViewError> + Send,
349    {
350        self.for_each_key_while(|key| {
351            f(key)?;
352            Ok(true)
353        })
354        .await
355    }
356}
357
358impl<C: Context> HashableView for ByteSetView<C> {
359    type Hasher = sha3::Sha3_256;
360
361    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
362        self.hash().await
363    }
364
365    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
366        #[cfg(with_metrics)]
367        let _hash_latency = metrics::SET_VIEW_HASH_RUNTIME.measure_latency();
368        let mut hasher = sha3::Sha3_256::default();
369        let mut count = 0u32;
370        self.for_each_key(|key| {
371            count += 1;
372            hasher.update_with_bytes(key)?;
373            Ok(())
374        })
375        .await?;
376        hasher.update_with_bcs_bytes(&count)?;
377        Ok(hasher.finalize())
378    }
379}
380
381/// A [`View`] implementing the set functionality with the index `I` being any serializable type.
382#[derive(Debug, Allocative)]
383#[allocative(bound = "C, I")]
384pub struct SetView<C, I> {
385    /// The underlying set storing entries with serialized keys.
386    set: ByteSetView<C>,
387    /// Phantom data for the key type.
388    #[allocative(skip)]
389    _phantom: PhantomData<I>,
390}
391
392impl<C: Context, I: Send + Sync + Serialize, C2: Context> ReplaceContext<C2> for SetView<C, I> {
393    type Target = SetView<C2, I>;
394
395    async fn with_context(
396        &mut self,
397        ctx: impl FnOnce(&Self::Context) -> C2 + Clone,
398    ) -> Self::Target {
399        SetView {
400            set: self.set.with_context(ctx).await,
401            _phantom: self._phantom,
402        }
403    }
404}
405
406impl<C: Context, I: Send + Sync + Serialize> View for SetView<C, I> {
407    const NUM_INIT_KEYS: usize = ByteSetView::<C>::NUM_INIT_KEYS;
408
409    type Context = C;
410
411    fn context(&self) -> C {
412        self.set.context()
413    }
414
415    fn pre_load(context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
416        ByteSetView::<C>::pre_load(context)
417    }
418
419    fn post_load(context: C, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
420        let set = ByteSetView::post_load(context, values)?;
421        Ok(Self {
422            set,
423            _phantom: PhantomData,
424        })
425    }
426
427    fn rollback(&mut self) {
428        self.set.rollback()
429    }
430
431    async fn has_pending_changes(&self) -> bool {
432        self.set.has_pending_changes().await
433    }
434
435    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
436        self.set.pre_save(batch)
437    }
438
439    fn post_save(&mut self) {
440        self.set.post_save()
441    }
442
443    fn clear(&mut self) {
444        self.set.clear()
445    }
446}
447
448impl<C, I> ClonableView for SetView<C, I>
449where
450    C: Context,
451    I: Send + Sync + Serialize,
452{
453    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
454        Ok(SetView {
455            set: self.set.clone_unchecked()?,
456            _phantom: PhantomData,
457        })
458    }
459}
460
461impl<C: Context, I: Serialize> SetView<C, I> {
462    /// Inserts a value. If already present then no effect.
463    /// ```rust
464    /// # tokio_test::block_on(async {
465    /// # use linera_views::context::MemoryContext;
466    /// # use linera_views::set_view::SetView;
467    /// # use linera_views::views::View;
468    /// # let context = MemoryContext::new_for_testing(());
469    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
470    /// set.insert(&(34 as u32));
471    /// assert_eq!(set.indices().await.unwrap().len(), 1);
472    /// # })
473    /// ```
474    pub fn insert<Q>(&mut self, index: &Q) -> Result<(), ViewError>
475    where
476        I: Borrow<Q>,
477        Q: Serialize + ?Sized,
478    {
479        let short_key = BaseKey::derive_short_key(index)?;
480        self.set.insert(short_key);
481        Ok(())
482    }
483
484    /// Removes a value. If absent then nothing is done.
485    /// ```rust
486    /// # tokio_test::block_on(async {
487    /// # use linera_views::{context::MemoryContext, set_view::SetView};
488    /// # use linera_views::views::View;
489    /// # let context = MemoryContext::new_for_testing(());
490    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
491    /// set.remove(&(34 as u32));
492    /// assert_eq!(set.indices().await.unwrap().len(), 0);
493    /// # })
494    /// ```
495    pub fn remove<Q>(&mut self, index: &Q) -> Result<(), ViewError>
496    where
497        I: Borrow<Q>,
498        Q: Serialize + ?Sized,
499    {
500        let short_key = BaseKey::derive_short_key(index)?;
501        self.set.remove(short_key);
502        Ok(())
503    }
504
505    /// Obtains the extra data.
506    pub fn extra(&self) -> &C::Extra {
507        self.set.extra()
508    }
509}
510
511impl<C: Context, I: Serialize> SetView<C, I> {
512    /// Returns true if the given index exists in the set.
513    /// ```rust
514    /// # tokio_test::block_on(async {
515    /// # use linera_views::{context::MemoryContext, set_view::SetView};
516    /// # use linera_views::views::View;
517    /// # let context = MemoryContext::new_for_testing(());
518    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
519    /// set.insert(&(34 as u32));
520    /// assert_eq!(set.contains(&(34 as u32)).await.unwrap(), true);
521    /// assert_eq!(set.contains(&(45 as u32)).await.unwrap(), false);
522    /// # })
523    /// ```
524    pub async fn contains<Q>(&self, index: &Q) -> Result<bool, ViewError>
525    where
526        I: Borrow<Q>,
527        Q: Serialize + ?Sized,
528    {
529        let short_key = BaseKey::derive_short_key(index)?;
530        self.set.contains(&short_key).await
531    }
532}
533
534impl<C: Context, I: Serialize + DeserializeOwned + Send> SetView<C, I> {
535    /// Returns the list of indices in the set. The order is determined by serialization.
536    /// ```rust
537    /// # tokio_test::block_on(async {
538    /// # use linera_views::{context::MemoryContext, set_view::SetView};
539    /// # use linera_views::views::View;
540    /// # let context = MemoryContext::new_for_testing(());
541    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
542    /// set.insert(&(34 as u32));
543    /// assert_eq!(set.indices().await.unwrap(), vec![34 as u32]);
544    /// # })
545    /// ```
546    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
547        let mut indices = Vec::new();
548        self.for_each_index(|index| {
549            indices.push(index);
550            Ok(())
551        })
552        .await?;
553        Ok(indices)
554    }
555
556    /// Returns the number of entries in the set.
557    /// ```rust
558    /// # tokio_test::block_on(async {
559    /// # use linera_views::{context::MemoryContext, set_view::SetView};
560    /// # use linera_views::views::View;
561    /// # let context = MemoryContext::new_for_testing(());
562    /// let mut set: SetView<_, u32> = SetView::load(context).await.unwrap();
563    /// set.insert(&(34 as u32));
564    /// assert_eq!(set.iterative_count().await.unwrap(), 1);
565    /// # })
566    /// ```
567    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
568        self.set.iterative_count().await
569    }
570
571    /// Applies a function f on each index. Indices are visited in an order
572    /// determined by the serialization. If the function returns false, then the
573    /// loop ends prematurely.
574    /// ```rust
575    /// # tokio_test::block_on(async {
576    /// # use linera_views::context::MemoryContext;
577    /// # use linera_views::set_view::SetView;
578    /// # use linera_views::views::View;
579    /// # let context = MemoryContext::new_for_testing(());
580    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
581    /// set.insert(&(34 as u32));
582    /// set.insert(&(37 as u32));
583    /// set.insert(&(42 as u32));
584    /// let mut count = 0;
585    /// set.for_each_index_while(|_key| {
586    ///     count += 1;
587    ///     Ok(count < 2)
588    /// })
589    /// .await
590    /// .unwrap();
591    /// assert_eq!(count, 2);
592    /// # })
593    /// ```
594    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
595    where
596        F: FnMut(I) -> Result<bool, ViewError> + Send,
597    {
598        self.set
599            .for_each_key_while(|key| {
600                let index = BaseKey::deserialize_value(key)?;
601                f(index)
602            })
603            .await?;
604        Ok(())
605    }
606
607    /// Applies a function f on each index. Indices are visited in an order
608    /// determined by the serialization.
609    /// ```rust
610    /// # tokio_test::block_on(async {
611    /// # use linera_views::context::MemoryContext;
612    /// # use linera_views::set_view::SetView;
613    /// # use linera_views::views::View;
614    /// # let context = MemoryContext::new_for_testing(());
615    /// let mut set = SetView::<_, u32>::load(context).await.unwrap();
616    /// set.insert(&(34 as u32));
617    /// set.insert(&(37 as u32));
618    /// set.insert(&(42 as u32));
619    /// let mut count = 0;
620    /// set.for_each_index(|_key| {
621    ///     count += 1;
622    ///     Ok(())
623    /// })
624    /// .await
625    /// .unwrap();
626    /// assert_eq!(count, 3);
627    /// # })
628    /// ```
629    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
630    where
631        F: FnMut(I) -> Result<(), ViewError> + Send,
632    {
633        self.set
634            .for_each_key(|key| {
635                let index = BaseKey::deserialize_value(key)?;
636                f(index)
637            })
638            .await?;
639        Ok(())
640    }
641}
642
643impl<C, I> HashableView for SetView<C, I>
644where
645    Self: View,
646    ByteSetView<C>: HashableView,
647{
648    type Hasher = <ByteSetView<C> as HashableView>::Hasher;
649
650    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
651        self.set.hash_mut().await
652    }
653
654    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
655        self.set.hash().await
656    }
657}
658
659/// A [`View`] implementing the set functionality with the index `I` being a type with a custom
660/// serialization format.
661#[derive(Debug, Allocative)]
662#[allocative(bound = "C, I")]
663pub struct CustomSetView<C, I> {
664    /// The underlying set storing entries with custom-serialized keys.
665    set: ByteSetView<C>,
666    /// Phantom data for the key type.
667    #[allocative(skip)]
668    _phantom: PhantomData<I>,
669}
670
671impl<C, I> View for CustomSetView<C, I>
672where
673    C: Context,
674    I: Send + Sync + CustomSerialize,
675{
676    const NUM_INIT_KEYS: usize = ByteSetView::<C>::NUM_INIT_KEYS;
677
678    type Context = C;
679
680    fn context(&self) -> C {
681        self.set.context()
682    }
683
684    fn pre_load(context: &C) -> Result<Vec<Vec<u8>>, ViewError> {
685        ByteSetView::pre_load(context)
686    }
687
688    fn post_load(context: C, values: &[Option<Vec<u8>>]) -> Result<Self, ViewError> {
689        let set = ByteSetView::post_load(context, values)?;
690        Ok(Self {
691            set,
692            _phantom: PhantomData,
693        })
694    }
695
696    fn rollback(&mut self) {
697        self.set.rollback()
698    }
699
700    async fn has_pending_changes(&self) -> bool {
701        self.set.has_pending_changes().await
702    }
703
704    fn pre_save(&self, batch: &mut Batch) -> Result<bool, ViewError> {
705        self.set.pre_save(batch)
706    }
707
708    fn post_save(&mut self) {
709        self.set.post_save()
710    }
711
712    fn clear(&mut self) {
713        self.set.clear()
714    }
715}
716
717impl<C, I> ClonableView for CustomSetView<C, I>
718where
719    C: Context,
720    I: Send + Sync + CustomSerialize,
721{
722    fn clone_unchecked(&mut self) -> Result<Self, ViewError> {
723        Ok(CustomSetView {
724            set: self.set.clone_unchecked()?,
725            _phantom: PhantomData,
726        })
727    }
728}
729
730impl<C: Context, I: CustomSerialize> CustomSetView<C, I> {
731    /// Inserts a value. If present then it has no effect.
732    /// ```rust
733    /// # tokio_test::block_on(async {
734    /// # use linera_views::context::MemoryContext;
735    /// # use linera_views::set_view::CustomSetView;
736    /// # use linera_views::views::View;
737    /// # let context = MemoryContext::new_for_testing(());
738    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
739    /// set.insert(&(34 as u128));
740    /// assert_eq!(set.indices().await.unwrap().len(), 1);
741    /// # })
742    /// ```
743    pub fn insert<Q>(&mut self, index: &Q) -> Result<(), ViewError>
744    where
745        I: Borrow<Q>,
746        Q: CustomSerialize,
747    {
748        let short_key = index.to_custom_bytes()?;
749        self.set.insert(short_key);
750        Ok(())
751    }
752
753    /// Removes a value. If absent then nothing is done.
754    /// ```rust
755    /// # tokio_test::block_on(async {
756    /// # use linera_views::context::MemoryContext;
757    /// # use linera_views::set_view::CustomSetView;
758    /// # use linera_views::views::View;
759    /// # let context = MemoryContext::new_for_testing(());
760    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
761    /// set.remove(&(34 as u128));
762    /// assert_eq!(set.indices().await.unwrap().len(), 0);
763    /// # })
764    /// ```
765    pub fn remove<Q>(&mut self, index: &Q) -> Result<(), ViewError>
766    where
767        I: Borrow<Q>,
768        Q: CustomSerialize,
769    {
770        let short_key = index.to_custom_bytes()?;
771        self.set.remove(short_key);
772        Ok(())
773    }
774
775    /// Obtains the extra data.
776    pub fn extra(&self) -> &C::Extra {
777        self.set.extra()
778    }
779}
780
781impl<C, I> CustomSetView<C, I>
782where
783    C: Context,
784    I: CustomSerialize,
785{
786    /// Returns true if the given index exists in the set.
787    /// ```rust
788    /// # tokio_test::block_on(async {
789    /// # use linera_views::context::MemoryContext;
790    /// # use linera_views::set_view::CustomSetView;
791    /// # use linera_views::views::View;
792    /// # let context = MemoryContext::new_for_testing(());
793    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
794    /// set.insert(&(34 as u128));
795    /// assert_eq!(set.contains(&(34 as u128)).await.unwrap(), true);
796    /// assert_eq!(set.contains(&(37 as u128)).await.unwrap(), false);
797    /// # })
798    /// ```
799    pub async fn contains<Q>(&self, index: &Q) -> Result<bool, ViewError>
800    where
801        I: Borrow<Q>,
802        Q: CustomSerialize,
803    {
804        let short_key = index.to_custom_bytes()?;
805        self.set.contains(&short_key).await
806    }
807}
808
809impl<C, I> CustomSetView<C, I>
810where
811    C: Context,
812    I: Sync + Send + CustomSerialize,
813{
814    /// Returns the list of indices in the set. The order is determined by the custom
815    /// serialization.
816    /// ```rust
817    /// # tokio_test::block_on(async {
818    /// # use linera_views::context::MemoryContext;
819    /// # use linera_views::set_view::CustomSetView;
820    /// # use linera_views::views::View;
821    /// # let context = MemoryContext::new_for_testing(());
822    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
823    /// set.insert(&(34 as u128));
824    /// set.insert(&(37 as u128));
825    /// assert_eq!(set.indices().await.unwrap(), vec![34 as u128, 37 as u128]);
826    /// # })
827    /// ```
828    pub async fn indices(&self) -> Result<Vec<I>, ViewError> {
829        let mut indices = Vec::new();
830        self.for_each_index(|index| {
831            indices.push(index);
832            Ok(())
833        })
834        .await?;
835        Ok(indices)
836    }
837
838    /// Returns the number of entries of the set.
839    /// ```rust
840    /// # tokio_test::block_on(async {
841    /// # use linera_views::context::MemoryContext;
842    /// # use linera_views::set_view::CustomSetView;
843    /// # use linera_views::views::View;
844    /// # let context = MemoryContext::new_for_testing(());
845    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
846    /// set.insert(&(34 as u128));
847    /// set.insert(&(37 as u128));
848    /// assert_eq!(set.iterative_count().await.unwrap(), 2);
849    /// # })
850    /// ```
851    pub async fn iterative_count(&self) -> Result<usize, ViewError> {
852        self.set.iterative_count().await
853    }
854
855    /// Applies a function f on each index. Indices are visited in an order
856    /// determined by the custom serialization. If the function does return
857    /// false, then the loop prematurely ends.
858    /// ```rust
859    /// # tokio_test::block_on(async {
860    /// # use linera_views::context::MemoryContext;
861    /// # use linera_views::set_view::CustomSetView;
862    /// # use linera_views::views::View;
863    /// # let context = MemoryContext::new_for_testing(());
864    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
865    /// set.insert(&(34 as u128));
866    /// set.insert(&(37 as u128));
867    /// set.insert(&(42 as u128));
868    /// let mut count = 0;
869    /// set.for_each_index_while(|_key| {
870    ///     count += 1;
871    ///     Ok(count < 5)
872    /// })
873    /// .await
874    /// .unwrap();
875    /// assert_eq!(count, 3);
876    /// # })
877    /// ```
878    pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
879    where
880        F: FnMut(I) -> Result<bool, ViewError> + Send,
881    {
882        self.set
883            .for_each_key_while(|key| {
884                let index = I::from_custom_bytes(key)?;
885                f(index)
886            })
887            .await?;
888        Ok(())
889    }
890
891    /// Applies a function f on each index. Indices are visited in an order
892    /// determined by the custom serialization.
893    /// ```rust
894    /// # tokio_test::block_on(async {
895    /// # use linera_views::context::MemoryContext;
896    /// # use linera_views::set_view::CustomSetView;
897    /// # use linera_views::views::View;
898    /// # let context = MemoryContext::new_for_testing(());
899    /// let mut set = CustomSetView::<_, u128>::load(context).await.unwrap();
900    /// set.insert(&(34 as u128));
901    /// set.insert(&(37 as u128));
902    /// set.insert(&(42 as u128));
903    /// let mut count = 0;
904    /// set.for_each_index(|_key| {
905    ///     count += 1;
906    ///     Ok(())
907    /// })
908    /// .await
909    /// .unwrap();
910    /// assert_eq!(count, 3);
911    /// # })
912    /// ```
913    pub async fn for_each_index<F>(&self, mut f: F) -> Result<(), ViewError>
914    where
915        F: FnMut(I) -> Result<(), ViewError> + Send,
916    {
917        self.set
918            .for_each_key(|key| {
919                let index = I::from_custom_bytes(key)?;
920                f(index)
921            })
922            .await?;
923        Ok(())
924    }
925}
926
927impl<C: Context, I> HashableView for CustomSetView<C, I>
928where
929    Self: View,
930{
931    type Hasher = sha3::Sha3_256;
932
933    async fn hash_mut(&mut self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
934        self.set.hash_mut().await
935    }
936
937    async fn hash(&self) -> Result<<Self::Hasher as Hasher>::Output, ViewError> {
938        self.set.hash().await
939    }
940}
941
942/// Type wrapping `ByteSetView` while memoizing the hash.
943pub type HashedByteSetView<C> = WrappedHashableContainerView<C, ByteSetView<C>, HasherOutput>;
944
945/// Wrapper around `ByteSetView` to compute hashes based on the history of changes.
946pub type HistoricallyHashedByteSetView<C> = HistoricallyHashableView<C, ByteSetView<C>>;
947
948/// Type wrapping `SetView` while memoizing the hash.
949pub type HashedSetView<C, I> = WrappedHashableContainerView<C, SetView<C, I>, HasherOutput>;
950
951/// Wrapper around `SetView` to compute hashes based on the history of changes.
952pub type HistoricallyHashedSetView<C, I> = HistoricallyHashableView<C, SetView<C, I>>;
953
954/// Type wrapping `CustomSetView` while memoizing the hash.
955pub type HashedCustomSetView<C, I> =
956    WrappedHashableContainerView<C, CustomSetView<C, I>, HasherOutput>;
957
958/// Wrapper around `CustomSetView` to compute hashes based on the history of changes.
959pub type HistoricallyHashedCustomSetView<C, I> = HistoricallyHashableView<C, CustomSetView<C, I>>;
960
961#[cfg(with_graphql)]
962mod graphql {
963    use std::borrow::Cow;
964
965    use serde::{de::DeserializeOwned, Serialize};
966
967    use super::{CustomSetView, SetView};
968    use crate::{
969        common::CustomSerialize,
970        context::Context,
971        graphql::{hash_name, mangle},
972    };
973
974    impl<C: Send + Sync, I: async_graphql::OutputType> async_graphql::TypeName for SetView<C, I> {
975        fn type_name() -> Cow<'static, str> {
976            format!(
977                "SetView_{}_{:08x}",
978                mangle(I::type_name()),
979                hash_name::<I>(),
980            )
981            .into()
982        }
983    }
984
985    #[async_graphql::Object(cache_control(no_cache), name_type)]
986    impl<C, I> SetView<C, I>
987    where
988        C: Context,
989        I: Send + Sync + Serialize + DeserializeOwned + async_graphql::OutputType,
990    {
991        async fn elements(&self, count: Option<usize>) -> Result<Vec<I>, async_graphql::Error> {
992            let mut indices = self.indices().await?;
993            if let Some(count) = count {
994                indices.truncate(count);
995            }
996            Ok(indices)
997        }
998
999        #[graphql(derived(name = "count"))]
1000        async fn count_(&self) -> Result<u32, async_graphql::Error> {
1001            let count = self.iterative_count().await?;
1002            u32::try_from(count).map_err(|_| async_graphql::Error::new("count exceeds u32"))
1003        }
1004    }
1005
1006    impl<C: Send + Sync, I: async_graphql::OutputType> async_graphql::TypeName for CustomSetView<C, I> {
1007        fn type_name() -> Cow<'static, str> {
1008            format!(
1009                "CustomSetView_{}_{:08x}",
1010                mangle(I::type_name()),
1011                hash_name::<I>(),
1012            )
1013            .into()
1014        }
1015    }
1016
1017    #[async_graphql::Object(cache_control(no_cache), name_type)]
1018    impl<C, I> CustomSetView<C, I>
1019    where
1020        C: Context,
1021        I: Send + Sync + CustomSerialize + async_graphql::OutputType,
1022    {
1023        async fn elements(&self, count: Option<usize>) -> Result<Vec<I>, async_graphql::Error> {
1024            let mut indices = self.indices().await?;
1025            if let Some(count) = count {
1026                indices.truncate(count);
1027            }
1028            Ok(indices)
1029        }
1030
1031        #[graphql(derived(name = "count"))]
1032        async fn count_(&self) -> Result<u32, async_graphql::Error> {
1033            let count = self.iterative_count().await?;
1034            u32::try_from(count).map_err(|_| async_graphql::Error::new("count exceeds u32"))
1035        }
1036    }
1037}
1038
1039#[cfg(test)]
1040mod tests {
1041    use super::*;
1042    use crate::{context::MemoryContext, store::WritableKeyValueStore as _};
1043
1044    #[tokio::test]
1045    async fn test_byte_set_view_flush_with_delete_storage_first_and_set_updates(
1046    ) -> Result<(), ViewError> {
1047        let context = MemoryContext::new_for_testing(());
1048        let mut set = ByteSetView::load(context).await?;
1049        // Initially should have no pending changes
1050        assert!(!set.has_pending_changes().await);
1051
1052        // First, add some initial data to storage
1053        set.insert(vec![1, 2, 3]);
1054        set.insert(vec![4, 5, 6]);
1055        // Should have pending changes after inserts
1056        assert!(set.has_pending_changes().await);
1057
1058        // Check keys before flush
1059        assert_eq!(set.keys().await?, vec![vec![1, 2, 3], vec![4, 5, 6]]);
1060
1061        let mut batch = Batch::new();
1062        set.pre_save(&mut batch)?;
1063        set.context().store().write_batch(batch).await?;
1064        set.post_save();
1065        // Should have no pending changes after flush
1066        assert!(!set.has_pending_changes().await);
1067
1068        // Check keys after flush
1069        assert_eq!(set.keys().await?, vec![vec![1, 2, 3], vec![4, 5, 6]]);
1070        assert_eq!(set.iterative_count().await?, 2);
1071
1072        // Now clear the set (this sets delete_storage_first = true)
1073        set.clear();
1074        // Should have pending changes after clear
1075        assert!(set.has_pending_changes().await);
1076
1077        // After clear, keys should be empty
1078        assert!(set.keys().await?.is_empty());
1079
1080        // Add new items after clearing - this creates Update::Set entries
1081        set.insert(vec![7, 8, 9]);
1082        set.insert(vec![10, 11, 12]);
1083        // Should still have pending changes
1084        assert!(set.has_pending_changes().await);
1085
1086        // Check keys after adding new items
1087        assert_eq!(set.keys().await?, vec![vec![7, 8, 9], vec![10, 11, 12]]);
1088
1089        // Create a new batch and flush
1090        let mut batch = Batch::new();
1091        let delete_view = set.pre_save(&mut batch)?;
1092        // The key assertion: delete_view should be false because we had Update::Set entries
1093        // This tests line 103: if let Update::Set(_) = update { ... delete_view = false; }
1094        assert!(!delete_view);
1095        // Verify the batch contains the expected operations
1096        assert!(!batch.is_empty());
1097
1098        // Write the batch and verify the final state
1099        set.context().store().write_batch(batch).await?;
1100        set.post_save();
1101        // Should have no pending changes after final flush
1102        assert!(!set.has_pending_changes().await);
1103
1104        // Reload and verify only the new items exist
1105        let new_set = ByteSetView::load(set.context().clone()).await?;
1106        assert!(new_set.contains(&[7, 8, 9]).await?);
1107        assert!(new_set.contains(&[10, 11, 12]).await?);
1108        assert!(!new_set.contains(&[1, 2, 3]).await?);
1109        assert!(!new_set.contains(&[4, 5, 6]).await?);
1110        // New set should have no pending changes
1111        assert!(!new_set.has_pending_changes().await);
1112
1113        Ok(())
1114    }
1115
1116    #[tokio::test]
1117    async fn test_byte_set_view_flush_with_delete_storage_first_no_set_updates(
1118    ) -> Result<(), ViewError> {
1119        let context = MemoryContext::new_for_testing(());
1120        let mut set = ByteSetView::load(context).await?;
1121
1122        // Add some initial data
1123        set.insert(vec![1, 2, 3]);
1124        let mut batch = Batch::new();
1125        set.pre_save(&mut batch)?;
1126        set.context().store().write_batch(batch).await?;
1127        set.post_save();
1128
1129        // Clear the set and flush without adding anything back
1130        set.clear();
1131        let mut batch = Batch::new();
1132        let delete_view = set.pre_save(&mut batch)?;
1133
1134        // When there are no Update::Set entries after clear, delete_view should be true
1135        assert!(delete_view);
1136
1137        Ok(())
1138    }
1139
1140    #[tokio::test]
1141    async fn test_byte_set_view_flush_with_delete_storage_first_mixed_updates(
1142    ) -> Result<(), ViewError> {
1143        let context = MemoryContext::new_for_testing(());
1144        let mut set = ByteSetView::load(context).await?;
1145
1146        // Add initial data
1147        set.insert(vec![1, 2, 3]);
1148        set.insert(vec![4, 5, 6]);
1149        let mut batch = Batch::new();
1150        set.pre_save(&mut batch)?;
1151        set.context().store().write_batch(batch).await?;
1152        set.post_save();
1153
1154        // Clear the set
1155        set.clear();
1156
1157        // Add some items back and remove others
1158        set.insert(vec![7, 8, 9]); // This creates Update::Set
1159        set.remove(vec![10, 11, 12]); // This creates Update::Removed (but gets optimized away due to delete_storage_first)
1160
1161        let mut batch = Batch::new();
1162        let delete_view = set.pre_save(&mut batch)?;
1163
1164        // Should be false because we have Update::Set entries (line 103 logic)
1165        assert!(!delete_view);
1166
1167        Ok(())
1168    }
1169
1170    #[tokio::test]
1171    async fn test_has_pending_changes_comprehensive() -> Result<(), ViewError> {
1172        let context = MemoryContext::new_for_testing(());
1173        let mut set = ByteSetView::load(context).await?;
1174
1175        // Fresh load should have no pending changes
1176        assert!(!set.has_pending_changes().await);
1177
1178        // Insert creates pending changes
1179        set.insert(vec![1]);
1180        assert!(set.has_pending_changes().await);
1181
1182        // Multiple inserts still have pending changes
1183        set.insert(vec![2]);
1184        set.insert(vec![3]);
1185        assert!(set.has_pending_changes().await);
1186
1187        // Flush clears pending changes
1188        let mut batch = Batch::new();
1189        set.pre_save(&mut batch)?;
1190        set.context().store().write_batch(batch).await?;
1191        set.post_save();
1192        assert!(!set.has_pending_changes().await);
1193
1194        // Remove creates pending changes
1195        set.remove(vec![1]);
1196        assert!(set.has_pending_changes().await);
1197
1198        // Clear creates pending changes
1199        set.clear();
1200        assert!(set.has_pending_changes().await);
1201
1202        // Insert after clear still has pending changes
1203        set.insert(vec![4]);
1204        assert!(set.has_pending_changes().await);
1205
1206        // Rollback clears pending changes
1207        set.rollback();
1208        assert!(!set.has_pending_changes().await);
1209
1210        // After rollback, original data should still be accessible
1211        assert!(set.contains(&[2]).await?);
1212        assert!(set.contains(&[3]).await?);
1213
1214        Ok(())
1215    }
1216
1217    #[tokio::test]
1218    async fn test_for_each_key_while_match_update_pattern() -> Result<(), ViewError> {
1219        let context = MemoryContext::new_for_testing(());
1220        let mut set = ByteSetView::load(context).await?;
1221
1222        // Add initial data to storage
1223        set.insert(vec![1]);
1224        set.insert(vec![3]);
1225        set.insert(vec![5]);
1226        let mut batch = Batch::new();
1227        set.pre_save(&mut batch)?;
1228        set.context().store().write_batch(batch).await?;
1229        set.post_save();
1230
1231        // Add some pending updates that will be processed in the loop
1232        set.insert(vec![2]); // This will create an Update::Set
1233        set.insert(vec![4]); // This will create another Update::Set
1234
1235        let mut keys_processed = Vec::new();
1236
1237        // This will exercise line 286: match update pattern
1238        // The method iterates through stored keys and pending updates
1239        set.for_each_key_while(|key| {
1240            keys_processed.push(key.to_vec());
1241            Ok(true) // Continue processing
1242        })
1243        .await?;
1244
1245        // Should have processed both stored and pending keys
1246        assert_eq!(
1247            keys_processed,
1248            vec![vec![1], vec![2], vec![3], vec![4], vec![5]]
1249        );
1250
1251        Ok(())
1252    }
1253
1254    #[tokio::test]
1255    async fn test_for_each_key_while_early_return() -> Result<(), ViewError> {
1256        let context = MemoryContext::new_for_testing(());
1257        let mut set = ByteSetView::load(context).await?;
1258
1259        // Add data to storage first
1260        set.insert(vec![1]);
1261        set.insert(vec![2]);
1262        set.insert(vec![3]);
1263        let mut batch = Batch::new();
1264        set.pre_save(&mut batch)?;
1265        set.context().store().write_batch(batch).await?;
1266        set.post_save();
1267
1268        let mut count = 0;
1269
1270        // This tests line 300: return Ok(()); when function returns false
1271        set.for_each_key_while(|_key| {
1272            count += 1;
1273            if count >= 2 {
1274                Ok(false) // This should trigger early return on line 300
1275            } else {
1276                Ok(true)
1277            }
1278        })
1279        .await?;
1280
1281        // Should have stopped early, processing only 2 keys
1282        assert_eq!(count, 2);
1283
1284        Ok(())
1285    }
1286
1287    #[tokio::test]
1288    async fn test_hash_mut_delegation() -> Result<(), ViewError> {
1289        let context = MemoryContext::new_for_testing(());
1290        let mut set = ByteSetView::load(context).await?;
1291
1292        // Add some data
1293        set.insert(vec![1, 2, 3]);
1294        set.insert(vec![4, 5, 6]);
1295
1296        // Test line 356: self.hash().await - hash_mut delegates to hash
1297        let hash1 = set.hash_mut().await?;
1298        let hash2 = set.hash().await?;
1299
1300        // Both should produce the same result since hash_mut delegates to hash
1301        assert_eq!(hash1, hash2);
1302
1303        // Verify hash changes when data changes
1304        set.insert(vec![7, 8, 9]);
1305        let hash3 = set.hash_mut().await?;
1306        assert_ne!(hash1, hash3);
1307
1308        Ok(())
1309    }
1310
1311    #[tokio::test]
1312    async fn test_for_each_key_while_early_return_on_update_set() -> Result<(), ViewError> {
1313        let context = MemoryContext::new_for_testing(());
1314        let mut set = ByteSetView::load(context).await?;
1315
1316        // Add some data to storage first
1317        set.insert(vec![1]);
1318        set.insert(vec![3]);
1319        let mut batch = Batch::new();
1320        set.pre_save(&mut batch)?;
1321        set.context().store().write_batch(batch).await?;
1322        set.post_save();
1323
1324        // Add pending updates that come before stored keys lexicographically
1325        set.insert(vec![0]); // This will be processed first as an Update::Set
1326        set.insert(vec![2]); // This will be processed as an Update::Set
1327
1328        let mut count = 0;
1329
1330        // This tests line 290: return Ok(()); in the Update::Set branch
1331        // The function should return false on the first Update::Set key, triggering early return
1332        set.for_each_key_while(|key| {
1333            count += 1;
1334            if key == [0] {
1335                Ok(false) // This should trigger line 290: return Ok(());
1336            } else {
1337                Ok(true)
1338            }
1339        })
1340        .await?;
1341
1342        // Should have stopped early after processing the first key
1343        assert_eq!(count, 1);
1344
1345        Ok(())
1346    }
1347
1348    #[tokio::test]
1349    async fn test_for_each_key_while_early_return_in_remaining_updates() -> Result<(), ViewError> {
1350        let context = MemoryContext::new_for_testing(());
1351        let mut set = ByteSetView::load(context).await?;
1352
1353        // Only add pending updates, no stored data
1354        // This forces the method to only process the remaining updates loop (line 308-315)
1355        set.insert(vec![1]);
1356        set.insert(vec![2]);
1357        set.insert(vec![3]);
1358
1359        let mut count = 0;
1360
1361        // This tests line 311: return Ok(()); in the remaining updates while loop
1362        set.for_each_key_while(|key| {
1363            count += 1;
1364            if key == [2] {
1365                Ok(false) // This should trigger line 311: return Ok(());
1366            } else {
1367                Ok(true)
1368            }
1369        })
1370        .await?;
1371
1372        // Should have stopped early when processing key [2]
1373        assert_eq!(count, 2);
1374
1375        Ok(())
1376    }
1377
1378    #[tokio::test]
1379    async fn test_contains_update_removed_returns_false() -> Result<(), ViewError> {
1380        let context = MemoryContext::new_for_testing(());
1381        let mut set = ByteSetView::load(context).await?;
1382
1383        // Initially no pending changes
1384        assert!(!set.has_pending_changes().await);
1385
1386        // First add an item and persist it
1387        set.insert(vec![1, 2, 3]);
1388
1389        // Should have pending changes after insert
1390        assert!(set.has_pending_changes().await);
1391
1392        // Check keys before flush
1393        assert_eq!(set.keys().await?, vec![vec![1, 2, 3]]);
1394
1395        let mut batch = Batch::new();
1396        set.pre_save(&mut batch)?;
1397        set.context().store().write_batch(batch).await?;
1398        set.post_save();
1399
1400        // No pending changes after flush
1401        assert!(!set.has_pending_changes().await);
1402
1403        // Check keys after flush
1404        assert_eq!(set.keys().await?, vec![vec![1, 2, 3]]);
1405
1406        // Verify it exists
1407        assert!(set.contains(&[1, 2, 3]).await?);
1408
1409        // Now remove the item - this creates an Update::Removed
1410        set.remove(vec![1, 2, 3]);
1411
1412        // Should have pending changes after remove
1413        assert!(set.has_pending_changes().await);
1414
1415        // After remove, keys should be empty
1416        assert!(set.keys().await?.is_empty());
1417
1418        // This tests line 196: Update::Removed => false,
1419        // The contains() method should return false for the removed item
1420        assert!(!set.contains(&[1, 2, 3]).await?);
1421
1422        Ok(())
1423    }
1424
1425    #[tokio::test]
1426    async fn test_contains_delete_storage_first_returns_false() -> Result<(), ViewError> {
1427        let context = MemoryContext::new_for_testing(());
1428        let mut set = ByteSetView::load(context).await?;
1429
1430        // Add some items and persist them
1431        set.insert(vec![1]);
1432        set.insert(vec![2]);
1433        set.insert(vec![3]);
1434        let mut batch = Batch::new();
1435        set.pre_save(&mut batch)?;
1436        set.context().store().write_batch(batch).await?;
1437        set.post_save();
1438
1439        // Verify items exist
1440        assert!(set.contains(&[1]).await?);
1441        assert!(set.contains(&[2]).await?);
1442        assert!(set.contains(&[3]).await?);
1443
1444        // Clear the set - this sets delete_storage_first = true
1445        set.clear();
1446
1447        // This tests line 202: return Ok(false); when delete_storage_first is true
1448        // All items should now return false, even for keys that exist in storage
1449        assert!(!set.contains(&[1]).await?);
1450        assert!(!set.contains(&[2]).await?);
1451        assert!(!set.contains(&[3]).await?);
1452
1453        // Even non-existent keys should return false
1454        assert!(!set.contains(&[99]).await?);
1455
1456        Ok(())
1457    }
1458
1459    #[tokio::test]
1460    async fn test_contains_delete_storage_first_with_new_additions() -> Result<(), ViewError> {
1461        let context = MemoryContext::new_for_testing(());
1462        let mut set = ByteSetView::load(context).await?;
1463
1464        // Add and persist some initial data
1465        set.insert(vec![1]);
1466        set.insert(vec![2]);
1467        let mut batch = Batch::new();
1468        set.pre_save(&mut batch)?;
1469        set.context().store().write_batch(batch).await?;
1470        set.post_save();
1471
1472        // Clear the set (sets delete_storage_first = true)
1473        set.clear();
1474
1475        // Add new items after clearing
1476        set.insert(vec![3]);
1477        set.insert(vec![4]);
1478
1479        // Line 202 should be bypassed for new items since they have Update::Set
1480        // Old items should return false due to line 202
1481        assert!(!set.contains(&[1]).await?); // Old item - line 202 path
1482        assert!(!set.contains(&[2]).await?); // Old item - line 202 path
1483        assert!(set.contains(&[3]).await?); // New item - has Update::Set
1484        assert!(set.contains(&[4]).await?); // New item - has Update::Set
1485
1486        Ok(())
1487    }
1488
1489    #[tokio::test]
1490    async fn test_for_each_key_while_update_set_processing_in_stored_loop() -> Result<(), ViewError>
1491    {
1492        let context = MemoryContext::new_for_testing(());
1493        let mut set = ByteSetView::load(context).await?;
1494
1495        // Add data to storage first
1496        set.insert(vec![2]);
1497        set.insert(vec![4]);
1498        set.insert(vec![6]);
1499        let mut batch = Batch::new();
1500        set.pre_save(&mut batch)?;
1501        set.context().store().write_batch(batch).await?;
1502        set.post_save();
1503
1504        // Add pending updates that will be processed alongside stored keys
1505        set.insert(vec![1]); // Update::Set - comes before stored keys
1506        set.insert(vec![3]); // Update::Set - comes between stored keys
1507        set.remove(vec![5]); // Update::Removed - should be ignored
1508
1509        let mut processed_keys = Vec::new();
1510
1511        // This tests line 292: closing brace of Update::Set block in stored keys processing
1512        // Only Update::Set entries should be processed, Update::Removed should be skipped
1513        set.for_each_key_while(|key| {
1514            processed_keys.push(key.to_vec());
1515            Ok(true)
1516        })
1517        .await?;
1518
1519        // Should process stored keys (2, 4, 6) and Update::Set pending keys (1, 3)
1520        // Should NOT process Update::Removed key (5)
1521        assert_eq!(
1522            processed_keys,
1523            vec![vec![1], vec![2], vec![3], vec![4], vec![6]]
1524        );
1525
1526        Ok(())
1527    }
1528
1529    #[tokio::test]
1530    async fn test_set_view_flush_with_delete_storage_first_and_set_updates() -> Result<(), ViewError>
1531    {
1532        let context = MemoryContext::new_for_testing(());
1533        let mut set = SetView::<_, u32>::load(context).await?;
1534
1535        // Add initial data
1536        set.insert(&42)?;
1537        set.insert(&84)?;
1538        let mut batch = Batch::new();
1539        set.pre_save(&mut batch)?;
1540        set.context().store().write_batch(batch).await?;
1541        set.post_save();
1542
1543        // Clear the set
1544        set.clear();
1545
1546        // Add new items - this should trigger the Update::Set branch in line 103
1547        set.insert(&123)?;
1548        set.insert(&456)?;
1549
1550        let mut batch = Batch::new();
1551        let delete_view = set.pre_save(&mut batch)?;
1552
1553        // Should be false due to Update::Set entries
1554        assert!(!delete_view);
1555
1556        // Verify final state
1557        set.context().store().write_batch(batch).await?;
1558        set.post_save();
1559        let new_set = SetView::<_, u32>::load(set.context().clone()).await?;
1560        assert!(new_set.contains(&123).await?);
1561        assert!(new_set.contains(&456).await?);
1562        assert!(!new_set.contains(&42).await?);
1563        assert!(!new_set.contains(&84).await?);
1564
1565        Ok(())
1566    }
1567
1568    #[tokio::test]
1569    async fn test_set_view_count_delegation() -> Result<(), ViewError> {
1570        let context = MemoryContext::new_for_testing(());
1571        let mut set = SetView::<_, u32>::load(context).await?;
1572
1573        // Initially no pending changes
1574        assert!(!set.has_pending_changes().await);
1575
1576        // Test line 557: self.set.iterative_count().await - SetView delegates to ByteSetView
1577        assert_eq!(set.iterative_count().await?, 0);
1578
1579        // Add items and verify delegation works
1580        set.insert(&42)?;
1581
1582        // Should have pending changes after first insert
1583        assert!(set.has_pending_changes().await);
1584
1585        // Check indices after first insert
1586        assert_eq!(set.indices().await?, vec![42]);
1587
1588        set.insert(&84)?;
1589        set.insert(&126)?;
1590
1591        // Should still have pending changes
1592        assert!(set.has_pending_changes().await);
1593
1594        // Check indices after all inserts
1595        assert_eq!(set.indices().await?, vec![42, 84, 126]);
1596
1597        // This calls line 557 which delegates to the underlying ByteSetView
1598        assert_eq!(set.iterative_count().await?, 3);
1599
1600        Ok(())
1601    }
1602
1603    #[tokio::test]
1604    async fn test_set_view_hash_mut_delegation() -> Result<(), ViewError> {
1605        let context = MemoryContext::new_for_testing(());
1606        let mut set = SetView::<_, u32>::load(context).await?;
1607
1608        // Add some data to the SetView
1609        set.insert(&42)?;
1610        set.insert(&84)?;
1611        set.insert(&126)?;
1612
1613        // Test line 641: self.set.hash_mut().await - SetView delegates to ByteSetView
1614        let hash1 = set.hash_mut().await?;
1615        let hash2 = set.hash().await?;
1616
1617        // Both should produce the same result since SetView delegates to ByteSetView
1618        assert_eq!(hash1, hash2);
1619
1620        // Verify that the delegation works correctly when data changes
1621        set.insert(&168)?;
1622        let hash3 = set.hash_mut().await?;
1623        assert_ne!(hash1, hash3);
1624
1625        // Test that SetView hash delegation produces same result as direct ByteSetView hash
1626        let context2 = MemoryContext::new_for_testing(());
1627        let mut byte_set = ByteSetView::load(context2).await?;
1628
1629        // Add equivalent data to ByteSetView (using serialized form of the same numbers)
1630        use crate::context::BaseKey;
1631        byte_set.insert(BaseKey::derive_short_key(&42u32)?);
1632        byte_set.insert(BaseKey::derive_short_key(&84u32)?);
1633        byte_set.insert(BaseKey::derive_short_key(&126u32)?);
1634        byte_set.insert(BaseKey::derive_short_key(&168u32)?);
1635
1636        let byte_set_hash = byte_set.hash_mut().await?;
1637        assert_eq!(hash3, byte_set_hash);
1638
1639        Ok(())
1640    }
1641
1642    // CustomSetView tests - similar patterns but using CustomSerialize
1643    #[tokio::test]
1644    async fn test_custom_set_view_flush_with_delete_storage_first_and_set_updates(
1645    ) -> Result<(), ViewError> {
1646        let context = MemoryContext::new_for_testing(());
1647        let mut set = CustomSetView::<_, u128>::load(context).await?;
1648
1649        // Initially no pending changes
1650        assert!(!set.has_pending_changes().await);
1651
1652        // Add initial data
1653        set.insert(&42u128)?;
1654        set.insert(&84u128)?;
1655
1656        // Should have pending changes after inserts
1657        assert!(set.has_pending_changes().await);
1658
1659        // Check indices before flush
1660        assert_eq!(set.indices().await?, vec![42u128, 84u128]);
1661
1662        let mut batch = Batch::new();
1663        set.pre_save(&mut batch)?;
1664        set.context().store().write_batch(batch).await?;
1665        set.post_save();
1666
1667        // No pending changes after flush
1668        assert!(!set.has_pending_changes().await);
1669
1670        // Check indices after flush
1671        assert_eq!(set.indices().await?, vec![42u128, 84u128]);
1672
1673        // Clear the set
1674        set.clear();
1675
1676        // Should have pending changes after clear
1677        assert!(set.has_pending_changes().await);
1678
1679        // After clear, indices should be empty
1680        assert!(set.indices().await?.is_empty());
1681
1682        // Add new items - this should trigger the Update::Set branch (line 103 equivalent)
1683        set.insert(&123u128)?;
1684        set.insert(&456u128)?;
1685
1686        // Should still have pending changes
1687        assert!(set.has_pending_changes().await);
1688
1689        // Check indices after new inserts
1690        assert_eq!(set.indices().await?, vec![123u128, 456u128]);
1691
1692        let mut batch = Batch::new();
1693        let delete_view = set.pre_save(&mut batch)?;
1694
1695        // Should be false due to Update::Set entries
1696        assert!(!delete_view);
1697
1698        // Verify final state
1699        set.context().store().write_batch(batch).await?;
1700        set.post_save();
1701
1702        // No pending changes after final flush
1703        assert!(!set.has_pending_changes().await);
1704
1705        let new_set = CustomSetView::<_, u128>::load(set.context().clone()).await?;
1706        assert!(new_set.contains(&123u128).await?);
1707        assert!(new_set.contains(&456u128).await?);
1708        assert!(!new_set.contains(&42u128).await?);
1709        assert!(!new_set.contains(&84u128).await?);
1710
1711        // New set should have no pending changes
1712        assert!(!new_set.has_pending_changes().await);
1713
1714        Ok(())
1715    }
1716
1717    #[tokio::test]
1718    async fn test_custom_set_view_contains_update_removed_returns_false() -> Result<(), ViewError> {
1719        let context = MemoryContext::new_for_testing(());
1720        let mut set = CustomSetView::<_, u128>::load(context).await?;
1721
1722        // Add and persist an item
1723        set.insert(&12345u128)?;
1724        let mut batch = Batch::new();
1725        set.pre_save(&mut batch)?;
1726        set.context().store().write_batch(batch).await?;
1727        set.post_save();
1728
1729        // Verify it exists
1730        assert!(set.contains(&12345u128).await?);
1731
1732        // Remove the item - creates Update::Removed (tests line 196 equivalent)
1733        set.remove(&12345u128)?;
1734
1735        // Should return false for the removed item
1736        assert!(!set.contains(&12345u128).await?);
1737
1738        Ok(())
1739    }
1740
1741    #[tokio::test]
1742    async fn test_custom_set_view_contains_delete_storage_first_returns_false(
1743    ) -> Result<(), ViewError> {
1744        let context = MemoryContext::new_for_testing(());
1745        let mut set = CustomSetView::<_, u128>::load(context).await?;
1746
1747        // Add items and persist
1748        set.insert(&111u128)?;
1749        set.insert(&222u128)?;
1750        set.insert(&333u128)?;
1751        let mut batch = Batch::new();
1752        set.pre_save(&mut batch)?;
1753        set.context().store().write_batch(batch).await?;
1754        set.post_save();
1755
1756        // Verify items exist
1757        assert!(set.contains(&111u128).await?);
1758        assert!(set.contains(&222u128).await?);
1759
1760        // Clear the set - sets delete_storage_first = true
1761        set.clear();
1762
1763        // Tests line 202 equivalent: should return false when delete_storage_first is true
1764        assert!(!set.contains(&111u128).await?);
1765        assert!(!set.contains(&222u128).await?);
1766        assert!(!set.contains(&333u128).await?);
1767
1768        Ok(())
1769    }
1770
1771    #[tokio::test]
1772    async fn test_custom_set_view_hash_mut_delegation() -> Result<(), ViewError> {
1773        let context = MemoryContext::new_for_testing(());
1774        let mut set = CustomSetView::<_, u128>::load(context).await?;
1775
1776        // Add some data
1777        set.insert(&1000u128)?;
1778        set.insert(&2000u128)?;
1779
1780        // Test hash_mut delegation (line 641 equivalent for CustomSetView)
1781        let hash1 = set.hash_mut().await?;
1782        let hash2 = set.hash().await?;
1783
1784        // Both should produce the same result since CustomSetView delegates to ByteSetView
1785        assert_eq!(hash1, hash2);
1786
1787        // Verify hash changes when data changes
1788        set.insert(&3000u128)?;
1789        let hash3 = set.hash_mut().await?;
1790        assert_ne!(hash1, hash3);
1791
1792        Ok(())
1793    }
1794
1795    #[tokio::test]
1796    async fn test_custom_set_view_for_each_index_while_method_signature() -> Result<(), ViewError> {
1797        let context = MemoryContext::new_for_testing(());
1798        let mut set = CustomSetView::<_, u128>::load(context).await?;
1799        assert_eq!(set.iterative_count().await?, 0);
1800
1801        // Add some data to test the method
1802        set.insert(&100u128)?;
1803        set.insert(&200u128)?;
1804        set.insert(&300u128)?;
1805
1806        assert_eq!(set.iterative_count().await?, 3);
1807
1808        let mut collected_indices = Vec::new();
1809
1810        // Test line 584: pub async fn for_each_index_while<F>(&self, mut f: F) -> Result<(), ViewError>
1811        // This tests the method signature and implementation
1812        set.for_each_index_while(|index| {
1813            collected_indices.push(index);
1814            Ok(true)
1815        })
1816        .await?;
1817
1818        // Verify the method worked correctly
1819        assert_eq!(collected_indices, vec![100u128, 200u128, 300u128]);
1820
1821        Ok(())
1822    }
1823
1824    #[tokio::test]
1825    async fn test_custom_set_view_rollback() -> Result<(), ViewError> {
1826        let context = MemoryContext::new_for_testing(());
1827        let mut set = CustomSetView::<_, u128>::load(context).await?;
1828
1829        // Add and persist some initial data
1830        set.insert(&100u128)?;
1831        set.insert(&200u128)?;
1832        let mut batch = Batch::new();
1833        set.pre_save(&mut batch)?;
1834        set.context().store().write_batch(batch).await?;
1835        set.post_save();
1836
1837        // Verify initial state
1838        assert!(set.contains(&100u128).await?);
1839        assert!(set.contains(&200u128).await?);
1840        assert!(!set.has_pending_changes().await);
1841
1842        // Make some changes
1843        set.insert(&300u128)?;
1844        set.remove(&100u128)?;
1845        assert!(set.has_pending_changes().await);
1846
1847        // Verify changes are present before rollback
1848        assert!(set.contains(&300u128).await?);
1849        assert!(!set.contains(&100u128).await?);
1850
1851        // Test line 687: self.set.rollback() - CustomSetView rollback delegation
1852        set.rollback();
1853
1854        // After rollback, should revert to original state
1855        assert!(!set.has_pending_changes().await);
1856        assert!(set.contains(&100u128).await?);
1857        assert!(set.contains(&200u128).await?);
1858        assert!(!set.contains(&300u128).await?);
1859
1860        Ok(())
1861    }
1862
1863    #[tokio::test]
1864    async fn test_custom_set_view_clone_unchecked() -> Result<(), ViewError> {
1865        let context = MemoryContext::new_for_testing(());
1866        let mut set = CustomSetView::<_, u128>::load(context).await?;
1867
1868        // Add some data to the original set
1869        set.insert(&42u128)?;
1870        set.insert(&84u128)?;
1871
1872        // Test line 709: CustomSetView { set: self.set.clone_unchecked(), _phantom: PhantomData, }
1873        let mut cloned_set = set.clone_unchecked()?;
1874
1875        // Verify the clone has the same data
1876        assert!(cloned_set.contains(&42u128).await?);
1877        assert!(cloned_set.contains(&84u128).await?);
1878
1879        // Verify changes to clone don't affect original
1880        cloned_set.insert(&126u128)?;
1881        assert!(cloned_set.contains(&126u128).await?);
1882        assert!(!set.contains(&126u128).await?);
1883
1884        // Verify changes to original don't affect clone
1885        set.insert(&168u128)?;
1886        assert!(set.contains(&168u128).await?);
1887        assert!(!cloned_set.contains(&168u128).await?);
1888
1889        Ok(())
1890    }
1891
1892    #[cfg(with_graphql)]
1893    mod graphql_tests {
1894        use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema};
1895
1896        use super::*;
1897
1898        // Create a simple GraphQL schema for testing
1899        struct Query;
1900
1901        #[Object]
1902        impl Query {
1903            async fn test_set(&self) -> TestSetView {
1904                let context = MemoryContext::new_for_testing(());
1905                let mut set = SetView::<_, u32>::load(context).await.unwrap();
1906
1907                // Add test data
1908                set.insert(&42).unwrap();
1909                set.insert(&84).unwrap();
1910                set.insert(&126).unwrap();
1911                set.insert(&168).unwrap();
1912                set.insert(&210).unwrap();
1913
1914                TestSetView { set }
1915            }
1916        }
1917
1918        struct TestSetView {
1919            set: SetView<MemoryContext<()>, u32>,
1920        }
1921
1922        #[Object]
1923        impl TestSetView {
1924            async fn elements(
1925                &self,
1926                count: Option<usize>,
1927            ) -> Result<Vec<u32>, async_graphql::Error> {
1928                // This calls line 1169: async fn elements(&self, count: Option<usize>)
1929                let mut indices = self.set.indices().await?;
1930                if let Some(count) = count {
1931                    // This tests line 1172: indices.truncate(count);
1932                    indices.truncate(count);
1933                }
1934                Ok(indices)
1935            }
1936
1937            async fn count(&self) -> Result<u32, async_graphql::Error> {
1938                let count = self.set.iterative_count().await?;
1939                u32::try_from(count).map_err(|_| async_graphql::Error::new("count exceeds u32"))
1940            }
1941        }
1942
1943        #[tokio::test]
1944        async fn test_graphql_elements_without_count() -> Result<(), Box<dyn std::error::Error>> {
1945            let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
1946
1947            // Test line 1169 without count parameter - should return all elements
1948            let query = r#"
1949                query {
1950                    testSet {
1951                        elements
1952                    }
1953                }
1954            "#;
1955
1956            let result = schema.execute(query).await;
1957            assert!(result.errors.is_empty());
1958
1959            let data = result.data.into_json()?;
1960            let elements = &data["testSet"]["elements"];
1961            assert!(elements.is_array());
1962            assert_eq!(elements.as_array().unwrap().len(), 5);
1963
1964            Ok(())
1965        }
1966
1967        #[tokio::test]
1968        async fn test_graphql_elements_with_count() -> Result<(), Box<dyn std::error::Error>> {
1969            let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
1970
1971            // Test line 1172 truncate logic - should limit to 3 elements
1972            let query = r#"
1973                query {
1974                    testSet {
1975                        elements(count: 3)
1976                    }
1977                }
1978            "#;
1979
1980            let result = schema.execute(query).await;
1981            assert!(result.errors.is_empty());
1982
1983            let data = result.data.into_json()?;
1984            let elements = &data["testSet"]["elements"];
1985            assert!(elements.is_array());
1986            // This tests that line 1172 (indices.truncate(count)) worked correctly
1987            assert_eq!(elements.as_array().unwrap().len(), 3);
1988
1989            Ok(())
1990        }
1991
1992        #[tokio::test]
1993        async fn test_graphql_count_field() -> Result<(), Box<dyn std::error::Error>> {
1994            let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
1995
1996            let query = r#"
1997                query {
1998                    testSet {
1999                        count
2000                    }
2001                }
2002            "#;
2003
2004            let result = schema.execute(query).await;
2005            assert!(result.errors.is_empty());
2006
2007            let data = result.data.into_json()?;
2008            let count = &data["testSet"]["count"];
2009            assert_eq!(count.as_u64().unwrap(), 5);
2010
2011            Ok(())
2012        }
2013    }
2014}