@@ -261,20 +261,43 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
261261 /// print!("{:?}", city);
262262 /// ```
263263 pub fn lookup < T > ( & ' de self , address : IpAddr ) -> Result < T , MaxMindDBError >
264+ where
265+ T : Deserialize < ' de > ,
266+ {
267+ self . lookup_prefix ( address) . map ( |( v, _) | v)
268+ }
269+
270+ /// Lookup the socket address in the opened MaxMind DB
271+ ///
272+ /// Example:
273+ ///
274+ /// ```
275+ /// use maxminddb::geoip2;
276+ /// use std::net::IpAddr;
277+ /// use std::str::FromStr;
278+ ///
279+ /// let reader = maxminddb::Reader::open_readfile("test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
280+ ///
281+ /// let ip: IpAddr = "89.160.20.128".parse().unwrap();
282+ /// let (city, prefix_len) = reader.lookup_prefix::<geoip2::City>(ip).unwrap();
283+ /// print!("{:?}, prefix length: {}", city, prefix_len);
284+ /// ```
285+ pub fn lookup_prefix < T > ( & ' de self , address : IpAddr ) -> Result < ( T , usize ) , MaxMindDBError >
264286 where
265287 T : Deserialize < ' de > ,
266288 {
267289 let ip_bytes = ip_to_bytes ( address) ;
268- let pointer = self . find_address_in_tree ( & ip_bytes) ?;
290+ let ( pointer, prefix_len ) = self . find_address_in_tree ( & ip_bytes) ?;
269291 if pointer == 0 {
270292 return Err ( MaxMindDBError :: AddressNotFoundError (
271293 "Address not found in database" . to_owned ( ) ,
272294 ) ) ;
273295 }
296+
274297 let rec = self . resolve_data_pointer ( pointer) ?;
275298 let mut decoder = decoder:: Decoder :: new ( & self . buf . as_ref ( ) [ self . pointer_base ..] , rec) ;
276299
277- T :: deserialize ( & mut decoder)
300+ T :: deserialize ( & mut decoder) . map ( |v| ( v , prefix_len ) )
278301 }
279302
280303 /// Iterate over blocks of IP networks in the opened MaxMind DB
@@ -343,23 +366,25 @@ impl<'de, S: AsRef<[u8]>> Reader<S> {
343366 Ok ( within)
344367 }
345368
346- fn find_address_in_tree ( & self , ip_address : & [ u8 ] ) -> Result < usize , MaxMindDBError > {
369+ fn find_address_in_tree ( & self , ip_address : & [ u8 ] ) -> Result < ( usize , usize ) , MaxMindDBError > {
347370 let bit_count = ip_address. len ( ) * 8 ;
348371 let mut node = self . start_node ( bit_count) ;
349372
350373 let node_count = self . metadata . node_count as usize ;
374+ let mut prefix_len = bit_count;
351375
352376 for i in 0 ..bit_count {
353377 if node >= node_count {
378+ prefix_len = i;
354379 break ;
355380 }
356381 let bit = 1 & ( ip_address[ i >> 3 ] >> ( 7 - ( i % 8 ) ) ) ;
357382
358383 node = self . read_node ( node, bit as usize ) ?;
359384 }
360385 match node_count {
361- n if n == node => Ok ( 0 ) ,
362- n if node > n => Ok ( node) ,
386+ n if n == node => Ok ( ( 0 , prefix_len ) ) ,
387+ n if node > n => Ok ( ( node, prefix_len ) ) ,
363388 _ => Err ( MaxMindDBError :: InvalidDatabaseError (
364389 "invalid node in search tree" . to_owned ( ) ,
365390 ) ) ,
@@ -455,6 +480,7 @@ fn ip_to_bytes(address: IpAddr) -> Vec<u8> {
455480 }
456481}
457482
483+ #[ allow( clippy:: many_single_char_names) ]
458484fn bytes_and_prefix_to_net ( bytes : & [ u8 ] , prefix : u8 ) -> Result < IpNetwork , MaxMindDBError > {
459485 let ( ip, pre) = match bytes. len ( ) {
460486 4 => (
0 commit comments