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}