@@ -81,7 +81,7 @@ pub struct Metadata {
8181#[ derive( Debug ) ]
8282struct WithinNode {
8383 node : usize ,
84- ip_bytes : Vec < u8 > ,
84+ ip_int : IpInt ,
8585 prefix_len : usize ,
8686}
8787
@@ -99,32 +99,66 @@ pub struct WithinItem<T> {
9999 pub info : T ,
100100}
101101
102+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
103+ enum IpInt {
104+ V4 ( u32 ) ,
105+ V6 ( u128 ) ,
106+ }
107+
108+ impl IpInt {
109+ fn new ( ip_addr : IpAddr ) -> Self {
110+ match ip_addr {
111+ IpAddr :: V4 ( v4) => IpInt :: V4 ( v4. into ( ) ) ,
112+ IpAddr :: V6 ( v6) => IpInt :: V6 ( v6. into ( ) ) ,
113+ }
114+ }
115+
116+ fn get_bit ( & self , index : usize ) -> bool {
117+ match self {
118+ IpInt :: V4 ( ip) => ( ip >> ( 31 - index) ) & 1 == 1 ,
119+ IpInt :: V6 ( ip) => ( ip >> ( 127 - index) ) & 1 == 1 ,
120+ }
121+ }
122+
123+ fn bit_count ( & self ) -> usize {
124+ match self {
125+ IpInt :: V4 ( _) => 32 ,
126+ IpInt :: V6 ( _) => 128 ,
127+ }
128+ }
129+
130+ fn is_ipv4_in_ipv6 ( & self ) -> bool {
131+ match self {
132+ IpInt :: V4 ( _) => false ,
133+ IpInt :: V6 ( ip) => * ip <= 0xFFFFFFFF ,
134+ }
135+ }
136+ }
137+
102138impl < ' de , T : Deserialize < ' de > , S : AsRef < [ u8 ] > > Iterator for Within < ' de , T , S > {
103139 type Item = Result < WithinItem < T > , MaxMindDBError > ;
104140
105141 fn next ( & mut self ) -> Option < Self :: Item > {
106142 while let Some ( current) = self . stack . pop ( ) {
107- let bit_count = current. ip_bytes . len ( ) * 8 ;
143+ let bit_count = current. ip_int . bit_count ( ) ;
108144
109145 // Skip networks that are aliases for the IPv4 network
110146 if self . reader . ipv4_start != 0
111147 && current. node == self . reader . ipv4_start
112148 && bit_count == 128
113- && current. ip_bytes [ .. 12 ] . iter ( ) . any ( | & b| b != 0 )
149+ && ! current. ip_int . is_ipv4_in_ipv6 ( )
114150 {
115151 continue ;
116152 }
117153
118154 match current. node . cmp ( & self . node_count ) {
119155 Ordering :: Greater => {
120156 // This is a data node, emit it and we're done (until the following next call)
121- let ip_net = match bytes_and_prefix_to_net (
122- & current. ip_bytes ,
123- current. prefix_len as u8 ,
124- ) {
125- Ok ( ip_net) => ip_net,
126- Err ( e) => return Some ( Err ( e) ) ,
127- } ;
157+ let ip_net =
158+ match bytes_and_prefix_to_net ( & current. ip_int , current. prefix_len as u8 ) {
159+ Ok ( ip_net) => ip_net,
160+ Err ( e) => return Some ( Err ( e) ) ,
161+ } ;
128162 // TODO: should this block become a helper method on reader?
129163 let rec = match self . reader . resolve_data_pointer ( current. node ) {
130164 Ok ( rec) => rec,
@@ -145,16 +179,23 @@ impl<'de, T: Deserialize<'de>, S: AsRef<[u8]>> Iterator for Within<'de, T, S> {
145179 Ordering :: Less => {
146180 // In order traversal of our children
147181 // right/1-bit
148- let mut right_ip_bytes = current. ip_bytes . clone ( ) ;
149- right_ip_bytes[ current. prefix_len >> 3 ] |=
150- 1 << ( ( bit_count - current. prefix_len - 1 ) % 8 ) ;
182+ let mut right_ip_int = current. ip_int ;
183+
184+ if current. prefix_len < bit_count {
185+ let bit = current. prefix_len ;
186+ match & mut right_ip_int {
187+ IpInt :: V4 ( ip) => * ip |= 1 << ( 31 - bit) ,
188+ IpInt :: V6 ( ip) => * ip |= 1 << ( 127 - bit) ,
189+ } ;
190+ }
191+
151192 let node = match self . reader . read_node ( current. node , 1 ) {
152193 Ok ( node) => node,
153194 Err ( e) => return Some ( Err ( e) ) ,
154195 } ;
155196 self . stack . push ( WithinNode {
156197 node,
157- ip_bytes : right_ip_bytes ,
198+ ip_int : right_ip_int ,
158199 prefix_len : current. prefix_len + 1 ,
159200 } ) ;
160201 // left/0-bit
@@ -164,7 +205,7 @@ impl<'de, T: Deserialize<'de>, S: AsRef<[u8]>> Iterator for Within<'de, T, S> {
164205 } ;
165206 self . stack . push ( WithinNode {
166207 node,
167- ip_bytes : current. ip_bytes . clone ( ) ,
208+ ip_int : current. ip_int ,
168209 prefix_len : current. prefix_len + 1 ,
169210 } ) ;
170211 }
@@ -286,8 +327,8 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
286327 where
287328 T : Deserialize < ' de > ,
288329 {
289- let ip_bytes = ip_to_bytes ( address) ;
290- let ( pointer, prefix_len) = self . find_address_in_tree ( & ip_bytes ) ?;
330+ let ip_int = IpInt :: new ( address) ;
331+ let ( pointer, prefix_len) = self . find_address_in_tree ( & ip_int ) ?;
291332 if pointer == 0 {
292333 return Err ( MaxMindDBError :: AddressNotFoundError (
293334 "Address not found in database" . to_owned ( ) ,
@@ -317,14 +358,14 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
317358 /// println!("ip_net={}, city={:?}", item.ip_net, item.info);
318359 /// }
319360 /// ```
320- pub fn within < T > ( & ' de self , cidr : IpNetwork ) -> Result < Within < T , S > , MaxMindDBError >
361+ pub fn within < T > ( & ' de self , cidr : IpNetwork ) -> Result < Within < ' de , T , S > , MaxMindDBError >
321362 where
322363 T : Deserialize < ' de > ,
323364 {
324365 let ip_address = cidr. network ( ) ;
325366 let prefix_len = cidr. prefix ( ) as usize ;
326- let ip_bytes = ip_to_bytes ( ip_address) ;
327- let bit_count = ip_bytes . len ( ) * 8 ;
367+ let ip_int = IpInt :: new ( ip_address) ;
368+ let bit_count = ip_int . bit_count ( ) ;
328369
329370 let mut node = self . start_node ( bit_count) ;
330371 let node_count = self . metadata . node_count as usize ;
@@ -334,8 +375,8 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
334375 // Traverse down the tree to the level that matches the cidr mark
335376 let mut i = 0_usize ;
336377 while i < prefix_len {
337- let bit = 1 & ( ip_bytes [ i >> 3 ] >> ( 7 - ( i % 8 ) ) ) as usize ;
338- node = self . read_node ( node, bit) ?;
378+ let bit = ip_int . get_bit ( i ) ;
379+ node = self . read_node ( node, bit as usize ) ?;
339380 if node >= node_count {
340381 // We've hit a dead end before we exhausted our prefix
341382 break ;
@@ -349,7 +390,7 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
349390 // traversed to as our to be processed stack.
350391 stack. push ( WithinNode {
351392 node,
352- ip_bytes ,
393+ ip_int ,
353394 prefix_len,
354395 } ) ;
355396 }
@@ -366,8 +407,8 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
366407 Ok ( within)
367408 }
368409
369- fn find_address_in_tree ( & self , ip_address : & [ u8 ] ) -> Result < ( usize , usize ) , MaxMindDBError > {
370- let bit_count = ip_address . len ( ) * 8 ;
410+ fn find_address_in_tree ( & self , ip_int : & IpInt ) -> Result < ( usize , usize ) , MaxMindDBError > {
411+ let bit_count = ip_int . bit_count ( ) ;
371412 let mut node = self . start_node ( bit_count) ;
372413
373414 let node_count = self . metadata . node_count as usize ;
@@ -378,8 +419,7 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
378419 prefix_len = i;
379420 break ;
380421 }
381- let bit = 1 & ( ip_address[ i >> 3 ] >> ( 7 - ( i % 8 ) ) ) ;
382-
422+ let bit = ip_int. get_bit ( i) ;
383423 node = self . read_node ( node, bit as usize ) ?;
384424 }
385425 match node_count {
@@ -472,60 +512,16 @@ fn to_usize(base: u8, bytes: &[u8]) -> usize {
472512 . fold ( base as usize , |acc, & b| ( acc << 8 ) | b as usize )
473513}
474514
475- fn ip_to_bytes ( address : IpAddr ) -> Vec < u8 > {
476- match address {
477- IpAddr :: V4 ( a) => a. octets ( ) . to_vec ( ) ,
478- IpAddr :: V6 ( a) => a. octets ( ) . to_vec ( ) ,
479- }
480- }
481-
482- #[ allow( clippy:: many_single_char_names) ]
483- fn bytes_and_prefix_to_net ( bytes : & [ u8 ] , prefix : u8 ) -> Result < IpNetwork , MaxMindDBError > {
484- let ( ip, pre) = match bytes. len ( ) {
485- 4 => (
486- IpAddr :: V4 ( Ipv4Addr :: new ( bytes[ 0 ] , bytes[ 1 ] , bytes[ 2 ] , bytes[ 3 ] ) ) ,
487- prefix,
488- ) ,
489- 16 => {
490- if bytes[ 0 ] == 0
491- && bytes[ 1 ] == 0
492- && bytes[ 2 ] == 0
493- && bytes[ 3 ] == 0
494- && bytes[ 4 ] == 0
495- && bytes[ 5 ] == 0
496- && bytes[ 6 ] == 0
497- && bytes[ 7 ] == 0
498- && bytes[ 8 ] == 0
499- && bytes[ 9 ] == 0
500- && bytes[ 10 ] == 0
501- && bytes[ 11 ] == 0
502- {
503- // It's actually v4, but in v6 form, convert would be nice if ipnetwork had this
504- // logic.
505- (
506- IpAddr :: V4 ( Ipv4Addr :: new ( bytes[ 12 ] , bytes[ 13 ] , bytes[ 14 ] , bytes[ 15 ] ) ) ,
507- prefix - 96 ,
508- )
509- } else {
510- let a = u16:: from ( bytes[ 0 ] ) << 8 | u16:: from ( bytes[ 1 ] ) ;
511- let b = u16:: from ( bytes[ 2 ] ) << 8 | u16:: from ( bytes[ 3 ] ) ;
512- let c = u16:: from ( bytes[ 4 ] ) << 8 | u16:: from ( bytes[ 5 ] ) ;
513- let d = u16:: from ( bytes[ 6 ] ) << 8 | u16:: from ( bytes[ 7 ] ) ;
514- let e = u16:: from ( bytes[ 8 ] ) << 8 | u16:: from ( bytes[ 9 ] ) ;
515- let f = u16:: from ( bytes[ 10 ] ) << 8 | u16:: from ( bytes[ 11 ] ) ;
516- let g = u16:: from ( bytes[ 12 ] ) << 8 | u16:: from ( bytes[ 13 ] ) ;
517- let h = u16:: from ( bytes[ 14 ] ) << 8 | u16:: from ( bytes[ 15 ] ) ;
518- ( IpAddr :: V6 ( Ipv6Addr :: new ( a, b, c, d, e, f, g, h) ) , prefix)
519- }
520- }
521- // This should never happen
522- _ => {
523- return Err ( MaxMindDBError :: InvalidNetworkError (
524- "invalid address" . to_owned ( ) ,
525- ) )
515+ #[ inline]
516+ fn bytes_and_prefix_to_net ( bytes : & IpInt , prefix : u8 ) -> Result < IpNetwork , MaxMindDBError > {
517+ let ( ip, prefix) = match bytes {
518+ IpInt :: V4 ( ip) => ( IpAddr :: V4 ( Ipv4Addr :: from ( * ip) ) , prefix) ,
519+ IpInt :: V6 ( ip) if bytes. is_ipv4_in_ipv6 ( ) => {
520+ ( IpAddr :: V4 ( Ipv4Addr :: from ( * ip as u32 ) ) , prefix - 96 )
526521 }
522+ IpInt :: V6 ( ip) => ( IpAddr :: V6 ( Ipv6Addr :: from ( * ip) ) , prefix) ,
527523 } ;
528- IpNetwork :: new ( ip, pre ) . map_err ( |e| MaxMindDBError :: InvalidNetworkError ( e. to_string ( ) ) )
524+ IpNetwork :: new ( ip, prefix ) . map_err ( |e| MaxMindDBError :: InvalidNetworkError ( e. to_string ( ) ) )
529525}
530526
531527fn find_metadata_start ( buf : & [ u8 ] ) -> Result < usize , MaxMindDBError > {
0 commit comments