From e54c81d1d0fbad3ef2883efa19e381175ee2c00a Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 24 Jul 2024 10:55:36 -0700 Subject: [PATCH] types/views: add Slice.All iterator And convert a few callers as an example, but nowhere near all. Updates #12912 Change-Id: I5eaa12a29a6cd03b58d6f1072bd27bc0467852f2 Signed-off-by: Brad Fitzpatrick --- ipn/ipnlocal/local.go | 22 +++++++++------------- types/views/views.go | 12 ++++++++++++ types/views/views_test.go | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 2b268c766..679f10e38 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -2095,9 +2095,7 @@ func (b *LocalBackend) updateFilterLocked(netMap *netmap.NetworkMap, prefs ipn.P } } if prefs.Valid() { - ar := prefs.AdvertiseRoutes() - for i := range ar.Len() { - r := ar.At(i) + for _, r := range prefs.AdvertiseRoutes().All() { if r.Bits() == 0 { // When offering a default route to the world, we // filter out locally reachable LANs, so that the @@ -2312,8 +2310,8 @@ func packetFilterPermitsUnlockedNodes(peers map[tailcfg.NodeID]tailcfg.NodeView, continue } numUnlocked++ - for i := range p.AllowedIPs().Len() { // not only addresses! - b.AddPrefix(p.AllowedIPs().At(i)) + for _, pfx := range p.AllowedIPs().All() { // not only addresses! + b.AddPrefix(pfx) } } if numUnlocked == 0 { @@ -4105,15 +4103,14 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg. return // TODO: propagate error? } var have4 bool - for i := range addrs.Len() { - if addrs.At(i).Addr().Is4() { + for _, addr := range addrs.All() { + if addr.Addr().Is4() { have4 = true break } } var ips []netip.Addr - for i := range addrs.Len() { - addr := addrs.At(i) + for _, addr := range addrs.All() { if selfV6Only { if addr.Addr().Is6() { ips = append(ips, addr.Addr()) @@ -4401,8 +4398,7 @@ func (b *LocalBackend) initPeerAPIListener() { b.peerAPIServer = ps isNetstack := b.sys.IsNetstack() - for i := range addrs.Len() { - a := addrs.At(i) + for i, a := range addrs.All() { var ln net.Listener var err error skipListen := i > 0 && isNetstack @@ -5263,8 +5259,8 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) { b.nodeByAddr[k] = 0 } addNode := func(n tailcfg.NodeView) { - for i := range n.Addresses().Len() { - if ipp := n.Addresses().At(i); ipp.IsSingleIP() { + for _, ipp := range n.Addresses().All() { + if ipp.IsSingleIP() { b.nodeByAddr[ipp.Addr()] = n.ID() } } diff --git a/types/views/views.go b/types/views/views.go index 4edd72688..b99a20a48 100644 --- a/types/views/views.go +++ b/types/views/views.go @@ -10,6 +10,7 @@ import ( "encoding/json" "errors" "fmt" + "iter" "maps" "reflect" "slices" @@ -208,6 +209,17 @@ type Slice[T any] struct { ж []T } +// All returns an iterator over v. +func (v Slice[T]) All() iter.Seq2[int, T] { + return func(yield func(int, T) bool) { + for i, v := range v.ж { + if !yield(i, v) { + return + } + } + } +} + // MapKey returns a unique key for a slice, based on its address and length. func (v Slice[T]) MapKey() SliceMapKey[T] { return mapKey(v.ж) } diff --git a/types/views/views_test.go b/types/views/views_test.go index 1a4f1f2d4..24118d099 100644 --- a/types/views/views_test.go +++ b/types/views/views_test.go @@ -6,8 +6,10 @@ package views import ( "bytes" "encoding/json" + "fmt" "net/netip" "reflect" + "slices" "strings" "testing" "unsafe" @@ -412,3 +414,15 @@ func TestContainsPointers(t *testing.T) { }) } } + +func TestSliceRange(t *testing.T) { + sv := SliceOf([]string{"foo", "bar"}) + var got []string + for i, v := range sv.All() { + got = append(got, fmt.Sprintf("%d-%s", i, v)) + } + want := []string{"0-foo", "1-bar"} + if !slices.Equal(got, want) { + t.Errorf("got %q; want %q", got, want) + } +}