rune/modules/collections/
hash_set.rs

1use core::ptr;
2
3use crate as rune;
4use crate::alloc::fmt::TryWrite;
5use crate::alloc::hashbrown::raw::RawIter;
6use crate::alloc::prelude::*;
7use crate::hashbrown::{IterRef, Table};
8use crate::runtime::{
9    EnvProtocolCaller, Formatter, Iterator, ProtocolCaller, RawAnyGuard, Ref, Value, VmResult,
10};
11use crate::{Any, ContextError, Module};
12
13/// A dynamic hash set.
14#[rune::module(::std::collections::hash_set)]
15pub fn module() -> Result<Module, ContextError> {
16    let mut m = Module::from_meta(self::module_meta)?;
17
18    m.ty::<HashSet>()?;
19    m.function_meta(HashSet::new__meta)?;
20    m.function_meta(HashSet::with_capacity__meta)?;
21    m.function_meta(HashSet::len__meta)?;
22    m.function_meta(HashSet::is_empty__meta)?;
23    m.function_meta(HashSet::capacity__meta)?;
24    m.function_meta(HashSet::insert__meta)?;
25    m.function_meta(HashSet::remove__meta)?;
26    m.function_meta(HashSet::contains__meta)?;
27    m.function_meta(HashSet::clear__meta)?;
28    m.function_meta(HashSet::difference__meta)?;
29    m.function_meta(HashSet::extend__meta)?;
30    m.function_meta(HashSet::intersection__meta)?;
31    m.function_meta(HashSet::union__meta)?;
32    m.function_meta(HashSet::iter__meta)?;
33    m.function_meta(HashSet::into_iter__meta)?;
34    m.function_meta(HashSet::from_iter__meta)?;
35    m.function_meta(HashSet::debug_fmt__meta)?;
36
37    m.function_meta(HashSet::clone__meta)?;
38    m.implement_trait::<HashSet>(rune::item!(::std::clone::Clone))?;
39
40    m.function_meta(HashSet::partial_eq__meta)?;
41    m.implement_trait::<HashSet>(rune::item!(::std::cmp::PartialEq))?;
42
43    m.function_meta(HashSet::eq__meta)?;
44    m.implement_trait::<HashSet>(rune::item!(::std::cmp::Eq))?;
45
46    m.ty::<Iter>()?;
47    m.function_meta(Iter::next__meta)?;
48    m.function_meta(Iter::size_hint__meta)?;
49    m.implement_trait::<Iter>(rune::item!(::std::iter::Iterator))?;
50    m.function_meta(Iter::len__meta)?;
51    m.implement_trait::<Iter>(rune::item!(::std::iter::ExactSizeIterator))?;
52
53    m.ty::<Difference>()?;
54    m.function_meta(Difference::next__meta)?;
55    m.function_meta(Difference::size_hint__meta)?;
56    m.implement_trait::<Difference>(rune::item!(::std::iter::Iterator))?;
57
58    m.ty::<Intersection>()?;
59    m.function_meta(Intersection::next__meta)?;
60    m.function_meta(Intersection::size_hint__meta)?;
61    m.implement_trait::<Intersection>(rune::item!(::std::iter::Iterator))?;
62
63    m.ty::<Union>()?;
64    m.function_meta(Union::next__meta)?;
65    m.implement_trait::<Union>(rune::item!(::std::iter::Iterator))?;
66    Ok(m)
67}
68
69/// A [hash set] implemented as a `HashMap` where the value is `()`.
70///
71/// As with the [`HashMap`] type, a `HashSet` requires that the elements
72/// implement the [`EQ`] and [`HASH`] protocols. If you implement these
73/// yourself, it is important that the following property holds:
74///
75/// ```text
76/// k1 == k2 -> hash(k1) == hash(k2)
77/// ```
78///
79/// In other words, if two keys are equal, their hashes must be equal. Violating
80/// this property is a logic error.
81///
82/// It is also a logic error for a key to be modified in such a way that the
83/// key's hash, as determined by the [`HASH`] protocol, or its equality, as
84/// determined by the [`EQ`] protocol, changes while it is in the map. This is
85/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
86/// unsafe code.
87///
88/// The behavior resulting from either logic error is not specified, but will be
89/// encapsulated to the `HashSet` that observed the logic error and not result
90/// in undefined behavior. This could include panics, incorrect results, aborts,
91/// memory leaks, and non-termination.
92///
93/// [hash set]: crate::collections#use-the-set-variant-of-any-of-these-maps-when
94/// [`HashMap`]: crate::collections::HashMap
95///
96/// # Examples
97///
98/// ```rune
99/// use std::collections::HashSet;
100///
101/// enum Tile {
102///     Wall,
103/// }
104///
105/// let m = HashSet::new();
106///
107/// m.insert((0, 1));
108///
109/// assert!(m.contains((0, 1)));
110/// assert!(!m.contains((0, 2)));
111/// ```
112#[derive(Any)]
113#[rune(module = crate, item = ::std::collections::hash_set)]
114pub(crate) struct HashSet {
115    table: Table<()>,
116}
117
118impl HashSet {
119    /// Creates an empty `HashSet`.
120    ///
121    /// The hash set is initially created with a capacity of 0, so it will not
122    /// allocate until it is first inserted into.
123    ///
124    /// # Examples
125    ///
126    /// ```rune
127    /// use std::collections::HashSet;
128    ///
129    /// let set = HashSet::new();
130    /// ```
131    #[rune::function(keep, path = Self::new)]
132    fn new() -> Self {
133        Self {
134            table: Table::new(),
135        }
136    }
137
138    /// Creates an empty `HashSet` with at least the specified capacity.
139    ///
140    /// The hash set will be able to hold at least `capacity` elements without
141    /// reallocating. This method is allowed to allocate for more elements than
142    /// `capacity`. If `capacity` is 0, the hash set will not allocate.
143    ///
144    /// # Examples
145    ///
146    /// ```rune
147    /// use std::collections::HashSet;
148    ///
149    /// let set = HashSet::with_capacity(10);
150    /// assert!(set.capacity() >= 10);
151    /// ```
152    #[rune::function(keep, path = Self::with_capacity)]
153    pub(crate) fn with_capacity(capacity: usize) -> VmResult<Self> {
154        VmResult::Ok(Self {
155            table: vm_try!(Table::try_with_capacity(capacity)),
156        })
157    }
158
159    /// Returns the number of elements in the set.
160    ///
161    /// # Examples
162    ///
163    /// ```rune
164    /// use std::collections::HashSet;
165    ///
166    /// let v = HashSet::new();
167    /// assert_eq!(v.len(), 0);
168    /// v.insert(1);
169    /// assert_eq!(v.len(), 1);
170    /// ```
171    #[rune::function(keep)]
172    fn len(&self) -> usize {
173        self.table.len()
174    }
175
176    /// Returns `true` if the set contains no elements.
177    ///
178    /// # Examples
179    ///
180    /// ```rune
181    /// use std::collections::HashSet;
182    ///
183    /// let v = HashSet::new();
184    /// assert!(v.is_empty());
185    /// v.insert(1);
186    /// assert!(!v.is_empty());
187    /// ```
188    #[rune::function(keep)]
189    fn is_empty(&self) -> bool {
190        self.table.is_empty()
191    }
192
193    /// Returns the number of elements the set can hold without reallocating.
194    ///
195    /// # Examples
196    ///
197    /// ```rune
198    /// use std::collections::HashSet;
199    ///
200    /// let set = HashSet::with_capacity(100);
201    /// assert!(set.capacity() >= 100);
202    /// ```
203    #[rune::function(keep)]
204    fn capacity(&self) -> usize {
205        self.table.capacity()
206    }
207
208    /// Adds a value to the set.
209    ///
210    /// Returns whether the value was newly inserted. That is:
211    ///
212    /// - If the set did not previously contain this value, `true` is returned.
213    /// - If the set already contained this value, `false` is returned.
214    ///
215    /// # Examples
216    ///
217    /// ```rune
218    /// use std::collections::HashSet;
219    ///
220    /// let set = HashSet::new();
221    ///
222    /// assert_eq!(set.insert(2), true);
223    /// assert_eq!(set.insert(2), false);
224    /// assert_eq!(set.len(), 1);
225    /// ```
226    #[rune::function(keep)]
227    pub(crate) fn insert(&mut self, key: Value) -> VmResult<bool> {
228        let mut caller = EnvProtocolCaller;
229        VmResult::Ok(vm_try!(self.table.insert_with(key, (), &mut caller)).is_none())
230    }
231
232    /// Removes a value from the set. Returns whether the value was present in
233    /// the set.
234    ///
235    /// # Examples
236    ///
237    /// ```rune
238    /// use std::collections::HashSet;
239    ///
240    /// let set = HashSet::new();
241    ///
242    /// set.insert(2);
243    /// assert_eq!(set.remove(2), true);
244    /// assert_eq!(set.remove(2), false);
245    /// ```
246    #[rune::function(keep)]
247    fn remove(&mut self, key: Value) -> VmResult<bool> {
248        let mut caller = EnvProtocolCaller;
249        VmResult::Ok(vm_try!(self.table.remove_with(&key, &mut caller)).is_some())
250    }
251
252    /// Returns `true` if the set contains a value.
253    ///
254    /// # Examples
255    ///
256    /// ```rune
257    /// use std::collections::HashSet;
258    ///
259    /// let set = HashSet::from_iter([1, 2, 3]);
260    ///
261    /// assert!(set.contains(1));
262    /// assert!(!set.contains(4));
263    /// ```
264    #[rune::function(keep)]
265    fn contains(&self, key: Value) -> VmResult<bool> {
266        let mut caller = EnvProtocolCaller;
267        VmResult::Ok(vm_try!(self.table.get(&key, &mut caller)).is_some())
268    }
269
270    /// Clears the set, removing all values.
271    ///
272    /// # Examples
273    ///
274    /// ```rune
275    /// use std::collections::HashSet;
276    ///
277    /// let v = HashSet::new();
278    /// v.insert(1);
279    /// v.clear();
280    /// assert!(v.is_empty());
281    /// ```
282    #[rune::function(keep)]
283    fn clear(&mut self) {
284        self.table.clear()
285    }
286
287    /// Visits the values representing the difference, i.e., the values that are
288    /// in `self` but not in `other`.
289    ///
290    /// # Examples
291    ///
292    /// ```rune
293    /// use std::collections::HashSet;
294    ///
295    /// let a = HashSet::from_iter([1, 2, 3]);
296    /// let b = HashSet::from_iter([4, 2, 3, 4]);
297    ///
298    /// let diff = a.difference(b).collect::<HashSet>();
299    /// assert_eq!(diff, [1].iter().collect::<HashSet>());
300    ///
301    /// // Note that difference is not symmetric,
302    /// // and `b - a` means something else:
303    /// let diff = b.difference(a).collect::<HashSet>();
304    /// assert_eq!(diff, [4].iter().collect::<HashSet>());
305    /// ```
306    #[rune::function(keep, instance, path = Self::difference)]
307    fn difference(this: Ref<Self>, other: Ref<Self>) -> Difference {
308        Self::difference_inner(this, other)
309    }
310
311    fn difference_inner(this: Ref<Self>, other: Ref<Self>) -> Difference {
312        Difference {
313            this: Table::iter_ref(Ref::map(this, |this| &this.table)),
314            other: Some(other),
315        }
316    }
317
318    /// Visits the values representing the intersection, i.e., the values that
319    /// are both in `self` and `other`.
320    ///
321    /// When an equal element is present in `self` and `other` then the
322    /// resulting `Intersection` may yield values to one or the other.
323    ///
324    /// # Examples
325    ///
326    /// ```rune
327    /// use std::collections::HashSet;
328    ///
329    /// let a = HashSet::from_iter([1, 2, 3]);
330    /// let b = HashSet::from_iter([4, 2, 3, 4]);
331    ///
332    /// let values = a.intersection(b).collect::<HashSet>();
333    /// assert_eq!(values, [2, 3].iter().collect::<HashSet>());
334    /// ```
335    #[rune::function(keep, instance, path = Self::intersection)]
336    fn intersection(this: Ref<Self>, other: Ref<Self>) -> Intersection {
337        // use shortest iterator as driver for intersections
338        if this.table.len() <= other.table.len() {
339            Intersection {
340                this: Table::iter_ref(Ref::map(this, |this| &this.table)),
341                other: Some(other),
342            }
343        } else {
344            Intersection {
345                this: Table::iter_ref(Ref::map(other, |this| &this.table)),
346                other: Some(this),
347            }
348        }
349    }
350
351    /// Visits the values representing the union, i.e., all the values in `self`
352    /// or `other`, without duplicates.
353    ///
354    /// # Examples
355    ///
356    /// ```rune
357    /// use std::collections::HashSet;
358    ///
359    /// let a = HashSet::from_iter([1, 2, 3]);
360    /// let b = HashSet::from_iter([4, 2, 3, 4]);
361    ///
362    /// let union = a.union(b).collect::<HashSet>();
363    /// assert_eq!(union, HashSet::from_iter([1, 2, 3, 4]));
364    ///
365    /// let union = b.union(a).collect::<HashSet>();
366    /// assert_eq!(union, HashSet::from_iter([1, 2, 3, 4]));
367    /// ```
368    #[rune::function(keep, instance, path = Self::union)]
369    fn union(this: Ref<Self>, other: Ref<Self>) -> VmResult<Union> {
370        unsafe {
371            let (this, this_guard) = Ref::into_raw(Ref::map(this, |this| &this.table));
372            let (other, other_guard) = Ref::into_raw(Ref::map(other, |this| &this.table));
373
374            // use longest as lead and then append any missing that are in second
375            let iter = if this.as_ref().len() >= other.as_ref().len() {
376                let this_iter = Table::iter_ref_raw(this);
377                let other_iter = Table::iter_ref_raw(other);
378
379                Union {
380                    this,
381                    this_iter,
382                    other_iter,
383                    _guards: (this_guard, other_guard),
384                }
385            } else {
386                let this_iter = Table::iter_ref_raw(other);
387                let other_iter = Table::iter_ref_raw(this);
388
389                Union {
390                    this: other,
391                    this_iter,
392                    other_iter,
393                    _guards: (other_guard, this_guard),
394                }
395            };
396
397            VmResult::Ok(iter)
398        }
399    }
400
401    /// Iterate over the hash set.
402    ///
403    /// # Examples
404    ///
405    /// ```rune
406    /// use std::collections::HashSet;
407    ///
408    /// let set = HashSet::from_iter([3, 2, 1]);
409    /// let vec = set.iter().collect::<Vec>();
410    /// vec.sort();
411    /// assert_eq!(vec, [1, 2, 3]);
412    /// ```
413    #[rune::function(keep, instance, path = Self::iter)]
414    fn iter(this: Ref<Self>) -> Iter {
415        let iter = Table::iter_ref(Ref::map(this, |this| &this.table));
416
417        Iter { iter }
418    }
419
420    /// Extend this set from an iterator.
421    #[rune::function(keep)]
422    fn extend(&mut self, value: Value) -> VmResult<()> {
423        let mut caller = EnvProtocolCaller;
424        let mut it = vm_try!(value.into_iter());
425
426        while let Some(key) = vm_try!(it.next()) {
427            vm_try!(self.table.insert_with(key, (), &mut caller));
428        }
429
430        VmResult::Ok(())
431    }
432
433    /// Convert the set into an iterator.
434    ///
435    /// # Examples
436    ///
437    /// ```rune
438    /// use std::collections::HashSet;
439    ///
440    /// let set = HashSet::from_iter([3, 2, 1]);
441    /// let vec = [];
442    ///
443    /// for value in set {
444    ///     vec.push(value);
445    /// }
446    ///
447    /// vec.sort();
448    /// assert_eq!(vec, [1, 2, 3]);
449    /// ```
450    #[rune::function(keep, instance, protocol = INTO_ITER, path = Self)]
451    fn into_iter(this: Ref<Self>) -> Iter {
452        Self::iter(this)
453    }
454
455    /// Write a debug representation to a string.
456    ///
457    /// This calls the [`DEBUG_FMT`] protocol over all elements of the
458    /// collection.
459    ///
460    /// # Examples
461    ///
462    /// ```rune
463    /// use std::collections::HashSet;
464    ///
465    /// let set = HashSet::from_iter([1, 2, 3]);
466    /// println!("{:?}", set);
467    /// ```
468    #[rune::function(keep, protocol = DEBUG_FMT)]
469    fn debug_fmt(&self, f: &mut Formatter) -> VmResult<()> {
470        self.debug_fmt_with(f, &mut EnvProtocolCaller)
471    }
472
473    fn debug_fmt_with(&self, f: &mut Formatter, _: &mut dyn ProtocolCaller) -> VmResult<()> {
474        vm_try!(vm_write!(f, "{{"));
475
476        let mut it = self.table.iter().peekable();
477
478        while let Some(value) = it.next() {
479            vm_try!(vm_write!(f, "{:?}", value));
480
481            if it.peek().is_some() {
482                vm_try!(vm_write!(f, ", "));
483            }
484        }
485
486        vm_try!(vm_write!(f, "}}"));
487        VmResult::Ok(())
488    }
489
490    /// Convert a [`HashSet`] from an iterator.
491    ///
492    /// The hashset can be converted from anything that implements the
493    /// [`INTO_ITER`] protocol.
494    ///
495    /// # Examples
496    ///
497    /// ```rune
498    /// use std::collections::HashSet;
499    ///
500    /// let set = HashSet::from_iter(["a", "b"]);
501    /// assert_eq!(set.len(), 2);
502    /// assert!(set.contains("a"));
503    /// assert!(set.contains("b"));
504    /// ```
505    #[rune::function(keep, path = Self::from_iter)]
506    fn from_iter(it: Iterator) -> VmResult<HashSet> {
507        let mut caller = EnvProtocolCaller;
508        Self::from_iter_with(it, &mut caller)
509    }
510
511    pub(crate) fn from_iter_with(
512        mut it: Iterator,
513        caller: &mut dyn ProtocolCaller,
514    ) -> VmResult<Self> {
515        let (lo, _) = vm_try!(it.size_hint());
516        let mut set = vm_try!(Table::try_with_capacity(lo));
517
518        while let Some(key) = vm_try!(it.next()) {
519            vm_try!(set.insert_with(key, (), caller));
520        }
521
522        VmResult::Ok(HashSet { table: set })
523    }
524
525    /// Perform a partial equality test between two sets.
526    ///
527    /// # Examples
528    ///
529    /// # Examples
530    ///
531    /// ```rune
532    /// use std::collections::HashSet;
533    ///
534    /// let set = HashSet::from_iter([1, 2, 3]);
535    /// assert_eq!(set, HashSet::from_iter([1, 2, 3]));
536    /// assert_ne!(set, HashSet::from_iter([2, 3, 4]));
537    /// ```
538    #[rune::function(keep, protocol = PARTIAL_EQ)]
539    fn partial_eq(&self, other: &Self) -> VmResult<bool> {
540        self.eq_with(other, &mut EnvProtocolCaller)
541    }
542
543    /// Perform a total equality test between two sets.
544    ///
545    /// # Examples
546    ///
547    /// ```rune
548    /// use std::ops::eq;
549    /// use std::collections::HashSet;
550    ///
551    /// let set = HashSet::from_iter([1, 2, 3]);
552    /// assert!(eq(set, HashSet::from_iter([1, 2, 3])));
553    /// assert!(!eq(set, HashSet::from_iter([2, 3, 4])));
554    /// ```
555    #[rune::function(keep, protocol = EQ)]
556    fn eq(&self, other: &Self) -> VmResult<bool> {
557        self.eq_with(other, &mut EnvProtocolCaller)
558    }
559
560    fn eq_with(&self, other: &Self, caller: &mut EnvProtocolCaller) -> VmResult<bool> {
561        if self.table.len() != other.table.len() {
562            return VmResult::Ok(false);
563        }
564
565        for (key, ()) in self.table.iter() {
566            if vm_try!(other.table.get(key, caller)).is_none() {
567                return VmResult::Ok(false);
568            }
569        }
570
571        VmResult::Ok(true)
572    }
573
574    #[rune::function(keep, instance, path = Self::clone, protocol = CLONE)]
575    fn clone(this: &HashSet) -> VmResult<HashSet> {
576        VmResult::Ok(Self {
577            table: vm_try!(this.table.try_clone()),
578        })
579    }
580}
581
582#[derive(Any)]
583#[rune(item = ::std::collections::hash_set)]
584struct Iter {
585    iter: IterRef<()>,
586}
587
588impl Iter {
589    #[rune::function(keep, instance, protocol = NEXT)]
590    pub(crate) fn next(&mut self) -> Option<Value> {
591        let (value, ()) = self.iter.next()?;
592        Some(value)
593    }
594
595    #[rune::function(keep, instance, protocol = SIZE_HINT)]
596    fn size_hint(&self) -> (usize, Option<usize>) {
597        self.iter.size_hint()
598    }
599
600    #[rune::function(keep, instance, protocol = LEN)]
601    fn len(&self) -> usize {
602        self.iter.len()
603    }
604}
605
606#[derive(Any)]
607#[rune(item = ::std::collections::hash_set)]
608struct Intersection {
609    this: IterRef<()>,
610    other: Option<Ref<HashSet>>,
611}
612
613impl Intersection {
614    #[rune::function(keep, instance, protocol = NEXT)]
615    pub(crate) fn next(&mut self) -> VmResult<Option<Value>> {
616        let mut caller = EnvProtocolCaller;
617
618        let Some(other) = &self.other else {
619            return VmResult::Ok(None);
620        };
621
622        for (key, ()) in self.this.by_ref() {
623            let c = vm_try!(other.table.get(&key, &mut caller)).is_some();
624
625            if c {
626                return VmResult::Ok(Some(key));
627            }
628        }
629
630        self.other = None;
631        VmResult::Ok(None)
632    }
633
634    #[rune::function(keep, instance, protocol = SIZE_HINT)]
635    fn size_hint(&self) -> (usize, Option<usize>) {
636        let (_, upper) = self.this.size_hint();
637        (0, upper)
638    }
639}
640
641#[derive(Any)]
642#[rune(item = ::std::collections::hash_set)]
643struct Difference {
644    this: IterRef<()>,
645    other: Option<Ref<HashSet>>,
646}
647
648impl Difference {
649    #[rune::function(keep, instance, protocol = NEXT)]
650    pub(crate) fn next(&mut self) -> VmResult<Option<Value>> {
651        let mut caller = EnvProtocolCaller;
652
653        let Some(other) = &self.other else {
654            return VmResult::Ok(None);
655        };
656
657        for (key, ()) in self.this.by_ref() {
658            let c = vm_try!(other.table.get(&key, &mut caller)).is_some();
659
660            if !c {
661                return VmResult::Ok(Some(key));
662            }
663        }
664
665        self.other = None;
666        VmResult::Ok(None)
667    }
668
669    #[rune::function(keep, instance, protocol = SIZE_HINT)]
670    fn size_hint(&self) -> (usize, Option<usize>) {
671        let (_, upper) = self.this.size_hint();
672        (0, upper)
673    }
674}
675
676#[derive(Any)]
677#[rune(item = ::std::collections::hash_set)]
678struct Union {
679    this: ptr::NonNull<Table<()>>,
680    this_iter: RawIter<(Value, ())>,
681    other_iter: RawIter<(Value, ())>,
682    _guards: (RawAnyGuard, RawAnyGuard),
683}
684
685impl Union {
686    #[rune::function(keep, instance, protocol = NEXT)]
687    fn next(&mut self) -> VmResult<Option<Value>> {
688        // SAFETY: we're holding onto the ref guards for both collections during
689        // iteration, so this is valid for the lifetime of the iterator.
690        unsafe {
691            if let Some(bucket) = self.this_iter.next() {
692                let (value, ()) = bucket.as_ref();
693                return VmResult::Ok(Some(value.clone()));
694            }
695
696            let mut caller = EnvProtocolCaller;
697
698            for bucket in self.other_iter.by_ref() {
699                let (key, ()) = bucket.as_ref();
700
701                if vm_try!(self.this.as_ref().get(key, &mut caller)).is_none() {
702                    return VmResult::Ok(Some(key.clone()));
703                }
704            }
705
706            VmResult::Ok(None)
707        }
708    }
709}