summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2023-08-18 08:03:32 -0700
committerBrad Fitzpatrick <brad@danga.com>2023-08-18 08:21:52 -0700
commit261cc498d3ad1a09ecfd1baeef583dc260c85f38 (patch)
tree2f7b45d1eadabf3d1bd586afaae00e4010db1c24
parentaf2e4909b6e977225922551f5b694f9d61c87545 (diff)
downloadtailscale-261cc498d3ad1a09ecfd1baeef583dc260c85f38.tar.xz
tailscale-261cc498d3ad1a09ecfd1baeef583dc260c85f38.zip
types/views: add LenIter method to slice view types
This is basically https://github.com/bradfitz/iter which was a joke but now that Go's adding range over int soonish, might as well. It simplies our code elsewher that uses slice views. Updates #8948 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
-rw-r--r--types/views/views.go15
-rw-r--r--types/views/views_test.go12
2 files changed, 27 insertions, 0 deletions
diff --git a/types/views/views.go b/types/views/views.go
index 5297ba864..b86c3f94a 100644
--- a/types/views/views.go
+++ b/types/views/views.go
@@ -73,6 +73,11 @@ func (v SliceView[T, V]) IsNil() bool { return v.ж == nil }
// Len returns the length of the slice.
func (v SliceView[T, V]) Len() int { return len(v.ж) }
+// LenIter returns a slice the same length as the v.Len().
+// The caller can then range over it to get the valid indexes.
+// It does not allocate.
+func (v SliceView[T, V]) LenIter() []struct{} { return make([]struct{}, len(v.ж)) }
+
// At returns a View of the element at index `i` of the slice.
func (v SliceView[T, V]) At(i int) V { return v.ж[i].View() }
@@ -129,6 +134,11 @@ func (v Slice[T]) IsNil() bool { return v.ж == nil }
// Len returns the length of the slice.
func (v Slice[T]) Len() int { return len(v.ж) }
+// LenIter returns a slice the same length as the v.Len().
+// The caller can then range over it to get the valid indexes.
+// It does not allocate.
+func (v Slice[T]) LenIter() []struct{} { return make([]struct{}, len(v.ж)) }
+
// At returns the element at index `i` of the slice.
func (v Slice[T]) At(i int) T { return v.ж[i] }
@@ -233,6 +243,11 @@ func (v IPPrefixSlice) IsNil() bool { return v.ж.IsNil() }
// Len returns the length of the slice.
func (v IPPrefixSlice) Len() int { return v.ж.Len() }
+// LenIter returns a slice the same length as the v.Len().
+// The caller can then range over it to get the valid indexes.
+// It does not allocate.
+func (v IPPrefixSlice) LenIter() []struct{} { return make([]struct{}, v.ж.Len()) }
+
// At returns the IPPrefix at index `i` of the slice.
func (v IPPrefixSlice) At(i int) netip.Prefix { return v.ж.At(i) }
diff --git a/types/views/views_test.go b/types/views/views_test.go
index 536372bcd..c78bd6dde 100644
--- a/types/views/views_test.go
+++ b/types/views/views_test.go
@@ -138,3 +138,15 @@ func TestViewUtils(t *testing.T) {
SliceOf([]string{"b", "c"}).SliceTo(1)),
qt.Equals, true)
}
+
+func TestLenIter(t *testing.T) {
+ orig := []string{"foo", "bar"}
+ var got []string
+ v := SliceOf(orig)
+ for i := range v.LenIter() {
+ got = append(got, v.At(i))
+ }
+ if !reflect.DeepEqual(orig, got) {
+ t.Errorf("got %q; want %q", got, orig)
+ }
+}