tor_linkspec/ids/
set.rs
1use std::collections::HashSet;
4
5use serde::de::Visitor;
6use tor_llcrypto::pk::{ed25519::Ed25519Identity, rsa::RsaIdentity};
7
8use crate::{RelayId, RelayIdRef};
9
10#[derive(Clone, Debug, Default, Eq, PartialEq)]
17pub struct RelayIdSet {
18 ed25519: HashSet<Ed25519Identity>,
20 rsa: HashSet<RsaIdentity>,
22}
23
24impl RelayIdSet {
25 pub fn new() -> Self {
27 Self::default()
28 }
29
30 pub fn insert<T: Into<RelayId>>(&mut self, key: T) -> bool {
34 let key: RelayId = key.into();
35 match key {
36 RelayId::Ed25519(key) => self.ed25519.insert(key),
37 RelayId::Rsa(key) => self.rsa.insert(key),
38 }
39 }
40
41 pub fn remove<'a, T: Into<RelayIdRef<'a>>>(&mut self, key: T) -> bool {
45 let key: RelayIdRef<'a> = key.into();
46 match key {
47 RelayIdRef::Ed25519(key) => self.ed25519.remove(key),
48 RelayIdRef::Rsa(key) => self.rsa.remove(key),
49 }
50 }
51
52 pub fn contains<'a, T: Into<RelayIdRef<'a>>>(&self, key: T) -> bool {
54 let key: RelayIdRef<'a> = key.into();
55 match key {
56 RelayIdRef::Ed25519(key) => self.ed25519.contains(key),
57 RelayIdRef::Rsa(key) => self.rsa.contains(key),
58 }
59 }
60
61 pub fn iter(&self) -> impl Iterator<Item = RelayIdRef<'_>> {
65 self.ed25519
66 .iter()
67 .map(|id| id.into())
68 .chain(self.rsa.iter().map(|id| id.into()))
69 }
70
71 pub fn len(&self) -> usize {
73 self.ed25519.len() + self.rsa.len()
74 }
75
76 pub fn is_empty(&self) -> bool {
78 self.ed25519.is_empty() && self.rsa.is_empty()
79 }
80}
81
82impl<ID: Into<RelayId>> Extend<ID> for RelayIdSet {
83 fn extend<T: IntoIterator<Item = ID>>(&mut self, iter: T) {
84 for item in iter {
85 self.insert(item);
86 }
87 }
88}
89
90impl FromIterator<RelayId> for RelayIdSet {
91 fn from_iter<T: IntoIterator<Item = RelayId>>(iter: T) -> Self {
92 let mut set = RelayIdSet::new();
93 set.extend(iter);
94 set
95 }
96}
97
98impl serde::Serialize for RelayIdSet {
99 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
100 where
101 S: serde::Serializer,
102 {
103 serializer.collect_seq(self.iter())
104 }
105}
106
107impl<'de> serde::Deserialize<'de> for RelayIdSet {
108 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
109 where
110 D: serde::Deserializer<'de>,
111 {
112 struct IdSetVisitor;
115 impl<'de> Visitor<'de> for IdSetVisitor {
116 type Value = RelayIdSet;
117
118 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
119 write!(f, "a list of relay identities")
120 }
121
122 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
123 where
124 A: serde::de::SeqAccess<'de>,
125 {
126 let mut set = RelayIdSet::new();
127 while let Some(key) = seq.next_element::<RelayId>()? {
128 set.insert(key);
129 }
130 Ok(set)
131 }
132 }
133 deserializer.deserialize_seq(IdSetVisitor)
134 }
135}
136
137#[cfg(test)]
138mod test {
139 #![allow(clippy::bool_assert_comparison)]
141 #![allow(clippy::clone_on_copy)]
142 #![allow(clippy::dbg_macro)]
143 #![allow(clippy::mixed_attributes_style)]
144 #![allow(clippy::print_stderr)]
145 #![allow(clippy::print_stdout)]
146 #![allow(clippy::single_char_pattern)]
147 #![allow(clippy::unwrap_used)]
148 #![allow(clippy::unchecked_duration_subtraction)]
149 #![allow(clippy::useless_vec)]
150 #![allow(clippy::needless_pass_by_value)]
151 use super::*;
154 use hex_literal::hex;
155 use serde_test::{assert_tokens, Token};
156
157 #[test]
158 fn basic_usage() {
159 #![allow(clippy::cognitive_complexity)]
160 let rsa1 = RsaIdentity::from(hex!("42656c6f7665642c207768617420617265206e61"));
161 let rsa2 = RsaIdentity::from(hex!("6d657320627574206169723f43686f6f73652074"));
162 let rsa3 = RsaIdentity::from(hex!("686f752077686174657665722073756974732074"));
163
164 let ed1 = Ed25519Identity::from(hex!(
165 "6865206c696e653a43616c6c206d652053617070686f2c2063616c6c206d6520"
166 ));
167 let ed2 = Ed25519Identity::from(hex!(
168 "43686c6f7269732c2043616c6c206d65204c616c6167652c206f7220446f7269"
169 ));
170 let ed3 = Ed25519Identity::from(hex!(
171 "732c204f6e6c792c206f6e6c792c2063616c6c206d65207468696e652e000000"
172 ));
173
174 let mut set = RelayIdSet::new();
175 assert_eq!(set.is_empty(), true);
176 assert_eq!(set.len(), 0);
177
178 set.insert(rsa1);
179 set.insert(rsa2);
180 set.insert(ed1);
181
182 assert_eq!(set.is_empty(), false);
183 assert_eq!(set.len(), 3);
184 assert_eq!(set.contains(&rsa1), true);
185 assert_eq!(set.contains(&rsa2), true);
186 assert_eq!(set.contains(&rsa3), false);
187 assert_eq!(set.contains(&ed1), true);
188 assert_eq!(set.contains(&ed2), false);
189 assert_eq!(set.contains(&ed3), false);
190
191 let contents: HashSet<_> = set.iter().collect();
192 assert_eq!(contents.len(), set.len());
193 assert!(contents.contains(&RelayIdRef::from(&rsa1)));
194 assert!(contents.contains(&RelayIdRef::from(&rsa2)));
195 assert!(contents.contains(&RelayIdRef::from(&ed1)));
196
197 assert_eq!(set.remove(&ed2), false);
198 assert_eq!(set.remove(&ed1), true);
199 assert_eq!(set.remove(&rsa3), false);
200 assert_eq!(set.remove(&rsa1), true);
201 assert_eq!(set.is_empty(), false);
202 assert_eq!(set.len(), 1);
203 assert_eq!(set.contains(&ed1), false);
204 assert_eq!(set.contains(&rsa1), false);
205 assert_eq!(set.contains(&rsa2), true);
206
207 let contents2: Vec<_> = set.iter().collect();
208 assert_eq!(contents2, vec![RelayIdRef::from(&rsa2)]);
209
210 let set2: RelayIdSet = set.iter().map(|id| id.to_owned()).collect();
211 assert_eq!(set, set2);
212
213 let mut set3 = RelayIdSet::new();
214 set3.extend(set.iter().map(|id| id.to_owned()));
215 assert_eq!(set2, set3);
216 }
217
218 #[test]
219 fn serde_empty() {
220 let set = RelayIdSet::new();
221
222 assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
223 }
224
225 #[test]
226 fn serde_singleton_rsa() {
227 let mut set = RelayIdSet::new();
228 set.insert(RsaIdentity::from(hex!(
229 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
230 )));
231
232 assert_tokens(
233 &set,
234 &[
235 Token::Seq { len: Some(1) },
236 Token::Str("$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
237 Token::SeqEnd,
238 ],
239 );
240 }
241
242 #[test]
243 fn serde_singleton_ed25519() {
244 let mut set = RelayIdSet::new();
245 set.insert(Ed25519Identity::from(hex!(
246 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
247 )));
248
249 assert_tokens(
250 &set,
251 &[
252 Token::Seq { len: Some(1) },
253 Token::String("ed25519:u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7u7s"),
254 Token::SeqEnd,
255 ],
256 );
257 }
258}