11use ipnetwork:: IpNetwork ;
2-
3- use maxminddb:: geoip2;
2+ use maxminddb:: { Within , geoip2} ;
43
54fn main ( ) -> Result < ( ) , String > {
65 let mut args = std:: env:: args ( ) . skip ( 1 ) ;
@@ -11,18 +10,35 @@ fn main() -> Result<(), String> {
1110 . unwrap ( ) ;
1211 let cidr: String = args
1312 . next ( )
14- . ok_or ( "Second argument must be the IP address and mask in CIDR notation" ) ?
13+ . ok_or ( "Second argument must be the IP address and mask in CIDR notation, e.g. 0.0.0.0/0 or ::/0 " ) ?
1514 . parse ( )
1615 . unwrap ( ) ;
1716 let ip_net = if cidr. contains ( ":" ) {
1817 IpNetwork :: V6 ( cidr. parse ( ) . unwrap ( ) )
1918 } else {
2019 IpNetwork :: V4 ( cidr. parse ( ) . unwrap ( ) )
2120 } ;
22- for r in reader. within ( ip_net) . map_err ( |e| e. to_string ( ) ) ? {
23- let i = r. map_err ( |e| e. to_string ( ) ) ?;
24- let ( ip_net, info) : ( IpNetwork , geoip2:: City ) = ( i. ip_net , i. info ) ;
25- println ! ( "ip_net={}, info={:#?}" , ip_net, info) ;
21+
22+ let mut n = 0 ;
23+ let mut iter: Within < geoip2:: City , _ > = reader. within ( ip_net) . map_err ( |e| e. to_string ( ) ) ?;
24+ while let Some ( next) = iter. next ( ) {
25+ let item = next. map_err ( |e| e. to_string ( ) ) ?;
26+ let continent = item. info . continent . and_then ( |c| c. code ) . unwrap_or ( "" ) ;
27+ let country = item. info . country . and_then ( |c| c. iso_code ) . unwrap_or ( "" ) ;
28+ let city = match item. info . city . and_then ( |c| c. names ) {
29+ Some ( names) => names. get ( "en" ) . unwrap_or ( & "" ) ,
30+ None => "" ,
31+ } ;
32+ if !city. is_empty ( ) {
33+ println ! ( "{} {}-{}-{}" , item. ip_net, continent, country, city) ;
34+ } else if !country. is_empty ( ) {
35+ println ! ( "{} {}-{}" , item. ip_net, continent, country) ;
36+ } else if !continent. is_empty ( ) {
37+ println ! ( "{} {}" , item. ip_net, continent) ;
38+ }
39+ n += 1 ;
2640 }
41+ eprintln ! ( "processed {} items" , n) ;
42+
2743 Ok ( ( ) )
2844}
0 commit comments