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