diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2022-07-21 08:06:01 -0700 |
|---|---|---|
| committer | Brad Fitzpatrick <brad@danga.com> | 2022-07-21 08:28:43 -0700 |
| commit | 43f3a969ca71c5769aeca6c2ee6bc283a504acd1 (patch) | |
| tree | 05f9307d446eaedadf53db9c52bfa8707b150956 | |
| parent | d8cb5aae1720c3edc5e30f77b5fc7634e940a252 (diff) | |
| download | tailscale-43f3a969ca71c5769aeca6c2ee6bc283a504acd1.tar.xz tailscale-43f3a969ca71c5769aeca6c2ee6bc283a504acd1.zip | |
types/views: add SliceContains, View.ContainsFunc, View.IndexFunc
We were starting to write these elsewhere as little unexported copies
in misc places.
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
| -rw-r--r-- | types/views/views.go | 37 | ||||
| -rw-r--r-- | types/views/views_test.go | 13 |
2 files changed, 50 insertions, 0 deletions
diff --git a/types/views/views.go b/types/views/views.go index bf9f2e4e9..e14ddcbdb 100644 --- a/types/views/views.go +++ b/types/views/views.go @@ -132,6 +132,43 @@ func (v Slice[T]) AsSlice() []T { return v.AppendTo(v.ж[:0:0]) } +// IndexFunc returns the first index of an element in v satisfying f(e), +// or -1 if none do. +// +// As it runs in O(n) time, use with care. +func (v Slice[T]) IndexFunc(f func(T) bool) int { + for i := 0; i < v.Len(); i++ { + if f(v.At(i)) { + return i + } + } + return -1 +} + +// ContainsFunc reports whether any element in v satisfies f(e). +// +// As it runs in O(n) time, use with care. +func (v Slice[T]) ContainsFunc(f func(T) bool) bool { + for i := 0; i < v.Len(); i++ { + if f(v.At(i)) { + return true + } + } + return false +} + +// SliceContains reports whether v contains element e. +// +// As it runs in O(n) time, use with care. +func SliceContains[T comparable](v Slice[T], e T) bool { + for i := 0; i < v.Len(); i++ { + if v.At(i) == e { + return true + } + } + return false +} + // IPPrefixSlice is a read-only accessor for a slice of netaddr.IPPrefix. type IPPrefixSlice struct { ж Slice[netaddr.IPPrefix] diff --git a/types/views/views_test.go b/types/views/views_test.go index d9785c9a1..b6e91e825 100644 --- a/types/views/views_test.go +++ b/types/views/views_test.go @@ -11,6 +11,7 @@ import ( "strings" "testing" + qt "github.com/frankban/quicktest" "inet.af/netaddr" ) @@ -73,3 +74,15 @@ func TestViewsJSON(t *testing.T) { } } } + +func TestViewUtils(t *testing.T) { + v := SliceOf([]string{"foo", "bar"}) + c := qt.New(t) + + c.Check(v.ContainsFunc(func(s string) bool { return strings.HasPrefix(s, "f") }), qt.Equals, true) + c.Check(v.ContainsFunc(func(s string) bool { return strings.HasPrefix(s, "g") }), qt.Equals, false) + c.Check(v.IndexFunc(func(s string) bool { return strings.HasPrefix(s, "b") }), qt.Equals, 1) + c.Check(v.IndexFunc(func(s string) bool { return strings.HasPrefix(s, "z") }), qt.Equals, -1) + c.Check(SliceContains(v, "bar"), qt.Equals, true) + c.Check(SliceContains(v, "baz"), qt.Equals, false) +} |
