Skip to content

Commit 45e1f48

Browse files
feat(iroh-relay): allow for extension of RelayMaps (#3575)
1 parent 4b25776 commit 45e1f48

File tree

1 file changed

+61
-8
lines changed

1 file changed

+61
-8
lines changed

iroh-relay/src/relay_map.rs

Lines changed: 61 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ impl PartialEq for RelayMap {
4343
impl Eq for RelayMap {}
4444

4545
impl RelayMap {
46+
/// Creates an empty relay map.
47+
pub fn empty() -> Self {
48+
Self {
49+
relays: Default::default(),
50+
}
51+
}
52+
4653
/// Returns the URLs of all servers in this relay map.
4754
///
4855
/// This function is generic over the container to collect into. If you simply want a list
@@ -59,13 +66,6 @@ impl RelayMap {
5966
.collect::<T>()
6067
}
6168

62-
/// Creates an empty relay map.
63-
pub fn empty() -> Self {
64-
Self {
65-
relays: Default::default(),
66-
}
67-
}
68-
6969
/// Returns a list with the [`RelayConfig`] for each relay in this relay map.
7070
///
7171
/// This function is generic over the container to collect into. If you simply want a list
@@ -111,14 +111,27 @@ impl RelayMap {
111111
pub fn remove(&self, url: &RelayUrl) -> Option<Arc<RelayConfig>> {
112112
self.relays.write().expect("poisoned").remove(url)
113113
}
114+
115+
/// Extends this `RelayMap` with another one.
116+
pub fn extend(&self, other: &RelayMap) {
117+
let mut a = self.relays.write().expect("poisoned");
118+
let b = other.relays.read().expect("poisoned");
119+
a.extend(b.iter().map(|(a, b)| (a.clone(), b.clone())));
120+
}
114121
}
115122

116123
impl FromIterator<RelayConfig> for RelayMap {
117124
fn from_iter<T: IntoIterator<Item = RelayConfig>>(iter: T) -> Self {
125+
Self::from_iter(iter.into_iter().map(Arc::new))
126+
}
127+
}
128+
129+
impl FromIterator<Arc<RelayConfig>> for RelayMap {
130+
fn from_iter<T: IntoIterator<Item = Arc<RelayConfig>>>(iter: T) -> Self {
118131
Self {
119132
relays: Arc::new(RwLock::new(
120133
iter.into_iter()
121-
.map(|endpoint| (endpoint.url.clone(), Arc::new(endpoint)))
134+
.map(|config| (config.url.clone(), config))
122135
.collect(),
123136
)),
124137
}
@@ -220,3 +233,43 @@ impl fmt::Display for RelayConfig {
220233
write!(f, "{}", self.url)
221234
}
222235
}
236+
237+
#[cfg(test)]
238+
mod tests {
239+
use std::str::FromStr;
240+
241+
use super::*;
242+
243+
#[test]
244+
fn relay_map_extend() {
245+
let urls1 = vec![
246+
RelayUrl::from_str("https://hello-a-01.com").unwrap(),
247+
RelayUrl::from_str("https://hello-b-01.com").unwrap(),
248+
RelayUrl::from_str("https://hello-c-01-.com").unwrap(),
249+
];
250+
251+
let urls2 = vec![
252+
RelayUrl::from_str("https://hello-a-02.com").unwrap(),
253+
RelayUrl::from_str("https://hello-b-02.com").unwrap(),
254+
RelayUrl::from_str("https://hello-c-02-.com").unwrap(),
255+
];
256+
257+
let map1 = RelayMap::from_iter(urls1.clone().into_iter().map(RelayConfig::from));
258+
let map2 = RelayMap::from_iter(urls2.clone().into_iter().map(RelayConfig::from));
259+
260+
assert_ne!(map1, map2);
261+
262+
// combine
263+
264+
let map3 = RelayMap::from_iter(
265+
map1.relays::<Vec<_>>()
266+
.into_iter()
267+
.chain(map2.relays::<Vec<_>>()),
268+
);
269+
270+
assert_eq!(map3.len(), 6);
271+
272+
map1.extend(&map2);
273+
assert_eq!(map3, map1);
274+
}
275+
}

0 commit comments

Comments
 (0)