diff --git a/netipx.go b/netipx.go index 53ce503..08d57db 100644 --- a/netipx.go +++ b/netipx.go @@ -545,3 +545,33 @@ func appendRangePrefixes(dst []netip.Prefix, makePrefix prefixMaker, a, b uint12 dst = appendRangePrefixes(dst, makePrefix, b.bitsClearedFrom(common+1), b) return dst } + +// CompareAddr returns -1 if a.Less(b), 1 if b.Less(0), else it +// returns 0. +func CompareAddr(a, b netip.Addr) int { + if a.Less(b) { + return -1 + } + if b.Less(a) { + return 1 + } + return 0 +} + +// ComparePrefix -1 if a.Addr().Less(b), 1 if +// b.Addr().Less(0), else if a and b have the same address, it +// compares their prefix bit length, returning -1, 0, or 1. +func ComparePrefix(a, b netip.Prefix) int { + aa, ba := a.Addr(), b.Addr() + if aa == ba { + ab, bb := a.Bits(), b.Bits() + if ab < bb { + return -1 + } + if bb < ab { + return 1 + } + return 0 + } + return CompareAddr(a.Addr(), b.Addr()) +} diff --git a/netipx_test.go b/netipx_test.go index 8122ccf..1384333 100644 --- a/netipx_test.go +++ b/netipx_test.go @@ -871,3 +871,38 @@ func TestNoAllocs(t *testing.T) { sinkIPPrefix = panicPfxOK(a.Prefix()) }) } + +func TestCompareAddr(t *testing.T) { + tests := []struct { + a, b string + want int + }{ + {"1.1.1.1", "1.1.1.2", -1}, + {"1.1.1.2", "1.1.1.1", 1}, + {"1.1.1.1", "1.1.1.1", 0}, + {"1.1.1.1", "1::1", -1}, + } + for _, tt := range tests { + if got := CompareAddr(netip.MustParseAddr(tt.a), netip.MustParseAddr(tt.b)); got != tt.want { + t.Errorf("f(%q, %q) = %v; want %v", tt.a, tt.b, got, tt.want) + } + } +} + +func TestComparePrefix(t *testing.T) { + tests := []struct { + a, b string + want int + }{ + {"1.1.1.1/10", "1.1.1.2/10", -1}, + {"1.1.1.2/10", "1.1.1.1/10", 1}, + {"1.1.1.1/10", "1.1.1.1/10", 0}, + {"1.1.1.1/9", "1.1.1.1/10", -1}, + {"1.1.1.1/32", "1::1/128", -1}, + } + for _, tt := range tests { + if got := ComparePrefix(netip.MustParsePrefix(tt.a), netip.MustParsePrefix(tt.b)); got != tt.want { + t.Errorf("f(%q, %q) = %v; want %v", tt.a, tt.b, got, tt.want) + } + } +}