From 261cc498d3ad1a09ecfd1baeef583dc260c85f38 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 18 Aug 2023 08:03:32 -0700 Subject: [PATCH] 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 --- types/views/views.go | 15 +++++++++++++++ types/views/views_test.go | 12 ++++++++++++ 2 files changed, 27 insertions(+) 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) + } +}