@@ -785,17 +785,32 @@ func (ip Addr) Prev() Addr {
785785// IPv4-mapped IPv6 addresses format with a "::ffff:"
786786// prefix before the dotted quad.
787787func (ip Addr ) String () string {
788- switch ip .z {
789- case z0 :
788+ if ! ip .IsValid () {
790789 return "invalid IP"
791- case z4 :
792- return ip .string4 ()
790+ }
791+ var b []byte
792+ switch {
793+ case ip .z == z4 :
794+ const max = len ("255.255.255.255" )
795+ b = make ([]byte , 0 , max )
796+ b = ip .appendTo4 (b )
797+ case ip .Is4In6 ():
798+ const max = len ("::ffff:255.255.255.255%enp5s0" )
799+ b = make ([]byte , 0 , max )
800+ b = ip .appendTo4In6 (b )
793801 default :
794- if ip .Is4In6 () {
795- return ip .string4In6 ()
796- }
797- return ip .string6 ()
802+ // Use a zone with a "plausibly long" name, so that most zone-ful
803+ // IP addresses won't require additional allocation.
804+ //
805+ // The compiler does a cool optimization here, where b ends up
806+ // stack-allocated and so the only allocation this function does
807+ // is to construct the returned string. As such, it's okay to be a
808+ // bit greedy here, size-wise.
809+ const max = len ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0" )
810+ b = make ([]byte , 0 , max )
811+ b = ip .appendTo6 (b )
798812 }
813+ return string (b )
799814}
800815
801816// AppendTo appends a text encoding of ip,
@@ -855,13 +870,6 @@ func appendHexPad(b []byte, x uint16) []byte {
855870 return append (b , digits [x >> 12 ], digits [x >> 8 & 0xf ], digits [x >> 4 & 0xf ], digits [x & 0xf ])
856871}
857872
858- func (ip Addr ) string4 () string {
859- const max = len ("255.255.255.255" )
860- ret := make ([]byte , 0 , max )
861- ret = ip .appendTo4 (ret )
862- return string (ret )
863- }
864-
865873func (ip Addr ) appendTo4 (ret []byte ) []byte {
866874 ret = appendDecimal (ret , ip .v4 (0 ))
867875 ret = append (ret , '.' )
@@ -873,13 +881,6 @@ func (ip Addr) appendTo4(ret []byte) []byte {
873881 return ret
874882}
875883
876- func (ip Addr ) string4In6 () string {
877- const max = len ("::ffff:255.255.255.255%enp5s0" )
878- ret := make ([]byte , 0 , max )
879- ret = ip .appendTo4In6 (ret )
880- return string (ret )
881- }
882-
883884func (ip Addr ) appendTo4In6 (ret []byte ) []byte {
884885 ret = append (ret , "::ffff:" ... )
885886 ret = ip .Unmap ().appendTo4 (ret )
@@ -890,25 +891,11 @@ func (ip Addr) appendTo4In6(ret []byte) []byte {
890891 return ret
891892}
892893
893- // string6 formats ip in IPv6 textual representation. It follows the
894- // guidelines in section 4 of RFC 5952
895- // (https://tools.ietf.org/html/rfc5952#section-4): no unnecessary
896- // zeros, use :: to elide the longest run of zeros, and don't use ::
894+ // appendTo6 formats ip in IPv6 textual representation, appends the result to
895+ // the byte slice, and returns the updated slice. It follows the guidelines in
896+ // section 4 of RFC 5952 (https://tools.ietf.org/html/rfc5952#section-4): no
897+ // unnecessary zeros, use :: to elide the longest run of zeros, and don't use ::
897898// to compact a single zero field.
898- func (ip Addr ) string6 () string {
899- // Use a zone with a "plausibly long" name, so that most zone-ful
900- // IP addresses won't require additional allocation.
901- //
902- // The compiler does a cool optimization here, where ret ends up
903- // stack-allocated and so the only allocation this function does
904- // is to construct the returned string. As such, it's okay to be a
905- // bit greedy here, size-wise.
906- const max = len ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0" )
907- ret := make ([]byte , 0 , max )
908- ret = ip .appendTo6 (ret )
909- return string (ret )
910- }
911-
912899func (ip Addr ) appendTo6 (ret []byte ) []byte {
913900 zeroStart , zeroEnd := uint8 (255 ), uint8 (255 )
914901 for i := uint8 (0 ); i < 8 ; i ++ {
0 commit comments