@@ -758,6 +758,9 @@ impl Ipv4Addr {
758
758
///
759
759
/// a.b.c.d becomes ::a.b.c.d
760
760
///
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
+ ///
761
764
/// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
762
765
///
763
766
/// # Examples
@@ -1493,6 +1496,9 @@ impl Ipv6Addr {
1493
1496
///
1494
1497
/// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
1495
1498
///
1499
+ /// Note: The IPv4 address used in the IPv4-compatible IPv6 address must be a
1500
+ /// globally-unique IPv4 unicast address.
1501
+ ///
1496
1502
/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
1497
1503
/// [`None`]: ../../std/option/enum.Option.html#variant.None
1498
1504
///
@@ -1504,14 +1510,19 @@ impl Ipv6Addr {
1504
1510
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
1505
1511
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
1506
1512
/// 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)));
1509
1516
/// ```
1510
1517
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1511
1518
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 }
1515
1526
}
1516
1527
_ => None ,
1517
1528
}
@@ -1542,13 +1553,7 @@ impl fmt::Display for Ipv6Addr {
1542
1553
if f. precision ( ) . is_none ( ) && f. width ( ) . is_none ( ) {
1543
1554
let segments = self . segments ( ) ;
1544
1555
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 ( ) {
1552
1557
match segments[ 5 ] {
1553
1558
// IPv4 Compatible address
1554
1559
0 => write ! ( f, "::{}" , ipv4) ,
@@ -2025,8 +2030,8 @@ mod tests {
2025
2030
assert_eq ! ( a1. to_string( ) , "::ffff:192.0.2.128" ) ;
2026
2031
2027
2032
// 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 " ) ;
2030
2035
2031
2036
// v6 address with no zero segments
2032
2037
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 {
2495
2500
2496
2501
check ! ( "::1" , & [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] , loopback) ;
2497
2502
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) ;
2503
2504
2504
2505
check ! ( "1::" , & [ 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , global | unicast_global) ;
2505
2506
0 commit comments