Skip to content

Commit

Permalink
feat: add 'mac' primitive for 'net.HardwareAddr' (MAC)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasmalkmus committed Jan 22, 2024
1 parent db0b683 commit 094db93
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 2 deletions.
9 changes: 9 additions & 0 deletions conv/decode.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package conv

import (
"net"
"net/netip"
"net/url"
"strconv"
Expand Down Expand Up @@ -126,6 +127,10 @@ func ToUUID(s string) (uuid.UUID, error) {
return uuid.Parse(s)
}

func ToMAC(s string) (net.HardwareAddr, error) {
return net.ParseMAC(s)
}

func ToAddr(s string) (netip.Addr, error) {
return netip.ParseAddr(s)
}
Expand Down Expand Up @@ -245,3 +250,7 @@ func ToBoolArray(a []string) ([]bool, error) {
func ToUUIDArray(a []string) ([]uuid.UUID, error) {
return decodeArray(a, ToUUID)
}

func ToMACArray(a []string) ([]net.HardwareAddr, error) {
return decodeArray(a, ToMAC)
}
7 changes: 7 additions & 0 deletions conv/encode.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package conv

import (
"net"
"net/netip"
"net/url"
"strconv"
Expand Down Expand Up @@ -42,6 +43,8 @@ func DurationToString(v time.Duration) string { return v.String() }

func UUIDToString(v uuid.UUID) string { return v.String() }

func MACToString(v net.HardwareAddr) string { return v.String() }

func AddrToString(v netip.Addr) string { return v.String() }

func URLToString(v url.URL) string { return v.String() }
Expand Down Expand Up @@ -104,3 +107,7 @@ func BoolArrayToString(vs []bool) []string {
func UUIDArrayToString(vs []uuid.UUID) []string {
return encodeArray(vs, UUIDToString)
}

func MACArrayToString(vs []net.HardwareAddr) []string {
return encodeArray(vs, MACToString)
}
2 changes: 2 additions & 0 deletions gen/ir/faker.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ func (t *Type) FakeValue() string {
return "time.Duration(5 * time.Second)"
case UUID:
return "uuid.New()"
case MAC:
return `net.ParseMAC("11:22:33:44:55:66")`
case IP:
if s := t.Schema; s != nil && s.Format == "ipv6" {
return `netip.MustParseAddr("::1")`
Expand Down
2 changes: 1 addition & 1 deletion gen/ir/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func jsonType(t *Type) string {
return "Number"
}
return "String"
case String, Duration, UUID, IP, URL, ByteSlice:
case String, Duration, UUID, MAC, IP, URL, ByteSlice:
return "String"
case Null:
return "Null"
Expand Down
3 changes: 3 additions & 0 deletions gen/ir/primitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func (p PrimitiveType) String() string {
return "time.Duration"
case UUID:
return "uuid.UUID"
case MAC:
return "net.HardwareAddr"
case IP:
return "netip.Addr"
case URL:
Expand Down Expand Up @@ -83,6 +85,7 @@ const (
Time
Duration
UUID
MAC
IP
URL
File
Expand Down
2 changes: 1 addition & 1 deletion gen/ir/template_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (t *Type) EncodeFn() string {
Float32, Float64,
String, Bool:
return naming.Capitalize(t.Primitive.String())
case UUID, Time, IP, Duration, URL:
case UUID, Time, MAC, IP, Duration, URL:
return naming.AfterDot(t.Primitive.String())
default:
return ""
Expand Down
1 change: 1 addition & 0 deletions gen/schema_gen_primitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ func TypeFormatMapping() map[jsonschema.SchemaType]map[string]ir.PrimitiveType {
"time": ir.Time,
"duration": ir.Duration,
"uuid": ir.UUID,
"mac": ir.MAC,
"ip": ir.IP,
"ipv4": ir.IP,
"ipv6": ir.IP,
Expand Down
21 changes: 21 additions & 0 deletions json/mac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package json

import (
"net"

"github.com/go-faster/jx"
)

// DecodeMAC decodes net.HardwareAddr.
func DecodeMAC(d *jx.Decoder) (net.HardwareAddr, error) {
raw, err := d.Str()
if err != nil {
return nil, err
}
return net.ParseMAC(raw)
}

// EncodeMAC encodes net.HardwareAddr.
func EncodeMAC(e *jx.Encoder, v net.HardwareAddr) {
e.Str(v.String())
}
78 changes: 78 additions & 0 deletions json/mac_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package json

import (
"fmt"
"net"
"testing"

"github.com/go-faster/jx"
"github.com/stretchr/testify/require"
)

func BenchmarkEncodeMAC(b *testing.B) {
mac, err := net.ParseMAC("00:11:22:33:44:55")
require.NoError(b, err)

e := jx.GetEncoder()
// Preallocate internal buffer.
EncodeMAC(e, mac)

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
e.Reset()
EncodeMAC(e, mac)
}
}

func BenchmarkDecodeMAC(b *testing.B) {
data := []byte(`"00:11:22:33:44:55"`)
d := jx.GetDecoder()

b.ReportAllocs()
b.ResetTimer()

var (
mac net.HardwareAddr
err error
)
for i := 0; i < b.N; i++ {
d.ResetBytes(data)
mac, err = DecodeMAC(d)
}
require.NoError(b, err)
_ = mac
}

func TestMAC(t *testing.T) {
mac := func(s string) net.HardwareAddr {
m, err := net.ParseMAC(s)
require.NoError(t, err)
return m
}
tests := []struct {
input string
wantVal net.HardwareAddr
wantErr bool
}{
// Valid MAC.
{`"00:11:22:33:44:55"`, mac("00:11:22:33:44:55"), false},
{`"A1-B2-C3-D4-E5-F6"`, mac("A1-B2-C3-D4-E5-F6"), false},

// Invalid MAC.
{"01:23:45:67:89:GH", nil, true}, // GH is not a valid hex digit.
{`"00-1B-2C-3D-4E"`, nil, true}, // Too few octets.
{`"A1B2C3D4E5F6"`, nil, true}, // Missing separators.
}
for i, tt := range tests {
tt := tt
t.Run(fmt.Sprintf("Test%d", i+1), testDecodeEncode(
DecodeMAC,
EncodeMAC,
tt.input,
tt.wantVal,
tt.wantErr,
))
}
}

0 comments on commit 094db93

Please sign in to comment.