1 use std::fmt::{self, Debug};
2 use std::slice;
3 
4 pub(crate) use self::ordered::OrderedSet;
5 pub(crate) use self::unordered::UnorderedSet;
6 
7 mod ordered {
8     use super::{Iter, UnorderedSet};
9     use std::hash::Hash;
10 
11     pub(crate) struct OrderedSet<T> {
12         set: UnorderedSet<T>,
13         vec: Vec<T>,
14     }
15 
16     impl<'a, T> OrderedSet<&'a T>
17     where
18         T: Hash + Eq,
19     {
new() -> Self20         pub(crate) fn new() -> Self {
21             OrderedSet {
22                 set: UnorderedSet::new(),
23                 vec: Vec::new(),
24             }
25         }
26 
insert(&mut self, value: &'a T) -> bool27         pub(crate) fn insert(&mut self, value: &'a T) -> bool {
28             let new = self.set.insert(value);
29             if new {
30                 self.vec.push(value);
31             }
32             new
33         }
34     }
35 
36     impl<'a, T> OrderedSet<&'a T> {
is_empty(&self) -> bool37         pub(crate) fn is_empty(&self) -> bool {
38             self.vec.is_empty()
39         }
40 
iter(&self) -> Iter<'_, 'a, T>41         pub(crate) fn iter(&self) -> Iter<'_, 'a, T> {
42             Iter(self.vec.iter())
43         }
44     }
45 
46     impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
47         type Item = &'a T;
48         type IntoIter = Iter<'s, 'a, T>;
into_iter(self) -> Self::IntoIter49         fn into_iter(self) -> Self::IntoIter {
50             self.iter()
51         }
52     }
53 }
54 
55 mod unordered {
56     use std::borrow::Borrow;
57     use std::collections::HashSet;
58     use std::hash::Hash;
59 
60     // Wrapper prohibits accidentally introducing iteration over the set, which
61     // could lead to nondeterministic generated code.
62     pub(crate) struct UnorderedSet<T>(HashSet<T>);
63 
64     impl<T> UnorderedSet<T>
65     where
66         T: Hash + Eq,
67     {
new() -> Self68         pub(crate) fn new() -> Self {
69             UnorderedSet(HashSet::new())
70         }
71 
insert(&mut self, value: T) -> bool72         pub(crate) fn insert(&mut self, value: T) -> bool {
73             self.0.insert(value)
74         }
75 
contains<Q>(&self, value: &Q) -> bool where T: Borrow<Q>, Q: ?Sized + Hash + Eq,76         pub(crate) fn contains<Q>(&self, value: &Q) -> bool
77         where
78             T: Borrow<Q>,
79             Q: ?Sized + Hash + Eq,
80         {
81             self.0.contains(value)
82         }
83 
84         #[allow(dead_code)] // only used by cxx-build, not cxxbridge-cmd
get<Q>(&self, value: &Q) -> Option<&T> where T: Borrow<Q>, Q: ?Sized + Hash + Eq,85         pub(crate) fn get<Q>(&self, value: &Q) -> Option<&T>
86         where
87             T: Borrow<Q>,
88             Q: ?Sized + Hash + Eq,
89         {
90             self.0.get(value)
91         }
92 
retain(&mut self, f: impl FnMut(&T) -> bool)93         pub(crate) fn retain(&mut self, f: impl FnMut(&T) -> bool) {
94             self.0.retain(f);
95         }
96     }
97 }
98 
99 pub(crate) struct Iter<'s, 'a, T>(slice::Iter<'s, &'a T>);
100 
101 impl<'s, 'a, T> Iterator for Iter<'s, 'a, T> {
102     type Item = &'a T;
103 
next(&mut self) -> Option<Self::Item>104     fn next(&mut self) -> Option<Self::Item> {
105         self.0.next().copied()
106     }
107 
size_hint(&self) -> (usize, Option<usize>)108     fn size_hint(&self) -> (usize, Option<usize>) {
109         self.0.size_hint()
110     }
111 }
112 
113 impl<'a, T> Debug for OrderedSet<&'a T>
114 where
115     T: Debug,
116 {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result117     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
118         formatter.debug_set().entries(self).finish()
119     }
120 }
121