nonempty_collections/set.rs
1//! Non-empty Sets.
2
3use core::fmt;
4use std::borrow::Borrow;
5use std::collections::HashSet;
6use std::hash::BuildHasher;
7use std::hash::Hash;
8use std::num::NonZeroUsize;
9
10#[cfg(feature = "serde")]
11use serde::Deserialize;
12#[cfg(feature = "serde")]
13use serde::Serialize;
14
15use crate::iter::NonEmptyIterator;
16use crate::FromNonEmptyIterator;
17use crate::IntoIteratorExt;
18use crate::IntoNonEmptyIterator;
19
20/// Like the [`crate::nev!`] macro, but for Sets. A nice short-hand for
21/// constructing [`NESet`] values.
22///
23/// ```
24/// use nonempty_collections::nes;
25///
26/// let s = nes![1, 2, 2, 3,];
27/// assert_eq!(3, s.len().get());
28/// ```
29#[macro_export]
30macro_rules! nes {
31 ($h:expr, $( $x:expr ),* $(,)?) => {{
32 let mut set = $crate::NESet::new($h);
33 $( set.insert($x); )*
34 set
35 }};
36 ($h:expr) => {
37 $crate::NESet::new($h)
38 }
39}
40
41/// A non-empty, growable `HashSet`.
42///
43/// # Construction and Access
44///
45/// The [`nes`] macro is the simplest way to construct an `NESet`:
46///
47/// ```
48/// use nonempty_collections::*;
49///
50/// let s = nes![1, 1, 2, 2, 3, 3, 4, 4];
51/// let mut v: NEVec<_> = s.nonempty_iter().collect();
52/// v.sort();
53/// assert_eq!(nev![&1, &2, &3, &4], v);
54/// ```
55///
56///
57/// ```
58/// use nonempty_collections::nes;
59///
60/// let s = nes!["Fëanor", "Fingolfin", "Finarfin"];
61/// assert!(s.contains(&"Fëanor"));
62/// ```
63///
64/// # Conversion
65///
66/// If you have a [`HashSet`] but want an `NESet`, try [`NESet::try_from_set`].
67/// Naturally, this might not succeed.
68///
69/// If you have an `NESet` but want a `HashSet`, try their corresponding
70/// [`From`] instance. This will always succeed.
71///
72/// ```
73/// use std::collections::HashSet;
74///
75/// use nonempty_collections::nes;
76///
77/// let n0 = nes![1, 2, 3];
78/// let s0 = HashSet::from(n0);
79///
80/// // Or just use `Into`.
81/// let n1 = nes![1, 2, 3];
82/// let s1: HashSet<_> = n1.into();
83/// ```
84///
85/// # API Differences with [`HashSet`]
86///
87/// Note that the following methods aren't implemented for `NESet`:
88///
89/// - `clear`
90/// - `drain`
91/// - `drain_filter`
92/// - `remove`
93/// - `retain`
94/// - `take`
95///
96/// As these methods are all "mutate-in-place" style and are difficult to
97/// reconcile with the non-emptiness guarantee.
98#[allow(clippy::unsafe_derive_deserialize)]
99#[cfg_attr(
100 feature = "serde",
101 derive(Serialize, Deserialize),
102 serde(bound(
103 serialize = "T: Eq + Hash + Clone + Serialize, S: Clone + BuildHasher",
104 deserialize = "T: Eq + Hash + Deserialize<'de>, S: Default + BuildHasher"
105 )),
106 serde(into = "HashSet<T, S>", try_from = "HashSet<T, S>")
107)]
108#[derive(Clone)]
109pub struct NESet<T, S = std::collections::hash_map::RandomState> {
110 inner: HashSet<T, S>,
111}
112
113impl<T, S> NESet<T, S> {
114 /// Returns the number of elements the set can hold without reallocating.
115 #[must_use]
116 pub fn capacity(&self) -> NonZeroUsize {
117 unsafe { NonZeroUsize::new_unchecked(self.inner.capacity()) }
118 }
119
120 /// Returns a reference to the set's `BuildHasher`.
121 #[must_use]
122 pub fn hasher(&self) -> &S {
123 self.inner.hasher()
124 }
125
126 /// Returns a regular iterator over the values in this non-empty set.
127 ///
128 /// For a `NonEmptyIterator` see `Self::nonempty_iter()`.
129 pub fn iter(&self) -> std::collections::hash_set::Iter<'_, T> {
130 self.inner.iter()
131 }
132
133 /// An iterator visiting all elements in arbitrary order.
134 pub fn nonempty_iter(&self) -> Iter<'_, T> {
135 Iter {
136 iter: self.inner.iter(),
137 }
138 }
139
140 /// Returns the number of elements in the set. Always 1 or more.
141 ///
142 /// ```
143 /// use nonempty_collections::nes;
144 ///
145 /// let s = nes![1, 2, 3];
146 /// assert_eq!(3, s.len().get());
147 /// ```
148 #[must_use]
149 pub fn len(&self) -> NonZeroUsize {
150 unsafe { NonZeroUsize::new_unchecked(self.inner.len()) }
151 }
152
153 /// A `NESet` is never empty.
154 #[deprecated(since = "0.1.0", note = "A NESet is never empty.")]
155 #[must_use]
156 pub const fn is_empty(&self) -> bool {
157 false
158 }
159}
160
161impl<T> NESet<T>
162where
163 T: Eq + Hash,
164{
165 /// Creates a new `NESet` with a single element.
166 #[must_use]
167 pub fn new(value: T) -> Self {
168 let mut inner = HashSet::new();
169 inner.insert(value);
170 Self { inner }
171 }
172
173 /// Creates a new `NESet` with a single element and specified capacity.
174 ///
175 /// ```
176 /// use std::hash::RandomState;
177 /// use std::num::NonZeroUsize;
178 ///
179 /// use nonempty_collections::*;
180 /// let set = NESet::with_capacity(NonZeroUsize::MIN, "hello");
181 /// assert_eq!(nes! {"hello"}, set);
182 /// assert!(set.capacity().get() >= 1);
183 /// ```
184 #[must_use]
185 pub fn with_capacity(capacity: NonZeroUsize, value: T) -> NESet<T> {
186 let mut inner = HashSet::with_capacity(capacity.get());
187 inner.insert(value);
188 NESet { inner }
189 }
190}
191
192impl<T, S> NESet<T, S>
193where
194 T: Eq + Hash,
195 S: BuildHasher,
196{
197 /// Attempt a conversion from a [`HashSet`], consuming the given `HashSet`.
198 /// Will return `None` if the `HashSet` is empty.
199 ///
200 /// ```
201 /// use std::collections::HashSet;
202 ///
203 /// use nonempty_collections::nes;
204 /// use nonempty_collections::NESet;
205 ///
206 /// let mut s = HashSet::new();
207 /// s.extend([1, 2, 3]);
208 ///
209 /// let n = NESet::try_from_set(s);
210 /// assert_eq!(Some(nes![1, 2, 3]), n);
211 /// let s: HashSet<()> = HashSet::new();
212 /// assert_eq!(None, NESet::try_from_set(s));
213 /// ```
214 #[must_use]
215 pub fn try_from_set(set: HashSet<T, S>) -> Option<NESet<T, S>> {
216 if set.is_empty() {
217 None
218 } else {
219 Some(NESet { inner: set })
220 }
221 }
222
223 /// Returns true if the set contains a value.
224 ///
225 /// ```
226 /// use nonempty_collections::nes;
227 ///
228 /// let s = nes![1, 2, 3];
229 /// assert!(s.contains(&3));
230 /// assert!(!s.contains(&10));
231 /// ```
232 #[must_use]
233 pub fn contains<Q>(&self, value: &Q) -> bool
234 where
235 T: Borrow<Q>,
236 Q: Eq + Hash + ?Sized,
237 {
238 self.inner.contains(value)
239 }
240
241 /// Visits the values representing the difference, i.e., the values that are
242 /// in `self` but not in `other`.
243 ///
244 /// ```
245 /// use nonempty_collections::nes;
246 ///
247 /// let s0 = nes![1, 2, 3];
248 /// let s1 = nes![3, 4, 5];
249 /// let mut v: Vec<_> = s0.difference(&s1).collect();
250 /// v.sort();
251 /// assert_eq!(vec![&1, &2], v);
252 /// ```
253 pub fn difference<'a>(
254 &'a self,
255 other: &'a NESet<T, S>,
256 ) -> std::collections::hash_set::Difference<'a, T, S> {
257 self.inner.difference(&other.inner)
258 }
259
260 /// Returns a reference to the value in the set, if any, that is equal to
261 /// the given value.
262 ///
263 /// The value may be any borrowed form of the set’s value type, but `Hash`
264 /// and `Eq` on the borrowed form must match those for the value type.
265 ///
266 /// ```
267 /// use nonempty_collections::nes;
268 ///
269 /// let s = nes![1, 2, 3];
270 /// assert_eq!(Some(&3), s.get(&3));
271 /// assert_eq!(None, s.get(&10));
272 /// ```
273 #[must_use]
274 pub fn get<Q>(&self, value: &Q) -> Option<&T>
275 where
276 T: Borrow<Q>,
277 Q: Eq + Hash,
278 {
279 self.inner.get(value)
280 }
281
282 /// Adds a value to the set.
283 ///
284 /// If the set did not have this value present, `true` is returned.
285 ///
286 /// If the set did have this value present, `false` is returned.
287 ///
288 /// ```
289 /// use nonempty_collections::nes;
290 ///
291 /// let mut s = nes![1, 2, 3];
292 /// assert_eq!(false, s.insert(2));
293 /// assert_eq!(true, s.insert(4));
294 /// ```
295 pub fn insert(&mut self, value: T) -> bool {
296 self.inner.insert(value)
297 }
298
299 /// Visits the values representing the interesection, i.e., the values that
300 /// are both in `self` and `other`.
301 ///
302 /// ```
303 /// use nonempty_collections::nes;
304 ///
305 /// let s0 = nes![1, 2, 3];
306 /// let s1 = nes![3, 4, 5];
307 /// let mut v: Vec<_> = s0.intersection(&s1).collect();
308 /// v.sort();
309 /// assert_eq!(vec![&3], v);
310 /// ```
311 pub fn intersection<'a>(
312 &'a self,
313 other: &'a NESet<T, S>,
314 ) -> std::collections::hash_set::Intersection<'a, T, S> {
315 self.inner.intersection(&other.inner)
316 }
317
318 /// Returns `true` if `self` has no elements in common with `other`.
319 /// This is equivalent to checking for an empty intersection.
320 ///
321 /// ```
322 /// use nonempty_collections::nes;
323 ///
324 /// let s0 = nes![1, 2, 3];
325 /// let s1 = nes![4, 5, 6];
326 /// assert!(s0.is_disjoint(&s1));
327 /// ```
328 #[must_use]
329 pub fn is_disjoint(&self, other: &NESet<T, S>) -> bool {
330 self.inner.is_disjoint(&other.inner)
331 }
332
333 /// Returns `true` if the set is a subset of another, i.e., `other` contains
334 /// at least all the values in `self`.
335 ///
336 /// ```
337 /// use nonempty_collections::nes;
338 ///
339 /// let sub = nes![1, 2, 3];
340 /// let sup = nes![1, 2, 3, 4];
341 ///
342 /// assert!(sub.is_subset(&sup));
343 /// assert!(!sup.is_subset(&sub));
344 /// ```
345 #[must_use]
346 pub fn is_subset(&self, other: &NESet<T, S>) -> bool {
347 self.inner.is_subset(&other.inner)
348 }
349
350 /// Returns `true` if the set is a superset of another, i.e., `self`
351 /// contains at least all the values in `other`.
352 ///
353 /// ```
354 /// use nonempty_collections::nes;
355 ///
356 /// let sub = nes![1, 2, 3];
357 /// let sup = nes![1, 2, 3, 4];
358 ///
359 /// assert!(sup.is_superset(&sub));
360 /// assert!(!sub.is_superset(&sup));
361 /// ```
362 #[must_use]
363 pub fn is_superset(&self, other: &NESet<T, S>) -> bool {
364 self.inner.is_superset(&other.inner)
365 }
366
367 /// Adds a value to the set, replacing the existing value, if any, that is
368 /// equal to the given one. Returns the replaced value.
369 pub fn replace(&mut self, value: T) -> Option<T> {
370 self.inner.replace(value)
371 }
372
373 /// Reserves capacity for at least `additional` more elements to be inserted
374 /// in the `NESet`. The collection may reserve more space to avoid frequent
375 /// reallocations.
376 ///
377 /// # Panics
378 ///
379 /// Panics if the new allocation size overflows `usize`.
380 pub fn reserve(&mut self, additional: usize) {
381 self.inner.reserve(additional);
382 }
383
384 /// Shrinks the capacity of the set as much as possible. It will drop down
385 /// as much as possible while maintaining the internal rules and possibly
386 /// leaving some space in accordance with the resize policy.
387 pub fn shrink_to_fit(&mut self) {
388 self.inner.shrink_to_fit();
389 }
390
391 /// Visits the values representing the union, i.e., all the values in `self`
392 /// or `other`, without duplicates.
393 ///
394 /// Note that a Union is always non-empty.
395 ///
396 /// ```
397 /// use nonempty_collections::*;
398 ///
399 /// let s0 = nes![1, 2, 3];
400 /// let s1 = nes![3, 4, 5];
401 /// let mut v: NEVec<_> = s0.union(&s1).collect();
402 /// v.sort();
403 /// assert_eq!(nev![&1, &2, &3, &4, &5], v);
404 /// ```
405 pub fn union<'a>(&'a self, other: &'a NESet<T, S>) -> Union<'a, T, S> {
406 Union {
407 inner: self.inner.union(&other.inner),
408 }
409 }
410
411 /// See [`HashSet::with_capacity_and_hasher`].
412 #[must_use]
413 pub fn with_capacity_and_hasher(capacity: NonZeroUsize, hasher: S, value: T) -> NESet<T, S> {
414 let mut inner = HashSet::with_capacity_and_hasher(capacity.get(), hasher);
415 inner.insert(value);
416 NESet { inner }
417 }
418
419 /// See [`HashSet::with_hasher`].
420 #[must_use]
421 pub fn with_hasher(hasher: S, value: T) -> NESet<T, S> {
422 let mut inner = HashSet::with_hasher(hasher);
423 inner.insert(value);
424 NESet { inner }
425 }
426}
427
428impl<T, S> PartialEq for NESet<T, S>
429where
430 T: Eq + Hash,
431 S: BuildHasher,
432{
433 /// ```
434 /// use nonempty_collections::nes;
435 ///
436 /// let s0 = nes![1, 2, 3];
437 /// let s1 = nes![1, 2, 3];
438 /// let s2 = nes![1, 2];
439 /// let s3 = nes![1, 2, 3, 4];
440 ///
441 /// assert!(s0 == s1);
442 /// assert!(s0 != s2);
443 /// assert!(s0 != s3);
444 /// ```
445 fn eq(&self, other: &Self) -> bool {
446 self.len() == other.len() && self.intersection(other).count() == self.len().get()
447 }
448}
449
450impl<T, S> Eq for NESet<T, S>
451where
452 T: Eq + Hash,
453 S: BuildHasher,
454{
455}
456
457impl<T, S> IntoNonEmptyIterator for NESet<T, S> {
458 type IntoNEIter = IntoIter<T>;
459
460 fn into_nonempty_iter(self) -> Self::IntoNEIter {
461 IntoIter {
462 iter: self.inner.into_iter(),
463 }
464 }
465}
466
467impl<'a, T, S> IntoNonEmptyIterator for &'a NESet<T, S> {
468 type IntoNEIter = Iter<'a, T>;
469
470 fn into_nonempty_iter(self) -> Self::IntoNEIter {
471 self.nonempty_iter()
472 }
473}
474
475impl<T, S> IntoIterator for NESet<T, S> {
476 type Item = T;
477
478 type IntoIter = std::collections::hash_set::IntoIter<T>;
479
480 fn into_iter(self) -> Self::IntoIter {
481 self.inner.into_iter()
482 }
483}
484
485impl<'a, T, S> IntoIterator for &'a NESet<T, S> {
486 type Item = &'a T;
487
488 type IntoIter = std::collections::hash_set::Iter<'a, T>;
489
490 fn into_iter(self) -> Self::IntoIter {
491 self.iter()
492 }
493}
494
495/// ```
496/// use nonempty_collections::*;
497///
498/// let s0 = nes![1, 2, 3];
499/// let s1: NESet<_> = s0.nonempty_iter().cloned().collect();
500/// assert_eq!(s0, s1);
501/// ```
502impl<T, S> FromNonEmptyIterator<T> for NESet<T, S>
503where
504 T: Eq + Hash,
505 S: BuildHasher + Default,
506{
507 /// ```
508 /// use nonempty_collections::*;
509 ///
510 /// let v = nev![1, 1, 2, 3, 2];
511 /// let s = NESet::from_nonempty_iter(v);
512 ///
513 /// assert_eq!(nes![1, 2, 3], s);
514 /// ```
515 fn from_nonempty_iter<I>(iter: I) -> Self
516 where
517 I: IntoNonEmptyIterator<Item = T>,
518 {
519 NESet {
520 inner: iter.into_nonempty_iter().into_iter().collect(),
521 }
522 }
523}
524
525/// A non-empty iterator over the values of an [`NESet`].
526#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
527pub struct Iter<'a, T: 'a> {
528 iter: std::collections::hash_set::Iter<'a, T>,
529}
530
531impl<'a, T: 'a> IntoIterator for Iter<'a, T> {
532 type Item = &'a T;
533
534 type IntoIter = std::collections::hash_set::Iter<'a, T>;
535
536 fn into_iter(self) -> Self::IntoIter {
537 self.iter
538 }
539}
540
541impl<T> NonEmptyIterator for Iter<'_, T> {}
542
543impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
544 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
545 self.iter.fmt(f)
546 }
547}
548
549/// An owned non-empty iterator over the values of an [`NESet`].
550#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
551pub struct IntoIter<T> {
552 iter: std::collections::hash_set::IntoIter<T>,
553}
554
555impl<T> IntoIterator for IntoIter<T> {
556 type Item = T;
557
558 type IntoIter = std::collections::hash_set::IntoIter<T>;
559
560 fn into_iter(self) -> Self::IntoIter {
561 self.iter
562 }
563}
564
565impl<T> NonEmptyIterator for IntoIter<T> {}
566
567impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569 self.iter.fmt(f)
570 }
571}
572
573/// A non-empty iterator producing elements in the union of two [`NESet`]s.
574#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
575pub struct Union<'a, T: 'a, S: 'a> {
576 inner: std::collections::hash_set::Union<'a, T, S>,
577}
578
579impl<'a, T, S> IntoIterator for Union<'a, T, S>
580where
581 T: Eq + Hash,
582 S: BuildHasher,
583{
584 type Item = &'a T;
585
586 type IntoIter = std::collections::hash_set::Union<'a, T, S>;
587
588 fn into_iter(self) -> Self::IntoIter {
589 self.inner
590 }
591}
592
593impl<T, S> NonEmptyIterator for Union<'_, T, S>
594where
595 T: Eq + Hash,
596 S: BuildHasher,
597{
598}
599
600impl<T, S> fmt::Debug for Union<'_, T, S>
601where
602 T: fmt::Debug + Eq + Hash,
603 S: BuildHasher,
604{
605 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
606 self.inner.fmt(f)
607 }
608}
609
610impl<T, S> From<NESet<T, S>> for HashSet<T, S>
611where
612 T: Eq + Hash,
613 S: BuildHasher,
614{
615 /// ```
616 /// use std::collections::HashSet;
617 ///
618 /// use nonempty_collections::nes;
619 ///
620 /// let s: HashSet<_> = nes![1, 2, 3].into();
621 /// let mut v: Vec<_> = s.into_iter().collect();
622 /// v.sort();
623 /// assert_eq!(vec![1, 2, 3], v);
624 /// ```
625 fn from(s: NESet<T, S>) -> Self {
626 s.inner
627 }
628}
629
630impl<T: fmt::Debug, S> fmt::Debug for NESet<T, S> {
631 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
632 self.inner.fmt(f)
633 }
634}
635
636impl<T, S> TryFrom<HashSet<T, S>> for NESet<T, S>
637where
638 T: Eq + Hash,
639 S: BuildHasher + Default,
640{
641 type Error = crate::Error;
642
643 fn try_from(set: HashSet<T, S>) -> Result<Self, Self::Error> {
644 let ne = set
645 .try_into_nonempty_iter()
646 .ok_or(crate::Error::Empty)?
647 .collect();
648
649 Ok(ne)
650 }
651}
652
653#[cfg(test)]
654mod test {
655 use maplit::hashset;
656
657 #[test]
658 fn debug_impl() {
659 let expected = format!("{:?}", hashset! {0});
660 let actual = format!("{:?}", nes! {0});
661 assert_eq!(expected, actual);
662 }
663
664 #[test]
665 fn iter_debug_impl() {
666 let expected = format!("{:?}", hashset! {0}.iter());
667 let actual = format!("{:?}", nes! {0}.nonempty_iter());
668 assert_eq!(expected, actual);
669 }
670}
671
672#[cfg(feature = "serde")]
673#[cfg(test)]
674mod serde_tests {
675 use std::collections::HashSet;
676
677 use crate::nes;
678 use crate::NESet;
679
680 #[test]
681 fn json() {
682 let set0 = nes![1, 1, 2, 3, 2, 1, 4];
683 let j = serde_json::to_string(&set0).unwrap();
684 let set1 = serde_json::from_str(&j).unwrap();
685 assert_eq!(set0, set1);
686
687 let empty: HashSet<usize> = HashSet::new();
688 let j = serde_json::to_string(&empty).unwrap();
689 let bad = serde_json::from_str::<NESet<usize>>(&j);
690 assert!(bad.is_err());
691 }
692}