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 <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-07-24 10:55:36 -07:00 committed by Brad Fitzpatrick
parent aedfb82876
commit e54c81d1d0
3 changed files with 35 additions and 13 deletions

View File

@ -2095,9 +2095,7 @@ func (b *LocalBackend) updateFilterLocked(netMap *netmap.NetworkMap, prefs ipn.P
} }
} }
if prefs.Valid() { if prefs.Valid() {
ar := prefs.AdvertiseRoutes() for _, r := range prefs.AdvertiseRoutes().All() {
for i := range ar.Len() {
r := ar.At(i)
if r.Bits() == 0 { if r.Bits() == 0 {
// When offering a default route to the world, we // When offering a default route to the world, we
// filter out locally reachable LANs, so that the // filter out locally reachable LANs, so that the
@ -2312,8 +2310,8 @@ func packetFilterPermitsUnlockedNodes(peers map[tailcfg.NodeID]tailcfg.NodeView,
continue continue
} }
numUnlocked++ numUnlocked++
for i := range p.AllowedIPs().Len() { // not only addresses! for _, pfx := range p.AllowedIPs().All() { // not only addresses!
b.AddPrefix(p.AllowedIPs().At(i)) b.AddPrefix(pfx)
} }
} }
if numUnlocked == 0 { if numUnlocked == 0 {
@ -4105,15 +4103,14 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, peers map[tailcfg.NodeID]tailcfg.
return // TODO: propagate error? return // TODO: propagate error?
} }
var have4 bool var have4 bool
for i := range addrs.Len() { for _, addr := range addrs.All() {
if addrs.At(i).Addr().Is4() { if addr.Addr().Is4() {
have4 = true have4 = true
break break
} }
} }
var ips []netip.Addr var ips []netip.Addr
for i := range addrs.Len() { for _, addr := range addrs.All() {
addr := addrs.At(i)
if selfV6Only { if selfV6Only {
if addr.Addr().Is6() { if addr.Addr().Is6() {
ips = append(ips, addr.Addr()) ips = append(ips, addr.Addr())
@ -4401,8 +4398,7 @@ func (b *LocalBackend) initPeerAPIListener() {
b.peerAPIServer = ps b.peerAPIServer = ps
isNetstack := b.sys.IsNetstack() isNetstack := b.sys.IsNetstack()
for i := range addrs.Len() { for i, a := range addrs.All() {
a := addrs.At(i)
var ln net.Listener var ln net.Listener
var err error var err error
skipListen := i > 0 && isNetstack skipListen := i > 0 && isNetstack
@ -5263,8 +5259,8 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) {
b.nodeByAddr[k] = 0 b.nodeByAddr[k] = 0
} }
addNode := func(n tailcfg.NodeView) { addNode := func(n tailcfg.NodeView) {
for i := range n.Addresses().Len() { for _, ipp := range n.Addresses().All() {
if ipp := n.Addresses().At(i); ipp.IsSingleIP() { if ipp.IsSingleIP() {
b.nodeByAddr[ipp.Addr()] = n.ID() b.nodeByAddr[ipp.Addr()] = n.ID()
} }
} }

View File

@ -10,6 +10,7 @@
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"iter"
"maps" "maps"
"reflect" "reflect"
"slices" "slices"
@ -208,6 +209,17 @@ type Slice[T any] struct {
ж []T ж []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. // MapKey returns a unique key for a slice, based on its address and length.
func (v Slice[T]) MapKey() SliceMapKey[T] { return mapKey(v.ж) } func (v Slice[T]) MapKey() SliceMapKey[T] { return mapKey(v.ж) }

View File

@ -6,8 +6,10 @@
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"net/netip" "net/netip"
"reflect" "reflect"
"slices"
"strings" "strings"
"testing" "testing"
"unsafe" "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)
}
}