9
9
use crate :: cmp:: Ordering ;
10
10
use crate :: fmt;
11
11
use crate :: hash;
12
+ use crate :: io:: Write ;
12
13
use crate :: sys:: net:: netc as c;
13
14
use crate :: sys_common:: { AsInner , FromInner } ;
14
15
@@ -833,8 +834,16 @@ impl From<Ipv6Addr> for IpAddr {
833
834
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
834
835
impl fmt:: Display for Ipv4Addr {
835
836
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
837
+ const IPV4_BUF_LEN : usize = 15 ; // Long enough for the longest possible IPv4 address
838
+ let mut buf = [ 0u8 ; IPV4_BUF_LEN ] ;
839
+ let mut buf_slice = & mut buf[ ..] ;
836
840
let octets = self . octets ( ) ;
837
- write ! ( fmt, "{}.{}.{}.{}" , octets[ 0 ] , octets[ 1 ] , octets[ 2 ] , octets[ 3 ] )
841
+ // Note: The call to write should never fail, hence the unwrap
842
+ write ! ( buf_slice, "{}.{}.{}.{}" , octets[ 0 ] , octets[ 1 ] , octets[ 2 ] , octets[ 3 ] ) . unwrap ( ) ;
843
+ let len = IPV4_BUF_LEN - buf_slice. len ( ) ;
844
+ // This unsafe is OK because we know what is being written to the buffer
845
+ let buf = unsafe { crate :: str:: from_utf8_unchecked ( & buf[ ..len] ) } ;
846
+ fmt. pad ( buf)
838
847
}
839
848
}
840
849
@@ -1495,18 +1504,40 @@ impl Ipv6Addr {
1495
1504
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1496
1505
impl fmt:: Display for Ipv6Addr {
1497
1506
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1507
+ // Note: The calls to write should never fail, hence the unwraps in the function
1508
+ // Long enough for the longest possible IPv6: 39
1509
+ const IPV6_BUF_LEN : usize = 39 ;
1510
+ let mut buf = [ 0u8 ; IPV6_BUF_LEN ] ;
1511
+ let mut buf_slice = & mut buf[ ..] ;
1512
+
1498
1513
match self . segments ( ) {
1499
1514
// We need special cases for :: and ::1, otherwise they're formatted
1500
1515
// as ::0.0.0.[01]
1501
- [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] => write ! ( fmt , "::" ) ,
1502
- [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] => write ! ( fmt , "::1" ) ,
1516
+ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] => write ! ( buf_slice , "::" ) . unwrap ( ) ,
1517
+ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 ] => write ! ( buf_slice , "::1" ) . unwrap ( ) ,
1503
1518
// Ipv4 Compatible address
1504
1519
[ 0 , 0 , 0 , 0 , 0 , 0 , g, h] => {
1505
- write ! ( fmt, "::{}.{}.{}.{}" , ( g >> 8 ) as u8 , g as u8 , ( h >> 8 ) as u8 , h as u8 )
1520
+ write ! (
1521
+ buf_slice,
1522
+ "::{}.{}.{}.{}" ,
1523
+ ( g >> 8 ) as u8 ,
1524
+ g as u8 ,
1525
+ ( h >> 8 ) as u8 ,
1526
+ h as u8
1527
+ )
1528
+ . unwrap ( ) ;
1506
1529
}
1507
1530
// Ipv4-Mapped address
1508
1531
[ 0 , 0 , 0 , 0 , 0 , 0xffff , g, h] => {
1509
- write ! ( fmt, "::ffff:{}.{}.{}.{}" , ( g >> 8 ) as u8 , g as u8 , ( h >> 8 ) as u8 , h as u8 )
1532
+ write ! (
1533
+ buf_slice,
1534
+ "::ffff:{}.{}.{}.{}" ,
1535
+ ( g >> 8 ) as u8 ,
1536
+ g as u8 ,
1537
+ ( h >> 8 ) as u8 ,
1538
+ h as u8
1539
+ )
1540
+ . unwrap ( ) ;
1510
1541
}
1511
1542
_ => {
1512
1543
fn find_zero_slice ( segments : & [ u16 ; 8 ] ) -> ( usize , usize ) {
@@ -1539,25 +1570,33 @@ impl fmt::Display for Ipv6Addr {
1539
1570
let ( zeros_at, zeros_len) = find_zero_slice ( & self . segments ( ) ) ;
1540
1571
1541
1572
if zeros_len > 1 {
1542
- fn fmt_subslice ( segments : & [ u16 ] , fmt : & mut fmt :: Formatter < ' _ > ) -> fmt :: Result {
1573
+ fn fmt_subslice ( segments : & [ u16 ] , buf : & mut & mut [ u8 ] ) {
1543
1574
if !segments. is_empty ( ) {
1544
- write ! ( fmt , "{:x}" , segments[ 0 ] ) ? ;
1575
+ write ! ( * buf , "{:x}" , segments[ 0 ] ) . unwrap ( ) ;
1545
1576
for & seg in & segments[ 1 ..] {
1546
- write ! ( fmt , ":{:x}" , seg) ? ;
1577
+ write ! ( * buf , ":{:x}" , seg) . unwrap ( ) ;
1547
1578
}
1548
1579
}
1549
- Ok ( ( ) )
1550
1580
}
1551
1581
1552
- fmt_subslice ( & self . segments ( ) [ ..zeros_at] , fmt ) ? ;
1553
- fmt . write_str ( "::" ) ? ;
1554
- fmt_subslice ( & self . segments ( ) [ zeros_at + zeros_len..] , fmt )
1582
+ fmt_subslice ( & self . segments ( ) [ ..zeros_at] , & mut buf_slice ) ;
1583
+ write ! ( buf_slice , "::" ) . unwrap ( ) ;
1584
+ fmt_subslice ( & self . segments ( ) [ zeros_at + zeros_len..] , & mut buf_slice ) ;
1555
1585
} else {
1556
1586
let & [ a, b, c, d, e, f, g, h] = & self . segments ( ) ;
1557
- write ! ( fmt, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}" , a, b, c, d, e, f, g, h)
1587
+ write ! (
1588
+ buf_slice,
1589
+ "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}" ,
1590
+ a, b, c, d, e, f, g, h
1591
+ )
1592
+ . unwrap ( ) ;
1558
1593
}
1559
1594
}
1560
1595
}
1596
+ let len = IPV6_BUF_LEN - buf_slice. len ( ) ;
1597
+ // This is safe because we know exactly what can be in this buffer
1598
+ let buf = unsafe { crate :: str:: from_utf8_unchecked ( & buf[ ..len] ) } ;
1599
+ fmt. pad ( buf)
1561
1600
}
1562
1601
}
1563
1602
@@ -1896,6 +1935,18 @@ mod tests {
1896
1935
assert_eq ! ( None , none) ;
1897
1936
}
1898
1937
1938
+ #[ test]
1939
+ fn ipv4_addr_to_string ( ) {
1940
+ // Short address
1941
+ assert_eq ! ( Ipv4Addr :: new( 1 , 1 , 1 , 1 ) . to_string( ) , "1.1.1.1" ) ;
1942
+ // Long address
1943
+ assert_eq ! ( Ipv4Addr :: new( 127 , 127 , 127 , 127 ) . to_string( ) , "127.127.127.127" ) ;
1944
+
1945
+ // Test padding
1946
+ assert_eq ! ( & format!( "{:16}" , Ipv4Addr :: new( 1 , 1 , 1 , 1 ) ) , "1.1.1.1 " ) ;
1947
+ assert_eq ! ( & format!( "{:>16}" , Ipv4Addr :: new( 1 , 1 , 1 , 1 ) ) , " 1.1.1.1" ) ;
1948
+ }
1949
+
1899
1950
#[ test]
1900
1951
fn ipv6_addr_to_string ( ) {
1901
1952
// ipv4-mapped address
@@ -1909,6 +1960,22 @@ mod tests {
1909
1960
// v6 address with no zero segments
1910
1961
assert_eq ! ( Ipv6Addr :: new( 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) . to_string( ) , "8:9:a:b:c:d:e:f" ) ;
1911
1962
1963
+ // longest possible IPv6 length
1964
+ assert_eq ! (
1965
+ Ipv6Addr :: new( 0x1111 , 0x2222 , 0x3333 , 0x4444 , 0x5555 , 0x6666 , 0x7777 , 0x8888 )
1966
+ . to_string( ) ,
1967
+ "1111:2222:3333:4444:5555:6666:7777:8888"
1968
+ ) ;
1969
+ // padding
1970
+ assert_eq ! (
1971
+ & format!( "{:20}" , Ipv6Addr :: new( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ) ) ,
1972
+ "1:2:3:4:5:6:7:8 "
1973
+ ) ;
1974
+ assert_eq ! (
1975
+ & format!( "{:>20}" , Ipv6Addr :: new( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ) ) ,
1976
+ " 1:2:3:4:5:6:7:8"
1977
+ ) ;
1978
+
1912
1979
// reduce a single run of zeros
1913
1980
assert_eq ! (
1914
1981
"ae::ffff:102:304" ,
0 commit comments