nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: inetaf/netaddr
Pull request #20 (2020-04-18 21:35:15)

netaddr: add IP.IsLoopback


Patch:
diff --git a/netaddr.go b/netaddr.go
index a7b7677..8956b70 100644
--- a/netaddr.go
+++ b/netaddr.go
@@ -60,8 +60,13 @@ func (ip v4Addr) as16() [16]byte {
 }
 func (ip v4Addr) String() string { return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]) }
 
-// mapped4Prefix are the 12 leading bytes in a IPv4-mapped IPv6 address.
-const mapped4Prefix = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"
+const (
+	// mapped4Prefix are the 12 leading bytes in a IPv4-mapped IPv6 address.
+	mapped4Prefix = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff"
+
+	// v6Loopback is the IPv6 loopback address.
+	v6Loopback = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
+)
 
 type v6Addr [16]byte
 
@@ -287,6 +292,23 @@ func (ip IP) IsLinkLocalUnicast() bool {
 	}
 }
 
+// IsLoopback reports whether ip is a loopback address. If ip is the zero value,
+// it will return false.
+func (ip IP) IsLoopback() bool {
+	switch ip := ip.ipImpl.(type) {
+	case nil:
+		return false
+	case v4Addr:
+		return ip[0] == 127
+	case v6Addr:
+		return string(ip[:len(v6Loopback)]) == v6Loopback
+	case v6AddrZone:
+		return string(ip.v6Addr[:len(v6Loopback)]) == v6Loopback
+	default:
+		panic("netaddr: unhandled ipImpl representation")
+	}
+}
+
 // IsMulticast reports whether ip is a multicast address. If ip is the zero
 // value, it will return false.
 func (ip IP) IsMulticast() bool {


Test patch:
diff --git a/netaddr_test.go b/netaddr_test.go
index 9623cd3..a726aee 100644
--- a/netaddr_test.go
+++ b/netaddr_test.go
@@ -212,6 +212,9 @@ func TestIPProperties(t *testing.T) {
 		llu4     = mustIP("169.254.0.1")
 		llu6     = mustIP("fe80::1")
 		lluZone6 = mustIP("fe80::1%eth0")
+
+		loopback4 = mustIP("127.0.0.1")
+		loopback6 = mustIP("::1")
 	)
 
 	tests := []struct {
@@ -219,6 +222,7 @@ func TestIPProperties(t *testing.T) {
 		ip               IP
 		multicast        bool
 		linkLocalUnicast bool
+		loopback         bool
 	}{
 		{
 			name: "nil",
@@ -266,6 +270,16 @@ func TestIPProperties(t *testing.T) {
 			ip:               lluZone6,
 			linkLocalUnicast: true,
 		},
+		{
+			name:     "loopback v4Addr",
+			ip:       loopback4,
+			loopback: true,
+		},
+		{
+			name:     "loopback v6Addr",
+			ip:       loopback6,
+			loopback: true,
+		},
 	}
 
 	for _, tt := range tests {
@@ -279,6 +293,11 @@ func TestIPProperties(t *testing.T) {
 			if llu != tt.linkLocalUnicast {
 				t.Errorf("IsLinkLocalUnicast(%v) = %v; want %v", tt.ip, llu, tt.linkLocalUnicast)
 			}
+
+			lo := tt.ip.IsLoopback()
+			if lo != tt.loopback {
+				t.Errorf("IsLoopback(%v) = %v; want %v", tt.ip, lo, tt.loopback)
+			}
 		})
 	}
 }
Repository: inetaf/netaddr
Pull request #24 (2020-04-21 20:28:04)

netaddr: add FromStdIPNet to convert *net.IPNet to IPPrefix
Signed-off-by: Matt Layher <mdlayher@gmail.com>

Mirrors the existing From* APIs.

mdlayher: No rush as I can get by with `ParseIPPrefix(cidr.String())` too, but let me know what you all think of this. Thanks!

Patch:
diff --git a/netaddr.go b/netaddr.go
index e1964e9..dccd128 100644
--- a/netaddr.go
+++ b/netaddr.go
@@ -499,6 +499,31 @@ type IPPrefix struct {
 	Bits uint8
 }
 
+// FromStdIPNet returns an IPPrefix from the standard library's IPNet type.
+// If std is invalid, ok is false.
+func FromStdIPNet(std *net.IPNet) (prefix IPPrefix, ok bool) {
+	ip, ok := FromStdIP(std.IP)
+	if !ok {
+		return IPPrefix{}, false
+	}
+
+	if l := len(std.Mask); l != net.IPv4len && l != net.IPv6len {
+		// Invalid mask.
+		return IPPrefix{}, false
+	}
+
+	ones, bits := std.Mask.Size()
+	if ones == 0 && bits == 0 {
+		// IPPrefix does not support non-contiguous masks.
+		return IPPrefix{}, false
+	}
+
+	return IPPrefix{
+		IP:   ip,
+		Bits: uint8(ones),
+	}, true
+}
+
 // ParseIPPrefix parses s as an IP address prefix.
 // The string can be in the form "192.168.1.0/24" or "2001::db8::/32",
 // the CIDR notation defined in RFC 4632 and RFC 4291.


Test patch:
diff --git a/netaddr_test.go b/netaddr_test.go
index ceffa44..d0ddbd9 100644
--- a/netaddr_test.go
+++ b/netaddr_test.go
@@ -618,6 +618,63 @@ func TestIPPrefix(t *testing.T) {
 	}
 }
 
+func TestFromStdIPNet(t *testing.T) {
+	tests := []struct {
+		name string
+		std  *net.IPNet
+		want IPPrefix
+	}{
+		{
+			name: "invalid IP",
+			std: &net.IPNet{
+				IP: net.IP{0xff},
+			},
+		},
+		{
+			name: "invalid mask",
+			std: &net.IPNet{
+				IP:   net.IPv6loopback,
+				Mask: nil,
+			},
+		},
+		{
+			name: "non-contiguous mask",
+			std: &net.IPNet{
+				IP:   net.IPv4(192, 0, 2, 0).To4(),
+				Mask: net.IPv4Mask(255, 0, 255, 0),
+			},
+		},
+		{
+			name: "IPv4",
+			std: &net.IPNet{
+				IP:   net.IPv4(192, 0, 2, 0).To4(),
+				Mask: net.CIDRMask(24, 32),
+			},
+			want: mustIPPrefix("192.0.2.0/24"),
+		},
+		{
+			name: "IPv6",
+			std: &net.IPNet{
+				IP:   net.ParseIP("2001:db8::"),
+				Mask: net.CIDRMask(64, 128),
+			},
+			want: mustIPPrefix("2001:db8::/64"),
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, ok := FromStdIPNet(tt.std)
+			if !ok && got != (IPPrefix{}) {
+				t.Fatalf("!ok but non-zero result")
+			}
+
+			if got != tt.want {
+				t.Errorf("FromStdIPNet(%q) = %+v; want %+v", tt.std, got, tt.want)
+			}
+		})
+	}
+}
+
 func TestParseIPPrefixAllocs(t *testing.T) {
 	tests := []struct {
 		ip    string
Repository: inetaf/netaddr
Pull request #28 (2020-04-30 16:08:00)

netaddr: add IPPrefix.{M,Un}arshalText methods
Signed-off-by: Matt Layher <mdlayher@gmail.com>

Updates #26.

bradfitz: LGTM but the commit message is not friendly to searching. Reword (even if longer) and feel free to submit.

mdlayher: Will do.

Patch:
diff --git a/netaddr.go b/netaddr.go
index db036d2..c440840 100644
--- a/netaddr.go
+++ b/netaddr.go
@@ -625,6 +625,34 @@ func (p IPPrefix) Contains(addr IP) bool {
 	return true
 }
 
+// MarshalText implements the encoding.TextMarshaler interface,
+// The encoding is the same as returned by String, with one exception:
+// If p is the zero value, the encoding is the empty string.
+func (p IPPrefix) MarshalText() ([]byte, error) {
+	if p == (IPPrefix{}) {
+		return []byte(""), nil
+	}
+
+	return []byte(p.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The IP address is expected in a form accepted by ParseIPPrefix.
+// It returns an error if *p is not the IPPrefix zero value.
+func (p *IPPrefix) UnmarshalText(text []byte) error {
+	if *p != (IPPrefix{}) {
+		return errors.New("netaddr: refusing to Unmarshal into non-zero IPPrefix")
+	}
+
+	if len(text) == 0 {
+		return nil
+	}
+
+	var err error
+	*p, err = ParseIPPrefix(string(text))
+	return err
+}
+
 // Strings returns the CIDR notation of p: "<ip>/<bits>".
 func (p IPPrefix) String() string {
 	return fmt.Sprintf("%s/%d", p.IP, p.Bits)


Test patch:
diff --git a/netaddr_test.go b/netaddr_test.go
index d1da8ad..264e968 100644
--- a/netaddr_test.go
+++ b/netaddr_test.go
@@ -495,6 +495,49 @@ func TestIPPrefixMasking(t *testing.T) {
 	}
 }
 
+func TestIPPrefixMarshalUnmarshal(t *testing.T) {
+	tests := []string{
+		"",
+		"1.2.3.4/32",
+		"0.0.0.0/0",
+		"::/0",
+		"::1/128",
+		"fe80::1cc0:3e8c:119f:c2e1%ens18/128",
+		"::ffff:c000:1234/128",
+		"2001:db8::/32",
+	}
+
+	for _, s := range tests {
+		t.Run(s, func(t *testing.T) {
+			// Ensure that JSON  (and by extension, text) marshaling is
+			// sane by entering quoted input.
+			orig := `"` + s + `"`
+
+			var p IPPrefix
+			if err := json.Unmarshal([]byte(orig), &p); err != nil {
+				t.Fatalf("failed to unmarshal: %v", err)
+			}
+
+			pb, err := json.Marshal(p)
+			if err != nil {
+				t.Fatalf("failed to marshal: %v", err)
+			}
+
+			back := string(pb)
+			if orig != back {
+				t.Errorf("Marshal = %q; want %q", back, orig)
+			}
+		})
+	}
+}
+
+func TestIPPrefixUnmarshalTextNonZero(t *testing.T) {
+	ip := mustIPPrefix("fe80::/64")
+	if err := ip.UnmarshalText([]byte("xxx")); err == nil {
+		t.Fatal("unmarshaled into non-empty IPPrefix")
+	}
+}
+
 func TestIs4AndIs6(t *testing.T) {
 	tests := []struct {
 		ip  IP
Repository: inetaf/netaddr
Pull request #47 (2020-08-10 10:29:29)

introduce IPPrefix.Masked for zeroing masked address bits
As suggested by @bradfitz in https://github.com/inetaf/netaddr/pull/46#issuecomment-671100081.


Patch:
diff --git a/netaddr.go b/netaddr.go
index b1b01a5..7431bf3 100644
--- a/netaddr.go
+++ b/netaddr.go
@@ -681,6 +681,8 @@ func FromStdIPNet(std *net.IPNet) (prefix IPPrefix, ok bool) {
 // ParseIPPrefix parses s as an IP address prefix.
 // The string can be in the form "192.168.1.0/24" or "2001::db8::/32",
 // the CIDR notation defined in RFC 4632 and RFC 4291.
+//
+// Note that masked address bits are not zeroed. Use Masked for that.
 func ParseIPPrefix(s string) (IPPrefix, error) {
 	i := strings.IndexByte(s, '/')
 	if i < 0 {
@@ -708,6 +710,15 @@ func ParseIPPrefix(s string) (IPPrefix, error) {
 	}, nil
 }
 
+// Masked returns p in its canonical form, with bits of of p.IP not in p.Bits masked off.
+// If p is zero or otherwise invalid, Masked returns the zero value.
+func (p IPPrefix) Masked() IPPrefix {
+	if m, err := p.IP.Prefix(p.Bits); err == nil {
+		return m
+	}
+	return IPPrefix{}
+}
+
 // IPNet returns the net.IPNet representation of an IPPrefix.
 // The returned value is always non-nil.
 // Any zone identifier is dropped in the conversion.


Test patch:
diff --git a/netaddr_test.go b/netaddr_test.go
index 686db03..93bfbb8 100644
--- a/netaddr_test.go
+++ b/netaddr_test.go
@@ -711,6 +711,34 @@ func TestIs4In6(t *testing.T) {
 	}
 }
 
+func TestIPPrefixMasked(t *testing.T) {
+	tests := []struct {
+		prefix string
+		ip     IP
+	}{
+		{
+			prefix: "192.168.0.255/24",
+			ip:     mustIP("192.168.0.0"),
+		},
+		{
+			prefix: "2100::/3",
+			ip:     mustIP("2000::"),
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.prefix, func(t *testing.T) {
+			prefix, err := ParseIPPrefix(test.prefix)
+			if err != nil {
+				t.Fatal(err)
+			}
+			prefix = prefix.Masked()
+			if prefix.IP != test.ip {
+				t.Errorf("IP=%s, want %s", prefix.IP, test.ip)
+			}
+		})
+	}
+}
+
 func TestIPPrefix(t *testing.T) {
 	tests := []struct {
 		prefix      string
Repository: inetaf/netaddr
Pull request #50 (2020-11-23 19:16:02)

Add IPRangeSet.ContainsFunc
cc @josharian too


Patch:
diff --git a/netaddr.go b/netaddr.go
index af633da..fbd9deb 100644
--- a/netaddr.go
+++ b/netaddr.go
@@ -1290,3 +1290,28 @@ func (s *IPRangeSet) Prefixes() []IPPrefix {
 	}
 	return out
 }
+
+// ContainsFunc returns a func that reports whether an IP is in s.
+// The returned func opertes on a copy of s, so s may be mutated
+// later.
+func (s *IPRangeSet) ContainsFunc() (contains func(IP) bool) {
+	rv := s.Ranges()
+	// TODO(bradfitz): build a faster data structure with
+	// with s.Prefixes()?
+	return func(ip IP) bool {
+		i := sort.Search(len(rv), func(i int) bool {
+			return ip.Less(rv[i].From)
+		})
+		if i == 0 {
+			return false
+		}
+		i--
+		if ip.Less(rv[i].From) {
+			return false
+		}
+		if rv[i].To.Less(ip) {
+			return false
+		}
+		return true
+	}
+}


Test patch:
diff --git a/example_test.go b/example_test.go
new file mode 100644
index 0000000..d0ec0da
--- /dev/null
+++ b/example_test.go
@@ -0,0 +1,48 @@
+// Copyright 2020 The Inet.Af AUTHORS. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package netaddr_test
+
+import (
+	"fmt"
+
+	"inet.af/netaddr"
+)
+
+func ExampleIPRangeSet() {
+	var s netaddr.IPRangeSet
+
+	p, _ := netaddr.ParseIPPrefix("10.0.0.0/8")
+	s.AddPrefix(p)
+	p, _ = netaddr.ParseIPPrefix("10.0.0.0/16")
+	s.RemovePrefix(p)
+
+	ip1, _ := netaddr.ParseIP("fed0::0400")
+	ip2, _ := netaddr.ParseIP("fed0::04ff")
+	s.AddRange(netaddr.IPRange{From: ip1, To: ip2})
+
+	fmt.Println("Ranges:")
+	for _, r := range s.Ranges() {
+		fmt.Printf("  %s - %s\n", r.From, r.To)
+	}
+
+	fmt.Println("Prefixes:")
+	for _, p := range s.Prefixes() {
+		fmt.Printf("  %s\n", p)
+	}
+	// Output:
+	// Ranges:
+	//   10.1.0.0 - 10.255.255.255
+	//   fed0::400 - fed0::4ff
+	// Prefixes:
+	//   10.1.0.0/16
+	//   10.2.0.0/15
+	//   10.4.0.0/14
+	//   10.8.0.0/13
+	//   10.16.0.0/12
+	//   10.32.0.0/11
+	//   10.64.0.0/10
+	//   10.128.0.0/9
+	//   fed0::400/120
+}
diff --git a/netaddr_test.go b/netaddr_test.go
index dc0fa6c..9aa1156 100644
--- a/netaddr_test.go
+++ b/netaddr_test.go
@@ -1701,3 +1701,41 @@ func TestIPNextPrior(t *testing.T) {
 		}
 	}
 }
+
+func TestIPRangeSetContainsFunc(t *testing.T) {
+	var s IPRangeSet
+	s.AddPrefix(mustIPPrefix("10.0.0.0/8"))
+	s.AddPrefix(mustIPPrefix("1.2.3.4/32"))
+	s.AddPrefix(mustIPPrefix("fc00::/7"))
+	contains := s.ContainsFunc()
+
+	tests := []struct {
+		ip   string
+		want bool
+	}{
+		{"0.0.0.0", false},
+		{"::", false},
+
+		{"1.2.3.3", false},
+		{"1.2.3.4", true},
+		{"1.2.3.5", false},
+
+		{"9.255.255.255", false},
+		{"10.0.0.0", true},
+		{"10.1.2.3", true},
+		{"10.255.255.255", true},
+		{"11.0.0.0", false},
+
+		{"::", false},
+		{"fc00::", true},
+		{"fc00::1", true},
+		{"fd00::1", true},
+		{"ff00::1", false},
+	}
+	for _, tt := range tests {
+		got := contains(mustIP(tt.ip))
+		if got != tt.want {
+			t.Errorf("contains(%q) = %v; want %v", tt.ip, got, tt.want)
+		}
+	}
+}
Repository: inetaf/netaddr
Pull request #52 (2020-12-15 18:35:44)

netaddr: add IP.BitLen method


Patch:
diff --git a/netaddr.go b/netaddr.go
index 32ee1b3..54b8bc2 100644
--- a/netaddr.go
+++ b/netaddr.go
@@ -282,10 +282,26 @@ func FromStdIPRaw(std net.IP) (ip IP, ok bool) {
 	return IP{}, false
 }
 
-// IsZero reports whether ip is its zero value. The IP zero value is
-// not a valid IP address of any type.
+// IsZero reports whether ip is the zero value of the IP type.
+// The zero value is not a valid IP address of any type.
+//
+// Note that "0.0.0.0" and "::" are not the zero value.
 func (ip IP) IsZero() bool { return ip == IP{} }
 
+// BitLen returns the number of bits in the IP address:
+// 32 for IPv4 or 128 for IPv6.
+// For the zero value (see IP.IsZero), it returns 0.
+// For IP4-mapped IPv6 addresses, it returns 128.
+func (ip IP) BitLen() uint8 {
+	if ip.IsZero() {
+		return 0
+	}
+	if ip.ipImpl.is4() {
+		return 32
+	}
+	return 128
+}
+
 // Zone returns ip's IPv6 scoped addressing zone, if any.
 func (ip IP) Zone() string {
 	if v6z, ok := ip.ipImpl.(v6AddrZone); ok {


Test patch:
diff --git a/netaddr_test.go b/netaddr_test.go
index b232b2d..917e393 100644
--- a/netaddr_test.go
+++ b/netaddr_test.go
@@ -1750,6 +1750,26 @@ func TestIPNextPrior(t *testing.T) {
 	}
 }
 
+func TestIPBitLen(t *testing.T) {
+	tests := []struct {
+		ip   IP
+		want uint8
+	}{
+		{IP{}, 0},
+		{mustIP("0.0.0.0"), 32},
+		{mustIP("10.0.0.1"), 32},
+		{mustIP("::"), 128},
+		{mustIP("fed0::1"), 128},
+		{mustIP("::ffff:10.0.0.1"), 128},
+	}
+	for _, tt := range tests {
+		got := tt.ip.BitLen()
+		if got != tt.want {
+			t.Errorf("BitLen(%v) = %d; want %d", tt.ip, got, tt.want)
+		}
+	}
+}
+
 func TestIPSetContainsFunc(t *testing.T) {
 	var s IPSet
 	s.AddPrefix(mustIPPrefix("10.0.0.0/8"))