1- use clap:: { Parser , Subcommand } ;
1+ use anyhow:: { Result , bail} ;
2+ use clap:: { Args , Parser , Subcommand } ;
23use ipnet:: IpNet ;
3- use std:: net:: IpAddr ;
4+ use std:: { collections :: HashSet , net:: IpAddr } ;
45
56#[ derive( Parser ) ]
67pub struct Arg {
@@ -14,20 +15,43 @@ pub enum Command {
1415 ListInterfaces ,
1516}
1617
17- #[ derive( Parser ) ]
18+ #[ derive( Args ) ]
1819pub struct TcpSynArg {
1920 #[ arg( long) ]
2021 pub src_ip : Option < IpAddr > ,
2122
2223 #[ arg( long, required = true , value_delimiter = ',' ) ]
2324 pub dest_ips : Vec < IpNet > ,
2425
25- #[ arg( long, required = true , value_delimiter = ',' ) ]
26- pub dest_ports : Vec < u16 > ,
26+ // use std::vec::Vec<u16> here
27+ // https://github.com/clap-rs/clap/issues/4679
28+ #[ arg( long, required = true , value_parser = parse_range) ]
29+ pub dest_ports : std:: vec:: Vec < u16 > ,
2730
2831 #[ arg( short, long) ]
2932 pub if_index : Option < u32 > ,
3033
3134 #[ arg( short, long, default_value_t = 5 ) ]
3235 pub thread : usize ,
3336}
37+
38+ fn parse_range ( s : & str ) -> Result < Vec < u16 > > {
39+ let mut result = HashSet :: new ( ) ;
40+
41+ for part in s. split ( ',' ) {
42+ if let Some ( ( start, end) ) = part. split_once ( '-' ) {
43+ let start = start. trim ( ) . parse :: < u16 > ( ) ?;
44+ let end = end. trim ( ) . parse :: < u16 > ( ) ?;
45+
46+ if start > end {
47+ bail ! ( "bad range: {}" , part) ;
48+ }
49+
50+ result. extend ( start..=end) ;
51+ } else {
52+ result. insert ( part. trim ( ) . parse :: < u16 > ( ) ?) ;
53+ }
54+ }
55+
56+ Ok ( result. into_iter ( ) . collect ( ) )
57+ }
0 commit comments