From 413d4c6c11e23b79a26465a840bce7b0f1392425 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 14 Aug 2013 00:33:20 -0400 Subject: [PATCH] net: make IP implement encoding.MarshalerText, encoding.UnmarshalerText 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 | 23 +++++++++++++++++++++++ src/pkg/net/ip_test.go | 15 +++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/pkg/net/ip.go b/src/pkg/net/ip.go index 0e42da2168..b73804d528 100644 --- a/src/pkg/net/ip.go +++ b/src/pkg/net/ip.go @@ -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. diff --git a/src/pkg/net/ip_test.go b/src/pkg/net/ip_test.go index 16f30d446b..606344d265 100644 --- a/src/pkg/net/ip_test.go +++ b/src/pkg/net/ip_test.go @@ -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, ""}, } @@ -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") + } + } } } -- 2.48.1