99use crate :: cmp:: Ordering ;
1010use crate :: fmt;
1111use crate :: hash;
12+ use crate :: io:: Write ;
1213use crate :: sys:: net:: netc as c;
1314use crate :: sys_common:: { AsInner , FromInner } ;
1415
@@ -833,8 +834,16 @@ impl From<Ipv6Addr> for IpAddr {
833834#[ stable( feature = "rust1" , since = "1.0.0" ) ]
834835impl fmt:: Display for Ipv4Addr {
835836 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[ ..] ;
836840 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)
838847 }
839848}
840849
@@ -1495,18 +1504,40 @@ impl Ipv6Addr {
14951504#[ stable( feature = "rust1" , since = "1.0.0" ) ]
14961505impl fmt:: Display for Ipv6Addr {
14971506 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+
14981513 match self . segments ( ) {
14991514 // We need special cases for :: and ::1, otherwise they're formatted
15001515 // 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 ( ) ,
15031518 // Ipv4 Compatible address
15041519 [ 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 ( ) ;
15061529 }
15071530 // Ipv4-Mapped address
15081531 [ 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 ( ) ;
15101541 }
15111542 _ => {
15121543 fn find_zero_slice ( segments : & [ u16 ; 8 ] ) -> ( usize , usize ) {
@@ -1539,25 +1570,33 @@ impl fmt::Display for Ipv6Addr {
15391570 let ( zeros_at, zeros_len) = find_zero_slice ( & self . segments ( ) ) ;
15401571
15411572 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 ] ) {
15431574 if !segments. is_empty ( ) {
1544- write ! ( fmt , "{:x}" , segments[ 0 ] ) ? ;
1575+ write ! ( * buf , "{:x}" , segments[ 0 ] ) . unwrap ( ) ;
15451576 for & seg in & segments[ 1 ..] {
1546- write ! ( fmt , ":{:x}" , seg) ? ;
1577+ write ! ( * buf , ":{:x}" , seg) . unwrap ( ) ;
15471578 }
15481579 }
1549- Ok ( ( ) )
15501580 }
15511581
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 ) ;
15551585 } else {
15561586 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 ( ) ;
15581593 }
15591594 }
15601595 }
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)
15611600 }
15621601}
15631602
@@ -1896,6 +1935,18 @@ mod tests {
18961935 assert_eq ! ( None , none) ;
18971936 }
18981937
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+
18991950 #[ test]
19001951 fn ipv6_addr_to_string ( ) {
19011952 // ipv4-mapped address
@@ -1909,6 +1960,22 @@ mod tests {
19091960 // v6 address with no zero segments
19101961 assert_eq ! ( Ipv6Addr :: new( 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ) . to_string( ) , "8:9:a:b:c:d:e:f" ) ;
19111962
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+
19121979 // reduce a single run of zeros
19131980 assert_eq ! (
19141981 "ae::ffff:102:304" ,
0 commit comments