@@ -79,8 +79,20 @@ pub struct RelayQuery {
79
79
}
80
80
81
81
impl RelayQuery {
82
- /// Create a new [`RelayQuery`] with no opinionated defaults. This
83
- /// should be the const equivalent to [`Default::default`].
82
+ /// Create a new [`RelayQuery`] with no opinionated defaults. This query matches every relay
83
+ /// with any configuration by setting each of its fields to [`Constraint::Any`]. Should be the
84
+ /// const equivalent to [`Default::default`].
85
+ ///
86
+ /// Note that the following identity applies for any `other_query`:
87
+ /// ```rust
88
+ /// # use mullvad_relay_selector::query::RelayQuery;
89
+ /// # use crate::mullvad_relay_selector::query::Intersection;
90
+ ///
91
+ /// # let other_query = RelayQuery::new();
92
+ /// assert_eq!(RelayQuery::new().intersection(other_query.clone()), Some(other_query));
93
+ /// # let other_query = RelayQuery::new();
94
+ /// assert_eq!(other_query.clone().intersection(RelayQuery::new()), Some(other_query));
95
+ /// ```
84
96
pub const fn new ( ) -> RelayQuery {
85
97
RelayQuery {
86
98
location : Constraint :: Any ,
@@ -94,20 +106,84 @@ impl RelayQuery {
94
106
}
95
107
96
108
impl Intersection for RelayQuery {
97
- /// `intersection` defines a cautious merge strategy between two
98
- /// [`RelayQuery`].
109
+ /// Return a new [`RelayQuery`] which matches the intersected queries.
99
110
///
100
- /// * If two [`RelayQuery`] differ in any configuration such that no
101
- /// consensus can be reached, the two [`RelayQuery`] are said to be
102
- /// incompatible and `intersection` returns [`Option::None`].
111
+ /// * If two [`RelayQuery`]s differ such that no relay matches both, [`Option::None`] is returned:
112
+ /// ```rust
113
+ /// # use mullvad_relay_selector::query::builder::RelayQueryBuilder;
114
+ /// # use crate::mullvad_relay_selector::query::Intersection;
115
+ /// let query_a = RelayQueryBuilder::new().wireguard().build();
116
+ /// let query_b = RelayQueryBuilder::new().openvpn().build();
117
+ /// assert_eq!(query_a.intersection(query_b), None);
118
+ /// ```
103
119
///
104
120
/// * Otherwise, a new [`RelayQuery`] is returned where each constraint is
105
121
/// as specific as possible. See [`Constraint`] for further details.
122
+ /// ```rust
123
+ /// # use crate::mullvad_relay_selector::*;
124
+ /// # use crate::mullvad_relay_selector::query::*;
125
+ /// # use crate::mullvad_relay_selector::query::builder::*;
126
+ /// # use mullvad_types::relay_list::*;
127
+ /// # use talpid_types::net::wireguard::PublicKey;
128
+ ///
129
+ /// // The relay list used by `relay_selector` in this example
130
+ /// let relay_list = RelayList {
131
+ /// # etag: None,
132
+ /// # openvpn: OpenVpnEndpointData { ports: vec![] },
133
+ /// # bridge: BridgeEndpointData {
134
+ /// # shadowsocks: vec![],
135
+ /// # },
136
+ /// # wireguard: WireguardEndpointData {
137
+ /// # port_ranges: vec![(53, 53), (4000, 33433), (33565, 51820), (52000, 60000)],
138
+ /// # ipv4_gateway: "10.64.0.1".parse().unwrap(),
139
+ /// # ipv6_gateway: "fc00:bbbb:bbbb:bb01::1".parse().unwrap(),
140
+ /// # udp2tcp_ports: vec![],
141
+ /// # },
142
+ /// countries: vec![RelayListCountry {
143
+ /// name: "Sweden".to_string(),
144
+ /// # code: "Sweden".to_string(),
145
+ /// cities: vec![RelayListCity {
146
+ /// name: "Gothenburg".to_string(),
147
+ /// # code: "Gothenburg".to_string(),
148
+ /// # latitude: 57.70887,
149
+ /// # longitude: 11.97456,
150
+ /// relays: vec![Relay {
151
+ /// hostname: "se9-wireguard".to_string(),
152
+ /// ipv4_addr_in: "185.213.154.68".parse().unwrap(),
153
+ /// # ipv6_addr_in: Some("2a03:1b20:5:f011::a09f".parse().unwrap()),
154
+ /// # include_in_country: false,
155
+ /// # active: true,
156
+ /// # owned: true,
157
+ /// # provider: "31173".to_string(),
158
+ /// # weight: 1,
159
+ /// # endpoint_data: RelayEndpointData::Wireguard(WireguardRelayEndpointData {
160
+ /// # public_key: PublicKey::from_base64(
161
+ /// # "BLNHNoGO88LjV/wDBa7CUUwUzPq/fO2UwcGLy56hKy4=",
162
+ /// # )
163
+ /// # .unwrap(),
164
+ /// # }),
165
+ /// # location: None,
166
+ /// }],
167
+ /// }],
168
+ /// }],
169
+ /// };
170
+ ///
171
+ /// # let relay_selector = RelaySelector::from_list(SelectorConfig::default(), relay_list.clone());
172
+ /// # let city = |country, city| GeographicLocationConstraint::city(country, city);
173
+ ///
174
+ /// let query_a = RelayQueryBuilder::new().wireguard().build();
175
+ /// let query_b = RelayQueryBuilder::new().location(city("Sweden", "Gothenburg")).build();
176
+ ///
177
+ /// let result = relay_selector.get_relay_by_query(query_a.intersection(query_b).unwrap());
178
+ /// assert!(result.is_ok());
179
+ /// ```
180
+ ///
181
+ /// This way, if the mullvad app wants to check if the user's relay settings
182
+ /// are compatible with any other [`RelayQuery`], for examples those defined by
183
+ /// [`RETRY_ORDER`] , taking the intersection between them will never result in
184
+ /// a situation where the app can override the user's preferences.
106
185
///
107
- /// This way, if the mullvad app wants to check if the user's configured
108
- /// [`RelayQuery`] are compatible with any other [`RelayQuery`], taking the
109
- /// intersection between them will never result in a situation where the app
110
- /// can override the user's preferences.
186
+ /// [`RETRY_ORDER`]: crate::RETRY_ORDER
111
187
fn intersection ( self , other : Self ) -> Option < Self >
112
188
where
113
189
Self : PartialEq ,
0 commit comments