]> Cypherpunks repositories - gostls13.git/commitdiff
net: make IP implement encoding.MarshalerText, encoding.UnmarshalerText
authorRuss Cox <rsc@golang.org>
Wed, 14 Aug 2013 04:33:20 +0000 (00:33 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 14 Aug 2013 04:33:20 +0000 (00:33 -0400)
See golang.org/s/go12encoding for design.

R=golang-dev, bradfitz, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/12705043

src/pkg/net/ip.go
src/pkg/net/ip_test.go

index 0e42da2168354a7eb5b62f7ab633cbb5a93ddf10..b73804d5287e40c04a7268e1153e065b1f924ab5 100644 (file)
@@ -12,6 +12,8 @@
 
 package net
 
+import "errors"
+
 // IP address lengths (bytes).
 const (
        IPv4len = 4
@@ -310,6 +312,27 @@ func (ip IP) String() string {
        return s
 }
 
+// MarshalText implements the encoding.TextMarshaler interface.
+// The encoding is the same as returned by String.
+func (ip IP) MarshalText() ([]byte, error) {
+       if len(ip) != IPv4len && len(ip) != IPv6len {
+               return nil, errors.New("invalid IP address")
+       }
+       return []byte(ip.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The IP address is expected in a form accepted by ParseIP.
+func (ip *IP) UnmarshalText(text []byte) error {
+       s := string(text)
+       x := ParseIP(s)
+       if x == nil {
+               return &ParseError{"IP address", s}
+       }
+       *ip = x
+       return nil
+}
+
 // Equal returns true if ip and x are the same IP address.
 // An IPv4 address and that same address in IPv6 form are
 // considered to be equal.
index 16f30d446b5c89586decf9498cd0a7100283785c..606344d265592abbb70d4ccf98fb3dcea3281004 100644 (file)
@@ -32,6 +32,11 @@ func TestParseIP(t *testing.T) {
                if out := ParseIP(tt.in); !reflect.DeepEqual(out, tt.out) {
                        t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out)
                }
+               var out IP
+
+               if err := out.UnmarshalText([]byte(tt.in)); !reflect.DeepEqual(out, tt.out) || (tt.out == nil) != (err != nil) {
+                       t.Errorf("IP.UnmarshalText(%q) = %v, %v, want %v", tt.in, out, err, tt.out)
+               }
        }
 }
 
@@ -47,6 +52,7 @@ var ipStringTests = []struct {
        {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0}, "2001:db8:0:0:1::"},
        {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1:0:0:1"},
        {IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD}, "2001:db8::a:b:c:d"},
+       {IPv4(192, 168, 0, 1), "192.168.0.1"},
        {nil, "<nil>"},
 }
 
@@ -55,6 +61,15 @@ func TestIPString(t *testing.T) {
                if out := tt.in.String(); out != tt.out {
                        t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.out)
                }
+               if tt.in != nil {
+                       if out, err := tt.in.MarshalText(); string(out) != tt.out || err != nil {
+                               t.Errorf("IP.MarshalText(%v) = %q, %v, want %q, nil", out, err, tt.out)
+                       }
+               } else {
+                       if _, err := tt.in.MarshalText(); err == nil {
+                               t.Errorf("IP.MarshalText(nil) succeeded, want failure")
+                       }
+               }
        }
 }