@@ -2,7 +2,7 @@ use crate::cmp::Ordering;
22use crate :: convert:: TryInto ;
33use crate :: fmt;
44use crate :: hash;
5- use crate :: io;
5+ use crate :: io:: { self , Write } ;
66use crate :: iter;
77use crate :: mem;
88use crate :: net:: { htons, ntohs, IpAddr , Ipv4Addr , Ipv6Addr } ;
@@ -600,7 +600,26 @@ impl fmt::Display for SocketAddr {
600600#[ stable( feature = "rust1" , since = "1.0.0" ) ]
601601impl fmt:: Display for SocketAddrV4 {
602602 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
603- write ! ( f, "{}:{}" , self . ip( ) , self . port( ) )
603+ // Fast path: if there's no alignment stuff, write to the output buffer
604+ // directly
605+ if f. precision ( ) . is_none ( ) && f. width ( ) . is_none ( ) {
606+ write ! ( f, "{}:{}" , self . ip( ) , self . port( ) )
607+ } else {
608+ const IPV4_SOCKET_BUF_LEN : usize = ( 3 * 4 ) // the segments
609+ + 3 // the separators
610+ + 1 + 5 ; // the port
611+ let mut buf = [ 0 ; IPV4_SOCKET_BUF_LEN ] ;
612+ let mut buf_slice = & mut buf[ ..] ;
613+
614+ // Unwrap is fine because writing to a sufficiently-sized
615+ // buffer is infallible
616+ write ! ( buf_slice, "{}:{}" , self . ip( ) , self . port( ) ) . unwrap ( ) ;
617+ let len = IPV4_SOCKET_BUF_LEN - buf_slice. len ( ) ;
618+
619+ // This unsafe is OK because we know what is being written to the buffer
620+ let buf = unsafe { crate :: str:: from_utf8_unchecked ( & buf[ ..len] ) } ;
621+ f. pad ( buf)
622+ }
604623 }
605624}
606625
@@ -614,7 +633,28 @@ impl fmt::Debug for SocketAddrV4 {
614633#[ stable( feature = "rust1" , since = "1.0.0" ) ]
615634impl fmt:: Display for SocketAddrV6 {
616635 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
617- write ! ( f, "[{}]:{}" , self . ip( ) , self . port( ) )
636+ // Fast path: if there's no alignment stuff, write to the output
637+ // buffer directly
638+ if f. precision ( ) . is_none ( ) && f. width ( ) . is_none ( ) {
639+ write ! ( f, "[{}]:{}" , self . ip( ) , self . port( ) )
640+ } else {
641+ const IPV6_SOCKET_BUF_LEN : usize = ( 4 * 8 ) // The address
642+ + 7 // The colon separators
643+ + 2 // The brackets
644+ + 1 + 5 ; // The port
645+
646+ let mut buf = [ 0 ; IPV6_SOCKET_BUF_LEN ] ;
647+ let mut buf_slice = & mut buf[ ..] ;
648+
649+ // Unwrap is fine because writing to a sufficiently-sized
650+ // buffer is infallible
651+ write ! ( buf_slice, "[{}]:{}" , self . ip( ) , self . port( ) ) . unwrap ( ) ;
652+ let len = IPV6_SOCKET_BUF_LEN - buf_slice. len ( ) ;
653+
654+ // This unsafe is OK because we know what is being written to the buffer
655+ let buf = unsafe { crate :: str:: from_utf8_unchecked ( & buf[ ..len] ) } ;
656+ f. pad ( buf)
657+ }
618658 }
619659}
620660
@@ -1168,6 +1208,28 @@ mod tests {
11681208 assert ! ( v6. is_ipv6( ) ) ;
11691209 }
11701210
1211+ #[ test]
1212+ fn socket_v4_to_str ( ) {
1213+ let socket = SocketAddrV4 :: new ( Ipv4Addr :: new ( 192 , 168 , 0 , 1 ) , 8080 ) ;
1214+
1215+ assert_eq ! ( format!( "{}" , socket) , "192.168.0.1:8080" ) ;
1216+ assert_eq ! ( format!( "{:<20}" , socket) , "192.168.0.1:8080 " ) ;
1217+ assert_eq ! ( format!( "{:>20}" , socket) , " 192.168.0.1:8080" ) ;
1218+ assert_eq ! ( format!( "{:^20}" , socket) , " 192.168.0.1:8080 " ) ;
1219+ assert_eq ! ( format!( "{:.10}" , socket) , "192.168.0." ) ;
1220+ }
1221+
1222+ #[ test]
1223+ fn socket_v6_to_str ( ) {
1224+ let socket: SocketAddrV6 = "[2a02:6b8:0:1::1]:53" . parse ( ) . unwrap ( ) ;
1225+
1226+ assert_eq ! ( format!( "{}" , socket) , "[2a02:6b8:0:1::1]:53" ) ;
1227+ assert_eq ! ( format!( "{:<24}" , socket) , "[2a02:6b8:0:1::1]:53 " ) ;
1228+ assert_eq ! ( format!( "{:>24}" , socket) , " [2a02:6b8:0:1::1]:53" ) ;
1229+ assert_eq ! ( format!( "{:^24}" , socket) , " [2a02:6b8:0:1::1]:53 " ) ;
1230+ assert_eq ! ( format!( "{:.15}" , socket) , "[2a02:6b8:0:1::" ) ;
1231+ }
1232+
11711233 #[ test]
11721234 fn compare ( ) {
11731235 let v4_1 = "224.120.45.1:23456" . parse :: < SocketAddrV4 > ( ) . unwrap ( ) ;
0 commit comments