Skip to main content

kevy_map/
set.rs

1//! `HashSet`-shaped wrapper over [`KevyMap<K, ()>`] — same per-shard /
2//! single-trust-domain assumptions; exposes the underlying map's bucket-addr
3//! API via [`KevySet::as_map`].
4
5use std::borrow::Borrow;
6use std::fmt;
7
8use kevy_hash::KevyHash;
9
10use crate::iter::Iter;
11use crate::map::KevyMap;
12
13/// `HashSet`-shaped wrapper over [`KevyMap<K, ()>`].
14///
15/// Carries the same per-shard / single-trust-domain assumptions; differs from
16/// `std::HashSet` only by hashing through [`KevyHash`] (one-call inlinable)
17/// and exposing the underlying `KevyMap`'s bucket-address API via
18/// [`KevySet::as_map`] for callers that want prefetch.
19pub struct KevySet<K>(KevyMap<K, ()>);
20
21impl<K> KevySet<K> {
22    /// Construct an empty set without allocating.
23    pub fn new() -> Self {
24        Self(KevyMap::new())
25    }
26
27    /// Construct a set sized for `cap_hint` members without growing.
28    pub fn with_capacity(cap_hint: usize) -> Self {
29        Self(KevyMap::with_capacity(cap_hint))
30    }
31
32    /// Live member count.
33    #[inline]
34    pub fn len(&self) -> usize {
35        self.0.len()
36    }
37    /// Whether `len() == 0`.
38    #[inline]
39    pub fn is_empty(&self) -> bool {
40        self.0.is_empty()
41    }
42    /// Allocated slot count of the underlying map.
43    #[inline]
44    pub fn capacity(&self) -> usize {
45        self.0.capacity()
46    }
47    /// Drop every member and reset the metadata. Keeps the allocation.
48    pub fn clear(&mut self) {
49        self.0.clear();
50    }
51
52    /// `&K` iterator over all members (unspecified order).
53    pub fn iter(&self) -> SetIter<'_, K> {
54        SetIter(self.0.iter())
55    }
56
57    /// Borrow the underlying map (gives access to the bucket-addr / prefetch
58    /// API).
59    pub fn as_map(&self) -> &KevyMap<K, ()> {
60        &self.0
61    }
62}
63
64impl<K: KevyHash + Eq> KevySet<K> {
65    /// Insert `key`. Returns `true` if newly added, `false` if it was already
66    /// present (matches `HashSet::insert`).
67    pub fn insert(&mut self, key: K) -> bool {
68        self.0.insert(key, ()).is_none()
69    }
70}
71
72impl<K> KevySet<K> {
73    /// Whether `key` is a member of the set.
74    pub fn contains<Q>(&self, key: &Q) -> bool
75    where
76        K: Borrow<Q>,
77        Q: KevyHash + Eq + ?Sized,
78    {
79        self.0.contains_key(key)
80    }
81
82    /// Remove `key`; returns `true` if it was present (matches `HashSet::remove`).
83    pub fn remove<Q>(&mut self, key: &Q) -> bool
84    where
85        K: Borrow<Q>,
86        Q: KevyHash + Eq + ?Sized,
87    {
88        self.0.remove(key).is_some()
89    }
90}
91
92impl<K> Default for KevySet<K> {
93    fn default() -> Self {
94        Self::new()
95    }
96}
97
98impl<K: fmt::Debug> fmt::Debug for KevySet<K> {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        f.debug_set().entries(self.iter()).finish()
101    }
102}
103
104/// `&K` iterator over all members of a [`KevySet`]; order unspecified.
105pub struct SetIter<'a, K>(Iter<'a, K, ()>);
106
107impl<'a, K> Iterator for SetIter<'a, K> {
108    type Item = &'a K;
109    fn next(&mut self) -> Option<Self::Item> {
110        self.0.next().map(|(k, _)| k)
111    }
112}
113
114impl<'a, K> IntoIterator for &'a KevySet<K> {
115    type Item = &'a K;
116    type IntoIter = SetIter<'a, K>;
117    fn into_iter(self) -> Self::IntoIter {
118        self.iter()
119    }
120}
121
122impl<K: KevyHash + Eq> FromIterator<K> for KevySet<K> {
123    fn from_iter<I: IntoIterator<Item = K>>(iter: I) -> Self {
124        let iter = iter.into_iter();
125        let mut s = match iter.size_hint() {
126            (lo, Some(hi)) if hi <= lo.saturating_mul(2) => Self::with_capacity(hi),
127            (lo, _) => Self::with_capacity(lo),
128        };
129        for k in iter {
130            s.insert(k);
131        }
132        s
133    }
134}
135
136impl<K: KevyHash + Eq> Extend<K> for KevySet<K> {
137    fn extend<I: IntoIterator<Item = K>>(&mut self, iter: I) {
138        for k in iter {
139            self.insert(k);
140        }
141    }
142}