Skip to content

Commit

Permalink
Merge pull request #3 from go-viper/netip
Browse files Browse the repository at this point in the history
Add decode hooks for netip Addr and AddrPort
  • Loading branch information
sagikazarmark authored Dec 18, 2023
2 parents c2530db + 4be8357 commit 7b7fc8e
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
41 changes: 41 additions & 0 deletions decode_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net"
"net/netip"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -288,3 +289,43 @@ func TextUnmarshallerHookFunc() DecodeHookFuncType {
return result, nil
}
}

// StringToNetIPAddrHookFunc returns a DecodeHookFunc that converts
// strings to netip.Addr.
func StringToNetIPAddrHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}
if t != reflect.TypeOf(netip.Addr{}) {
return data, nil
}

// Convert it by parsing
return netip.ParseAddr(data.(string))
}
}

// StringToNetIPAddrPortHookFunc returns a DecodeHookFunc that converts
// strings to netip.AddrPort.
func StringToNetIPAddrPortHookFunc() DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{},
) (interface{}, error) {
if f.Kind() != reflect.String {
return data, nil
}
if t != reflect.TypeOf(netip.AddrPort{}) {
return data, nil
}

// Convert it by parsing
return netip.ParseAddrPort(data.(string))
}
}
61 changes: 61 additions & 0 deletions decode_hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"math/big"
"net"
"net/netip"
"reflect"
"testing"
"time"
Expand Down Expand Up @@ -585,3 +586,63 @@ func TestTextUnmarshallerHookFunc(t *testing.T) {
}
}
}

func TestStringToNetIPAddrHookFunc(t *testing.T) {
strValue := reflect.ValueOf("5")
addrValue := reflect.ValueOf(netip.Addr{})
cases := []struct {
f, t reflect.Value
result interface{}
err bool
}{
{
reflect.ValueOf("192.0.2.1"), addrValue,
netip.AddrFrom4([4]byte{0xc0, 0x00, 0x02, 0x01}), false,
},
{strValue, addrValue, netip.Addr{}, true},
{strValue, strValue, "5", false},
}

for i, tc := range cases {
f := StringToNetIPAddrHookFunc()
actual, err := DecodeHookExec(f, tc.f, tc.t)
if tc.err != (err != nil) {
t.Fatalf("case %d: expected err %#v", i, tc.err)
}
if !reflect.DeepEqual(actual, tc.result) {
t.Fatalf(
"case %d: expected %#v, got %#v",
i, tc.result, actual)
}
}
}

func TestStringToNetIPAddrPortHookFunc(t *testing.T) {
strValue := reflect.ValueOf("5")
addrPortValue := reflect.ValueOf(netip.AddrPort{})
cases := []struct {
f, t reflect.Value
result interface{}
err bool
}{
{
reflect.ValueOf("192.0.2.1:80"), addrPortValue,
netip.AddrPortFrom(netip.AddrFrom4([4]byte{0xc0, 0x00, 0x02, 0x01}), 80), false,
},
{strValue, addrPortValue, netip.AddrPort{}, true},
{strValue, strValue, "5", false},
}

for i, tc := range cases {
f := StringToNetIPAddrPortHookFunc()
actual, err := DecodeHookExec(f, tc.f, tc.t)
if tc.err != (err != nil) {
t.Fatalf("case %d: expected err %#v", i, tc.err)
}
if !reflect.DeepEqual(actual, tc.result) {
t.Fatalf(
"case %d: expected %#v, got %#v",
i, tc.result, actual)
}
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/mitchellh/mapstructure

go 1.14
go 1.18

0 comments on commit 7b7fc8e

Please sign in to comment.