1 | //! An order-preserving immutable set constructed at compile time. |
2 | use crate::{ordered_map, OrderedMap, PhfHash}; |
3 | use core::fmt; |
4 | use core::iter::FusedIterator; |
5 | use core::iter::IntoIterator; |
6 | use phf_shared::PhfBorrow; |
7 | |
8 | /// An order-preserving immutable set constructed at compile time. |
9 | /// |
10 | /// Unlike a `Set`, iteration order is guaranteed to match the definition |
11 | /// order. |
12 | /// |
13 | /// ## Note |
14 | /// |
15 | /// The fields of this struct are public so that they may be initialized by the |
16 | /// `phf_ordered_set!` macro and code generation. They are subject to change at |
17 | /// any time and should never be accessed directly. |
18 | pub struct OrderedSet<T: 'static> { |
19 | #[doc (hidden)] |
20 | pub map: OrderedMap<T, ()>, |
21 | } |
22 | |
23 | impl<T> fmt::Debug for OrderedSet<T> |
24 | where |
25 | T: fmt::Debug, |
26 | { |
27 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
28 | fmt.debug_set().entries(self).finish() |
29 | } |
30 | } |
31 | |
32 | impl<T> PartialEq for OrderedSet<T> |
33 | where |
34 | T: PartialEq, |
35 | { |
36 | fn eq(&self, other: &Self) -> bool { |
37 | self.map == other.map |
38 | } |
39 | } |
40 | |
41 | impl<T> Eq for OrderedSet<T> where T: Eq {} |
42 | |
43 | impl<T> OrderedSet<T> { |
44 | /// Returns the number of elements in the `OrderedSet`. |
45 | #[inline ] |
46 | pub const fn len(&self) -> usize { |
47 | self.map.len() |
48 | } |
49 | |
50 | /// Returns true if the `OrderedSet` contains no elements. |
51 | #[inline ] |
52 | pub const fn is_empty(&self) -> bool { |
53 | self.len() == 0 |
54 | } |
55 | |
56 | /// Returns a reference to the set's internal static instance of the given |
57 | /// key. |
58 | /// |
59 | /// This can be useful for interning schemes. |
60 | pub fn get_key<U: ?Sized>(&self, key: &U) -> Option<&T> |
61 | where |
62 | U: Eq + PhfHash, |
63 | T: PhfBorrow<U>, |
64 | { |
65 | self.map.get_key(key) |
66 | } |
67 | |
68 | /// Returns the index of the key within the list used to initialize |
69 | /// the ordered set. |
70 | pub fn get_index<U: ?Sized>(&self, key: &U) -> Option<usize> |
71 | where |
72 | U: Eq + PhfHash, |
73 | T: PhfBorrow<U>, |
74 | { |
75 | self.map.get_index(key) |
76 | } |
77 | |
78 | /// Returns a reference to the key at an index |
79 | /// within the list used to initialize the ordered set. See `.get_index(key)`. |
80 | pub fn index(&self, index: usize) -> Option<&T> { |
81 | self.map.index(index).map(|(k, &())| k) |
82 | } |
83 | |
84 | /// Returns true if `value` is in the `OrderedSet`. |
85 | pub fn contains<U: ?Sized>(&self, value: &U) -> bool |
86 | where |
87 | U: Eq + PhfHash, |
88 | T: PhfBorrow<U>, |
89 | { |
90 | self.map.contains_key(value) |
91 | } |
92 | |
93 | /// Returns an iterator over the values in the set. |
94 | /// |
95 | /// Values are returned in the same order in which they were defined. |
96 | pub fn iter(&self) -> Iter<'_, T> { |
97 | Iter { |
98 | iter: self.map.keys(), |
99 | } |
100 | } |
101 | } |
102 | |
103 | impl<T> OrderedSet<T> |
104 | where |
105 | T: Eq + PhfHash + PhfBorrow<T>, |
106 | { |
107 | /// Returns true if `other` shares no elements with `self`. |
108 | #[inline ] |
109 | pub fn is_disjoint(&self, other: &OrderedSet<T>) -> bool { |
110 | !self.iter().any(|value: &T| other.contains(value)) |
111 | } |
112 | |
113 | /// Returns true if `other` contains all values in `self`. |
114 | #[inline ] |
115 | pub fn is_subset(&self, other: &OrderedSet<T>) -> bool { |
116 | self.iter().all(|value: &T| other.contains(value)) |
117 | } |
118 | |
119 | /// Returns true if `self` contains all values in `other`. |
120 | #[inline ] |
121 | pub fn is_superset(&self, other: &OrderedSet<T>) -> bool { |
122 | other.is_subset(self) |
123 | } |
124 | } |
125 | |
126 | impl<'a, T> IntoIterator for &'a OrderedSet<T> { |
127 | type Item = &'a T; |
128 | type IntoIter = Iter<'a, T>; |
129 | |
130 | fn into_iter(self) -> Iter<'a, T> { |
131 | self.iter() |
132 | } |
133 | } |
134 | |
135 | /// An iterator over the values in a `OrderedSet`. |
136 | pub struct Iter<'a, T> { |
137 | iter: ordered_map::Keys<'a, T, ()>, |
138 | } |
139 | |
140 | impl<'a, T> Clone for Iter<'a, T> { |
141 | #[inline ] |
142 | fn clone(&self) -> Self { |
143 | Self { |
144 | iter: self.iter.clone(), |
145 | } |
146 | } |
147 | } |
148 | |
149 | impl<'a, T> fmt::Debug for Iter<'a, T> |
150 | where |
151 | T: fmt::Debug, |
152 | { |
153 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
154 | f.debug_list().entries(self.clone()).finish() |
155 | } |
156 | } |
157 | |
158 | impl<'a, T> Iterator for Iter<'a, T> { |
159 | type Item = &'a T; |
160 | |
161 | #[inline ] |
162 | fn next(&mut self) -> Option<&'a T> { |
163 | self.iter.next() |
164 | } |
165 | |
166 | #[inline ] |
167 | fn size_hint(&self) -> (usize, Option<usize>) { |
168 | self.iter.size_hint() |
169 | } |
170 | } |
171 | |
172 | impl<'a, T> DoubleEndedIterator for Iter<'a, T> { |
173 | #[inline ] |
174 | fn next_back(&mut self) -> Option<&'a T> { |
175 | self.iter.next_back() |
176 | } |
177 | } |
178 | |
179 | impl<'a, T> ExactSizeIterator for Iter<'a, T> {} |
180 | |
181 | impl<'a, T> FusedIterator for Iter<'a, T> {} |
182 | |