@@ -17,6 +17,7 @@ use crate::target_configs::stdin::StdinTarget;
1717use ambassador:: { delegatable_trait, Delegate } ;
1818use clap:: { Parser , Subcommand } ;
1919use itertools:: Itertools ;
20+ use std:: collections:: HashSet ;
2021use std:: fmt;
2122use std:: str:: FromStr ;
2223use std:: sync:: { mpsc, Arc } ;
@@ -156,8 +157,7 @@ pub struct Config {
156157 #[ arg( env = "RATE_MIRRORS_PROTOCOL" , long = "protocol" , name = "protocol" ) ]
157158 pub protocols : Vec < Protocol > ,
158159
159- /// Per-mirror speed test timeout in milliseconds. It is doubled in cases where slow connection
160- /// times are detected
160+ /// Per-mirror speed test timeout in milliseconds
161161 #[ arg( env = "RATE_MIRRORS_PER_MIRROR_TIMEOUT" , long, default_value = "8000" ) ]
162162 pub per_mirror_timeout : u64 ,
163163
@@ -227,6 +227,15 @@ pub struct Config {
227227 ) ]
228228 pub entry_country : String ,
229229
230+ /// Exclude countries from mirror selection (comma-separated 2-letter ISO country codes).
231+ #[ arg(
232+ env = "RATE_MIRRORS_EXCLUDE_COUNTRIES" ,
233+ long = "exclude-countries" ,
234+ name = "country-codes" ,
235+ verbatim_doc_comment
236+ ) ]
237+ pub exclude_countries : Option < String > ,
238+
230239 /// Neighbor country to test per country
231240 #[ arg(
232241 env = "RATE_MIRRORS_COUNTRY_NEIGHBORS_PER_COUNTRY" ,
@@ -270,13 +279,37 @@ pub struct Config {
270279 /// Disable printing comments to output file
271280 #[ arg( env = "RATE_MIRRORS_DISABLE_COMMENTS_IN_FILE" , long) ]
272281 pub disable_comments_in_file : bool ,
282+
283+ /// Pre-parsed set of excluded country codes (lowercase)
284+ #[ arg( skip) ]
285+ pub excluded_countries_set : HashSet < String > ,
273286}
274287
275288impl Config {
289+ pub fn new ( ) -> Self {
290+ let mut config = Self :: parse ( ) ;
291+ config. excluded_countries_set = config
292+ . exclude_countries
293+ . as_ref ( )
294+ . map ( |s| {
295+ s. split ( ',' )
296+ . map ( |c| c. trim ( ) . to_ascii_lowercase ( ) )
297+ . filter ( |c| !c. is_empty ( ) )
298+ . collect ( )
299+ } )
300+ . unwrap_or_default ( ) ;
301+ config
302+ }
303+
276304 pub fn is_protocol_allowed ( & self , protocol : & Protocol ) -> bool {
277305 self . protocols . is_empty ( ) || self . protocols . contains ( protocol)
278306 }
279307
308+ pub fn is_country_excluded ( & self , code : & str ) -> bool {
309+ self . excluded_countries_set
310+ . contains ( & code. to_ascii_lowercase ( ) )
311+ }
312+
280313 pub fn is_protocol_allowed_for_url ( & self , url : & Url ) -> bool {
281314 self . protocols . is_empty ( )
282315 || url
0 commit comments