@@ -391,12 +391,25 @@ impl fmt::Display for Ipv6Network {
391391/// Converts a `Ipv6Addr` network mask into a prefix.
392392/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
393393pub fn ipv6_mask_to_prefix ( mask : Ipv6Addr ) -> Result < u8 , IpNetworkError > {
394+ match ipv6_mask_to_prefix_checked ( mask) {
395+ Some ( prefix) => Ok ( prefix) ,
396+ None => Err ( IpNetworkError :: InvalidPrefix ) ,
397+ }
398+ }
399+
400+ /// Converts a `Ipv6Addr` network mask into a prefix.
401+ ///
402+ /// If the mask is invalid this will return `None`. This is useful in const contexts where
403+ /// [`Option::unwrap`] may be called to trigger a compile-time error if the prefix is invalid.
404+ pub const fn ipv6_mask_to_prefix_checked ( mask : Ipv6Addr ) -> Option < u8 > {
394405 let mask = mask. segments ( ) ;
395- let mut mask_iter = mask. iter ( ) ;
396406
397407 // Count the number of set bits from the start of the address
398408 let mut prefix = 0 ;
399- for & segment in & mut mask_iter {
409+ let mut i = 0 ;
410+ while i < mask. len ( ) {
411+ let segment = mask[ i] ;
412+ i += 1 ;
400413 if segment == 0xffff {
401414 prefix += IPV6_SEGMENT_BITS ;
402415 } else if segment == 0 {
@@ -406,21 +419,23 @@ pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
406419 let prefix_bits = ( !segment) . leading_zeros ( ) as u8 ;
407420 // Check that the remainder of the bits are all unset
408421 if segment << prefix_bits != 0 {
409- return Err ( IpNetworkError :: InvalidPrefix ) ;
422+ return None ;
410423 }
411424 prefix += prefix_bits;
412425 break ;
413426 }
414427 }
415428
416429 // Now check all the remaining bits are unset
417- for & segment in mask_iter {
430+ while i < mask. len ( ) {
431+ let segment = mask[ i] ;
432+ i += 1 ;
418433 if segment != 0 {
419- return Err ( IpNetworkError :: InvalidPrefix ) ;
434+ return None ;
420435 }
421436 }
422437
423- Ok ( prefix)
438+ Some ( prefix)
424439}
425440
426441#[ cfg( test) ]
0 commit comments