blob: 6508f556efec653ea052176c9dc10759f04b3273 [file] [log] [blame]
David Tolnay599fad82020-10-03 19:42:16 -07001use std::fmt::{self, Debug};
David Tolnay7db73692019-10-20 14:51:12 -04002use std::slice;
3
David Tolnayecdd2d22020-11-03 19:36:12 -08004pub use self::ordered::OrderedSet;
David Tolnayc42de692020-11-03 19:30:38 -08005pub use self::unordered::UnorderedSet;
David Tolnay7db73692019-10-20 14:51:12 -04006
David Tolnayecdd2d22020-11-03 19:36:12 -08007mod ordered {
David Tolnayc42de692020-11-03 19:30:38 -08008 use super::{Iter, UnorderedSet};
David Tolnayecdd2d22020-11-03 19:36:12 -08009 use std::borrow::Borrow;
David Tolnayecdd2d22020-11-03 19:36:12 -080010 use std::hash::Hash;
11
12 pub struct OrderedSet<T> {
David Tolnayc42de692020-11-03 19:30:38 -080013 set: UnorderedSet<T>,
David Tolnayecdd2d22020-11-03 19:36:12 -080014 vec: Vec<T>,
15 }
16
17 impl<'a, T> OrderedSet<&'a T>
18 where
19 T: Hash + Eq,
20 {
21 pub fn new() -> Self {
22 OrderedSet {
David Tolnayc42de692020-11-03 19:30:38 -080023 set: UnorderedSet::new(),
David Tolnayecdd2d22020-11-03 19:36:12 -080024 vec: Vec::new(),
25 }
26 }
27
28 pub fn insert(&mut self, value: &'a T) -> bool {
29 let new = self.set.insert(value);
30 if new {
31 self.vec.push(value);
32 }
33 new
34 }
35
36 pub fn contains<Q>(&self, value: &Q) -> bool
37 where
38 &'a T: Borrow<Q>,
39 Q: ?Sized + Hash + Eq,
40 {
41 self.set.contains(value)
42 }
43
44 pub fn get<Q>(&self, value: &Q) -> Option<&'a T>
45 where
46 &'a T: Borrow<Q>,
47 Q: ?Sized + Hash + Eq,
48 {
49 self.set.get(value).copied()
David Tolnay7db73692019-10-20 14:51:12 -040050 }
51 }
52
David Tolnayecdd2d22020-11-03 19:36:12 -080053 impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
54 type Item = &'a T;
55 type IntoIter = Iter<'s, 'a, T>;
56 fn into_iter(self) -> Self::IntoIter {
57 Iter(self.vec.iter())
David Tolnay7db73692019-10-20 14:51:12 -040058 }
David Tolnay7db73692019-10-20 14:51:12 -040059 }
60}
61
David Tolnayc42de692020-11-03 19:30:38 -080062mod unordered {
63 use std::borrow::Borrow;
64 use std::collections::HashSet;
65 use std::hash::Hash;
66
67 // Wrapper prohibits accidentally introducing iteration over the set, which
68 // could lead to nondeterministic generated code.
69 pub struct UnorderedSet<T>(HashSet<T>);
70
71 impl<T> UnorderedSet<T>
72 where
73 T: Hash + Eq,
74 {
75 pub fn new() -> Self {
76 UnorderedSet(HashSet::new())
77 }
78
79 pub fn insert(&mut self, value: T) -> bool {
80 self.0.insert(value)
81 }
82
83 pub fn contains<Q>(&self, value: &Q) -> bool
84 where
85 T: Borrow<Q>,
86 Q: ?Sized + Hash + Eq,
87 {
88 self.0.contains(value)
89 }
90
91 pub fn get<Q>(&self, value: &Q) -> Option<&T>
92 where
93 T: Borrow<Q>,
94 Q: ?Sized + Hash + Eq,
95 {
96 self.0.get(value)
97 }
98 }
99}
100
David Tolnay7db73692019-10-20 14:51:12 -0400101pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
102
103impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
104 type Item = &'a T;
105 fn next(&mut self) -> Option<Self::Item> {
106 self.0.next().copied()
107 }
108}
David Tolnay599fad82020-10-03 19:42:16 -0700109
110impl<'a, T> Debug for OrderedSet<&'a T>
111where
112 T: Debug,
113{
114 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
115 formatter.debug_set().entries(self).finish()
116 }
117}