blob: 891df6066043974d367952e64dbfd3ebb7b82a2c [file] [log] [blame]
David Tolnayc86633d2020-10-03 23:48:06 -07001use std::borrow::Borrow;
David Tolnay7db73692019-10-20 14:51:12 -04002use std::collections::HashSet;
David Tolnay599fad82020-10-03 19:42:16 -07003use std::fmt::{self, Debug};
David Tolnay7db73692019-10-20 14:51:12 -04004use std::hash::Hash;
5use std::slice;
6
David Tolnay45f3f892020-08-29 19:19:56 -07007pub struct OrderedSet<T> {
8 set: HashSet<T>,
9 vec: Vec<T>,
David Tolnay7db73692019-10-20 14:51:12 -040010}
11
David Tolnay45f3f892020-08-29 19:19:56 -070012impl<'a, T> OrderedSet<&'a T>
David Tolnay7db73692019-10-20 14:51:12 -040013where
14 T: Hash + Eq,
15{
16 pub fn new() -> Self {
17 OrderedSet {
18 set: HashSet::new(),
19 vec: Vec::new(),
20 }
21 }
22
David Tolnayab914452020-05-04 00:21:37 -070023 pub fn insert(&mut self, value: &'a T) -> bool {
24 let new = self.set.insert(value);
25 if new {
David Tolnay7db73692019-10-20 14:51:12 -040026 self.vec.push(value);
27 }
David Tolnayab914452020-05-04 00:21:37 -070028 new
David Tolnay7db73692019-10-20 14:51:12 -040029 }
30
David Tolnayc86633d2020-10-03 23:48:06 -070031 pub fn contains<Q>(&self, value: &Q) -> bool
32 where
33 &'a T: Borrow<Q>,
34 Q: ?Sized + Hash + Eq,
35 {
David Tolnay7db73692019-10-20 14:51:12 -040036 self.set.contains(value)
37 }
38}
39
David Tolnay45f3f892020-08-29 19:19:56 -070040impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
David Tolnay7db73692019-10-20 14:51:12 -040041 type Item = &'a T;
42 type IntoIter = Iter<'s, 'a, T>;
43 fn into_iter(self) -> Self::IntoIter {
44 Iter(self.vec.iter())
45 }
46}
47
48pub struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
49
50impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
51 type Item = &'a T;
52 fn next(&mut self) -> Option<Self::Item> {
53 self.0.next().copied()
54 }
55}
David Tolnay599fad82020-10-03 19:42:16 -070056
57impl<'a, T> Debug for OrderedSet<&'a T>
58where
59 T: Debug,
60{
61 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
62 formatter.debug_set().entries(self).finish()
63 }
64}