Skip to content

net: add text marshalling and unmarshalling for HardwareAddr #34452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/net/mac.go
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@

package net

import "encoding/base64"

const hexDigit = "0123456789abcdef"

// A HardwareAddr represents a physical hardware address.
@@ -24,6 +26,36 @@ func (a HardwareAddr) String() string {
return string(buf)
}

// MarshalText implements encoding.TextMarshaler using the
// standard string representation of a HardwareAddr.
func (a HardwareAddr) MarshalText() ([]byte, error) {
return []byte(a.String()), nil
}

// UnmarshalText implements encoding.TextUnmarshaler.
func (a *HardwareAddr) UnmarshalText(text []byte) error {
if len(text) == 0 {
*a = nil
return nil
}

// First, attempt to decode raw bytes in case the MAC address
// was encoded as a raw byte slice in an older verison of golang.
b64buf := make([]byte, 6)
if _, err := base64.StdEncoding.Decode(b64buf, text); err == nil {
*a = b64buf
return nil
}

// Otherwise, fallback to normal MAC address parsing.
v, err := ParseMAC(string(text))
if err != nil {
return err
}
*a = v
return nil
}

// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet
// IP over InfiniBand link-layer address using one of the following formats:
// 00:00:5e:00:53:01
79 changes: 79 additions & 0 deletions src/net/mac_test.go
Original file line number Diff line number Diff line change
@@ -107,3 +107,82 @@ func TestParseMAC(t *testing.T) {
}
}
}

func TestHardwareAddr_UnmarshalText(t *testing.T) {
matchErr := func(s string, err error) bool {
if s == "" {
return err == nil
}
return err != nil && strings.Contains(err.Error(), s)
}

tests := []struct {
msg string
text string
wantStr string
wantErr string
}{
{
msg: "valid mac1",
text: "aa:bb:cc:dd:ee:ff",
wantStr: "aa:bb:cc:dd:ee:ff",
wantErr: "",
},
{
msg: "valid mac2",
text: "00-00-5e-00-63-01",
wantStr: "00:00:5e:00:63:01",
wantErr: "",
},
{
msg: "binary mac",
text: "VCKpL053",
wantStr: "54:22:a9:2f:4e:77",
wantErr: "",
},
{
msg: "empty text",
text: "",
wantStr: "",
wantErr: "",
},
{
msg: "invalid text",
text: "foo-bar-baz",
wantStr: "",
wantErr: "address foo-bar-baz: invalid MAC address",
},
}
for _, tt := range tests {
t.Run(tt.msg, func(t *testing.T) {
var a HardwareAddr
err := a.UnmarshalText([]byte(tt.text))
gotStr := a.String()
if tt.wantStr != gotStr || !matchErr(tt.wantErr, err) {
t.Errorf("want: addr = %q, err = %q, got: addr = %q, err = %q", tt.wantStr, tt.wantErr, gotStr, err)
}
})
}
}

func TestHardwareAddr_MarshalText(t *testing.T) {
input := "aa:bb:cc:dd:ee:ff"

var a HardwareAddr
if err := a.UnmarshalText([]byte(input)); err != nil {
t.Fatal(err)
}

output, err := a.MarshalText()
if err != nil {
t.Fatal(err)
}

if err := a.UnmarshalText([]byte(input)); err != nil {
t.Fatal(err)
}

if input != string(output) {
t.Errorf("want %q, got %q", input, string(output))
}
}