util/slicesx: add EqualSameNil, like slices.Equal but same nilness

Then use it in tailcfg which had it duplicated a couple times.

I think we have it a few other places too.

And use slices.Equal in wgengine/router too. (found while looking for callers)

Updates #cleanup

Change-Id: If5350eee9b3ef071882a3db29a305081e4cd9d23
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2023-09-30 15:28:14 -07:00
committed by Brad Fitzpatrick
parent 72e53749c1
commit 5f5c9142cc
4 changed files with 41 additions and 55 deletions

View File

@@ -57,3 +57,23 @@ func Partition[S ~[]T, T any](s S, cb func(T) bool) (trues, falses S) {
}
return
}
// EqualSameNil reports whether two slices are equal: the same length, same
// nilness (notably when length zero), and all elements equal. If the lengths
// are different or their nilness differs, Equal returns false. Otherwise, the
// elements are compared in increasing index order, and the comparison stops at
// the first unequal pair. Floating point NaNs are not considered equal.
//
// It is identical to the standard library's slices.Equal but adds the matching
// nilness check.
func EqualSameNil[S ~[]E, E comparable](s1, s2 S) bool {
if len(s1) != len(s2) || (s1 == nil) != (s2 == nil) {
return false
}
for i := range s1 {
if s1[i] != s2[i] {
return false
}
}
return true
}

View File

@@ -7,6 +7,8 @@ import (
"reflect"
"slices"
"testing"
qt "github.com/frankban/quicktest"
)
func TestInterleave(t *testing.T) {
@@ -84,3 +86,14 @@ func TestPartition(t *testing.T) {
t.Errorf("odds: got %v, want %v", odds, wantOdds)
}
}
func TestEqualSameNil(t *testing.T) {
c := qt.New(t)
c.Check(EqualSameNil([]string{"a"}, []string{"a"}), qt.Equals, true)
c.Check(EqualSameNil([]string{"a"}, []string{"b"}), qt.Equals, false)
c.Check(EqualSameNil([]string{"a"}, []string{}), qt.Equals, false)
c.Check(EqualSameNil([]string{}, []string{}), qt.Equals, true)
c.Check(EqualSameNil(nil, []string{}), qt.Equals, false)
c.Check(EqualSameNil([]string{}, nil), qt.Equals, false)
c.Check(EqualSameNil[[]string](nil, nil), qt.Equals, true)
}