1use left_right::aliasing::{Aliased, DropBehavior};
2use std::borrow::Borrow;
3use std::fmt;
4use std::hash::{BuildHasher, Hash};
5
6const BAG_THRESHOLD: usize = 32;
8
9#[repr(transparent)]
11pub struct Values<T, S = std::collections::hash_map::RandomState>(
12 pub(crate) ValuesInner<T, S, crate::aliasing::NoDrop>,
13);
14
15impl<T, S> Default for Values<T, S> {
16 fn default() -> Self {
17 Values(ValuesInner::Short(Default::default()))
18 }
19}
20
21impl<T, S> fmt::Debug for Values<T, S>
22where
23 T: fmt::Debug,
24 S: BuildHasher,
25{
26 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
27 self.0.fmt(fmt)
28 }
29}
30
31pub(crate) enum ValuesInner<T, S, D>
32where
33 D: DropBehavior,
34{
35 Short(smallvec::SmallVec<[Aliased<T, D>; 1]>),
36 Long(hashbag::HashBag<Aliased<T, D>, S>),
37}
38
39impl<T, S> From<ValuesInner<T, S, crate::aliasing::NoDrop>> for Values<T, S> {
40 fn from(v: ValuesInner<T, S, crate::aliasing::NoDrop>) -> Self {
41 Values(v)
42 }
43}
44
45impl<T, S, D> fmt::Debug for ValuesInner<T, S, D>
46where
47 D: DropBehavior,
48 T: fmt::Debug,
49 S: BuildHasher,
50{
51 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
52 match self {
53 ValuesInner::Short(ref v) => fmt.debug_set().entries(v.iter()).finish(),
54 ValuesInner::Long(ref v) => fmt.debug_set().entries(v.iter()).finish(),
55 }
56 }
57}
58
59impl<T, S> Values<T, S> {
60 pub fn len(&self) -> usize {
62 match self.0 {
63 ValuesInner::Short(ref v) => v.len(),
64 ValuesInner::Long(ref v) => v.len(),
65 }
66 }
67
68 pub fn is_empty(&self) -> bool {
70 match self.0 {
71 ValuesInner::Short(ref v) => v.is_empty(),
72 ValuesInner::Long(ref v) => v.is_empty(),
73 }
74 }
75
76 pub fn capacity(&self) -> usize {
78 match self.0 {
79 ValuesInner::Short(ref v) => v.capacity(),
80 ValuesInner::Long(ref v) => v.capacity(),
81 }
82 }
83
84 pub fn iter(&self) -> ValuesIter<'_, T, S> {
88 match self.0 {
89 ValuesInner::Short(ref v) => ValuesIter(ValuesIterInner::Short(v.iter())),
90 ValuesInner::Long(ref v) => ValuesIter(ValuesIterInner::Long(v.iter())),
91 }
92 }
93
94 pub fn get_one(&self) -> Option<&T> {
100 match self.0 {
101 ValuesInner::Short(ref v) => v.get(0).map(|v| &**v),
102 ValuesInner::Long(ref v) => v.iter().next().map(|v| &**v),
103 }
104 }
105
106 pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
111 where
112 Aliased<T, crate::aliasing::NoDrop>: Borrow<Q>,
113 Q: Eq + Hash,
114 T: Eq + Hash,
115 S: BuildHasher,
116 {
117 match self.0 {
118 ValuesInner::Short(ref v) => v.iter().any(|v| v.borrow() == value),
119 ValuesInner::Long(ref v) => v.contains(value) != 0,
120 }
121 }
122
123 #[cfg(test)]
124 fn is_short(&self) -> bool {
125 matches!(self.0, ValuesInner::Short(_))
126 }
127}
128
129impl<'a, T, S> IntoIterator for &'a Values<T, S> {
130 type IntoIter = ValuesIter<'a, T, S>;
131 type Item = &'a T;
132 fn into_iter(self) -> Self::IntoIter {
133 self.iter()
134 }
135}
136
137pub struct ValuesIter<'a, T, S>(ValuesIterInner<'a, T, S>);
138
139#[non_exhaustive]
140enum ValuesIterInner<'a, T, S> {
141 Short(<&'a smallvec::SmallVec<[Aliased<T, crate::aliasing::NoDrop>; 1]> as IntoIterator>::IntoIter),
142 Long(<&'a hashbag::HashBag<Aliased<T, crate::aliasing::NoDrop>, S> as IntoIterator>::IntoIter),
143}
144
145impl<'a, T, S> fmt::Debug for ValuesIter<'a, T, S>
146where
147 T: fmt::Debug,
148{
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 match self.0 {
151 ValuesIterInner::Short(ref it) => f.debug_tuple("Short").field(it).finish(),
152 ValuesIterInner::Long(ref it) => f.debug_tuple("Long").field(it).finish(),
153 }
154 }
155}
156
157impl<'a, T, S> Iterator for ValuesIter<'a, T, S> {
158 type Item = &'a T;
159 fn next(&mut self) -> Option<Self::Item> {
160 match self.0 {
161 ValuesIterInner::Short(ref mut it) => it.next().map(|v| &**v),
162 ValuesIterInner::Long(ref mut it) => it.next().map(|v| &**v),
163 }
164 }
165
166 fn size_hint(&self) -> (usize, Option<usize>) {
167 match self.0 {
168 ValuesIterInner::Short(ref it) => it.size_hint(),
169 ValuesIterInner::Long(ref it) => it.size_hint(),
170 }
171 }
172}
173
174impl<'a, T, S> ExactSizeIterator for ValuesIter<'a, T, S>
175where
176 <&'a smallvec::SmallVec<[T; 1]> as IntoIterator>::IntoIter: ExactSizeIterator,
177 <&'a hashbag::HashBag<T, S> as IntoIterator>::IntoIter: ExactSizeIterator,
178{
179}
180
181impl<'a, T, S> std::iter::FusedIterator for ValuesIter<'a, T, S>
182where
183 <&'a smallvec::SmallVec<[T; 1]> as IntoIterator>::IntoIter: std::iter::FusedIterator,
184 <&'a hashbag::HashBag<T, S> as IntoIterator>::IntoIter: std::iter::FusedIterator,
185{
186}
187
188impl<T, S, D> ValuesInner<T, S, D>
189where
190 D: DropBehavior,
191 T: Eq + Hash,
192 S: BuildHasher + Clone,
193{
194 pub(crate) fn new() -> Self {
195 ValuesInner::Short(smallvec::SmallVec::new())
196 }
197
198 pub(crate) fn with_capacity_and_hasher(capacity: usize, hasher: &S) -> Self {
199 if capacity > BAG_THRESHOLD {
200 ValuesInner::Long(hashbag::HashBag::with_capacity_and_hasher(
201 capacity,
202 hasher.clone(),
203 ))
204 } else {
205 ValuesInner::Short(smallvec::SmallVec::with_capacity(capacity))
206 }
207 }
208
209 pub(crate) fn shrink_to_fit(&mut self) {
210 match self {
211 ValuesInner::Short(ref mut v) => v.shrink_to_fit(),
212 ValuesInner::Long(ref mut v) => {
213 if v.len() < BAG_THRESHOLD && v.len() == v.set_len() {
224 let mut short = smallvec::SmallVec::with_capacity(v.len());
225 for (row, n) in v.drain() {
237 assert_eq!(n, 1);
238 short.push(row);
239 }
240 *self = ValuesInner::Short(short);
241 } else {
242 v.shrink_to_fit();
243 }
244 }
245 }
246 }
247
248 pub(crate) fn clear(&mut self) {
249 match self {
251 ValuesInner::Short(ref mut v) => v.clear(),
252 ValuesInner::Long(ref mut v) => v.clear(),
253 }
254 }
255
256 pub(crate) fn swap_remove(&mut self, value: &T) {
257 match self {
258 ValuesInner::Short(ref mut v) => {
259 if let Some(i) = v.iter().position(|v| &**v == value) {
260 v.swap_remove(i);
261 }
262 }
263 ValuesInner::Long(ref mut v) => {
264 v.remove(value);
265 }
266 }
267 }
268
269 fn baggify(&mut self, capacity: usize, hasher: &S) {
270 if let ValuesInner::Short(ref mut v) = self {
271 let mut long = hashbag::HashBag::with_capacity_and_hasher(capacity, hasher.clone());
272
273 long.extend(v.drain(..));
280 *self = ValuesInner::Long(long);
281 }
282 }
283
284 pub(crate) fn reserve(&mut self, additional: usize, hasher: &S) {
285 match self {
286 ValuesInner::Short(ref mut v) => {
287 let n = v.len() + additional;
288 if n >= BAG_THRESHOLD {
289 self.baggify(n, hasher);
290 } else {
291 v.reserve(additional)
292 }
293 }
294 ValuesInner::Long(ref mut v) => v.reserve(additional),
295 }
296 }
297
298 pub(crate) fn push(&mut self, value: Aliased<T, D>, hasher: &S) {
299 match self {
300 ValuesInner::Short(ref mut v) => {
301 let n = v.len() + 1;
303 if n >= BAG_THRESHOLD {
304 self.baggify(n, hasher);
305 if let ValuesInner::Long(ref mut v) = self {
306 v.insert(value);
307 } else {
308 unreachable!();
309 }
310 } else {
311 v.push(value);
312 }
313 }
314 ValuesInner::Long(ref mut v) => {
315 v.insert(value);
316 }
317 }
318 }
319
320 pub(crate) fn retain<F>(&mut self, mut f: F)
321 where
322 F: FnMut(&T) -> bool,
323 {
324 match self {
325 ValuesInner::Short(ref mut v) => v.retain(|v| f(&*v)),
326 ValuesInner::Long(ref mut v) => v.retain(|v, n| if f(v) { n } else { 0 }),
327 }
328 }
329}
330
331impl<T, S> AsRef<Values<T, S>> for ValuesInner<T, S, crate::aliasing::NoDrop> {
332 fn as_ref(&self) -> &Values<T, S> {
333 unsafe { &*(self as *const _ as *const Values<T, S>) }
335 }
336}
337
338impl<T, S> ValuesInner<T, S, crate::aliasing::DoDrop>
339where
340 T: Eq + Hash,
341 S: BuildHasher + Clone,
342{
343 pub(crate) unsafe fn alias(
344 other: &ValuesInner<T, S, crate::aliasing::NoDrop>,
345 hasher: &S,
346 ) -> Self {
347 match &other {
348 ValuesInner::Short(s) => {
349 ValuesInner::Short(s.iter().map(|v| v.alias().change_drop()).collect())
350 }
351 ValuesInner::Long(l) => {
352 let mut long = hashbag::HashBag::with_hasher(hasher.clone());
353 long.extend(l.set_iter().map(|(v, n)| (v.alias().change_drop(), n)));
354 ValuesInner::Long(long)
355 }
356 }
357 }
358}
359
360#[cfg(test)]
361mod tests {
362 use super::*;
363 use std::collections::hash_map::RandomState;
364
365 macro_rules! assert_empty {
366 ($x:expr) => {
367 assert_eq!($x.len(), 0);
368 assert!($x.is_empty());
369 assert_eq!($x.iter().count(), 0);
370 assert_eq!($x.into_iter().count(), 0);
371 assert_eq!($x.get_one(), None);
372 };
373 }
374
375 macro_rules! assert_len {
376 ($x:expr, $n:expr) => {
377 assert_eq!($x.len(), $n);
378 assert!(!$x.is_empty());
379 assert_eq!($x.iter().count(), $n);
380 assert_eq!($x.into_iter().count(), $n);
381 };
382 }
383
384 #[test]
385 fn sensible_default() {
386 let v: Values<i32> = Values::default();
387 assert!(v.is_short());
388 assert_eq!(v.capacity(), 1);
389 assert_empty!(v);
390 }
391
392 #[test]
393 fn short_values() {
394 let hasher = RandomState::default();
395 let mut v = Values(ValuesInner::new());
396
397 let values = 0..BAG_THRESHOLD - 1;
398 let len = values.clone().count();
399 for i in values.clone() {
400 v.0.push(Aliased::from(i), &hasher);
401 }
402
403 for i in values.clone() {
404 assert!(v.contains(&i));
405 }
406 assert!(v.is_short());
407 assert_len!(v, len);
408 assert_eq!(v.get_one(), Some(&0));
409
410 v.0.clear();
411
412 assert_empty!(v);
413
414 assert!(v.capacity() > 1);
416 assert!(v.is_short());
417
418 v.0.shrink_to_fit();
419
420 assert_eq!(v.capacity(), 1);
421 }
422
423 #[test]
424 fn long_values() {
425 let hasher = RandomState::default();
426 let mut v = Values(ValuesInner::new());
427
428 let values = 0..BAG_THRESHOLD;
429 let len = values.clone().count();
430 for i in values.clone() {
431 v.0.push(Aliased::from(i), &hasher);
432 }
433
434 for i in values.clone() {
435 assert!(v.contains(&i));
436 }
437 assert!(!v.is_short());
438 assert_len!(v, len);
439 assert!(values.contains(v.get_one().unwrap()));
440
441 v.0.clear();
442
443 assert_empty!(v);
444
445 assert!(v.capacity() > 1);
447 assert!(!v.is_short());
448
449 v.0.shrink_to_fit();
450
451 assert!(v.is_short());
453 assert_eq!(v.capacity(), 1);
454 }
455}