@@ -758,6 +758,9 @@ impl Ipv4Addr {
758758 ///
759759 /// a.b.c.d becomes ::a.b.c.d
760760 ///
761+ /// Note: The IPv4 address used in the IPv4-compatible IPv6 address must be a
762+ /// globally-unique IPv4 unicast address. This implementation does *not* check for it.
763+ ///
761764 /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
762765 ///
763766 /// # Examples
@@ -1493,6 +1496,9 @@ impl Ipv6Addr {
14931496 ///
14941497 /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
14951498 ///
1499+ /// Note: The IPv4 address used in the IPv4-compatible IPv6 address must be a
1500+ /// globally-unique IPv4 unicast address.
1501+ ///
14961502 /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
14971503 /// [`None`]: ../../std/option/enum.Option.html#variant.None
14981504 ///
@@ -1504,14 +1510,19 @@ impl Ipv6Addr {
15041510 /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
15051511 /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
15061512 /// Some(Ipv4Addr::new(192, 10, 2, 255)));
1507- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
1508- /// Some(Ipv4Addr::new(0, 0, 0, 1)));
1513+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(), None);
1514+ /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
1515+ /// Some(Ipv4Addr::new(18, 52, 86, 120)));
15091516 /// ```
15101517 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
15111518 pub fn to_ipv4 ( & self ) -> Option < Ipv4Addr > {
1512- match self . segments ( ) {
1513- [ 0 , 0 , 0 , 0 , 0 , f, g, h] if f == 0 || f == 0xffff => {
1514- Some ( Ipv4Addr :: new ( ( g >> 8 ) as u8 , g as u8 , ( h >> 8 ) as u8 , h as u8 ) )
1519+ match self . octets ( ) {
1520+ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0xff , 0xff , a, b, c, d] => {
1521+ Some ( Ipv4Addr :: new ( a, b, c, d) )
1522+ }
1523+ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , a, b, c, d] => {
1524+ let ipv4 = Ipv4Addr :: new ( a, b, c, d) ;
1525+ if ipv4. is_global ( ) { Some ( ipv4) } else { None }
15151526 }
15161527 _ => None ,
15171528 }
@@ -1542,13 +1553,7 @@ impl fmt::Display for Ipv6Addr {
15421553 if f. precision ( ) . is_none ( ) && f. width ( ) . is_none ( ) {
15431554 let segments = self . segments ( ) ;
15441555
1545- // Special case for :: and ::1; otherwise they get written with the
1546- // IPv4 formatter
1547- if self . is_unspecified ( ) {
1548- f. write_str ( "::" )
1549- } else if self . is_loopback ( ) {
1550- f. write_str ( "::1" )
1551- } else if let Some ( ipv4) = self . to_ipv4 ( ) {
1556+ if let Some ( ipv4) = self . to_ipv4 ( ) {
15521557 match segments[ 5 ] {
15531558 // IPv4 Compatible address
15541559 0 => write ! ( f, "::{}" , ipv4) ,
@@ -2025,8 +2030,8 @@ mod tests {
20252030 assert_eq ! ( a1. to_string( ) , "::ffff:192.0.2.128" ) ;
20262031
20272032 // ipv4-compatible address
2028- let a1 = Ipv6Addr :: new ( 0 , 0 , 0 , 0 , 0 , 0 , 0xc000 , 0x280 ) ;
2029- assert_eq ! ( a1. to_string( ) , "::192.0.2.128 " ) ;
2033+ let a1 = Ipv6Addr :: new ( 0 , 0 , 0 , 0 , 0 , 0 , 0x102 , 0x304 ) ;
2034+ assert_eq ! ( a1. to_string( ) , "::1.2.3.4 " ) ;
20302035
20312036 // v6 address with no zero segments
20322037 assert_eq ! ( Ipv6Addr :: new( 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) . to_string( ) , "8:9:a:b:c:d:e:f" ) ;
@@ -2495,11 +2500,7 @@ mod tests {
24952500
24962501 check ! ( "::1" , & [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] , loopback) ;
24972502
2498- check ! (
2499- "::0.0.0.2" ,
2500- & [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 ] ,
2501- global | unicast_global
2502- ) ;
2503+ check ! ( "::2" , & [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 ] , global | unicast_global) ;
25032504
25042505 check ! ( "1::" , & [ 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , global | unicast_global) ;
25052506
0 commit comments