From 43f3a969ca71c5769aeca6c2ee6bc283a504acd1 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 21 Jul 2022 08:06:01 -0700 Subject: [PATCH] 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 --- types/views/views.go | 37 +++++++++++++++++++++++++++++++++++++ types/views/views_test.go | 13 +++++++++++++ 2 files changed, 50 insertions(+) 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) +}