diff --git a/net/ip.go b/net/ip.go index 616658ca14977195a4d3b81a3db73f64d61f3399..44b84d192402d5e309ea9e394ee5237664cecae2 100644 --- a/net/ip.go +++ b/net/ip.go @@ -62,6 +62,21 @@ func IPFromBytes(b []byte) (IP, error) { return IP{}, fmt.Errorf("byte slice has an invalid legth. Expected either 4 (IPv4) or 16 (IPv6) bytes but got: %d", len(b)) } +// IPFromString returns an IP address for a given string +func IPFromString(str string) (IP, error) { + ip := net.ParseIP(str) + if ip == nil { + return IP{}, fmt.Errorf("%s is not a valid IP address", str) + } + + ip4 := ip.To4() + if ip4 != nil { + return IPFromBytes(ip4) + } + + return IPFromBytes(ip.To16()) +} + // Equal returns true if ip is equal to other func (ip IP) Equal(other IP) bool { return ip == other diff --git a/net/ip_test.go b/net/ip_test.go index 4720985f825ba242b1c78cf75773499d55bdd9bf..961730c01844a3c13c569de97eb7caed0be0567e 100644 --- a/net/ip_test.go +++ b/net/ip_test.go @@ -370,3 +370,46 @@ func TestBitAtPosition(t *testing.T) { } } } + +func TestIPFromString(t *testing.T) { + tests := []struct { + name string + input string + expected IP + wantFail bool + }{ + { + name: "ipv4", + input: "192.168.1.234", + expected: IPv4FromOctets(192, 168, 1, 234), + }, + { + name: "ipv6", + input: "2001:678:1e0::cafe", + expected: IPv6FromBlocks(0x2001, 0x678, 0x1e0, 0, 0, 0, 0, 0xcafe), + }, + { + name: "invalid", + input: "foo", + wantFail: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ip, err := IPFromString(test.input) + if err == nil && test.wantFail { + t.Fatal("expected error but got nil") + } + if err != nil { + if test.wantFail { + return + } + + t.Fatal(err) + } + + assert.Equal(t, test.expected, ip) + }) + } +}