mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
cmd/viewer, types/views, all: un-special case slice of netip.Prefix
Make it just a views.Slice[netip.Prefix] instead of its own named type. Having the special case led to circular dependencies in another WIP PR of mine. Updates #8948 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
261cc498d3
commit
6e57dee7eb
@ -15,6 +15,7 @@
|
||||
"tailscale.com/net/netutil"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/safesocket"
|
||||
"tailscale.com/types/views"
|
||||
)
|
||||
|
||||
var setCmd = &ffcli.Command{
|
||||
@ -171,7 +172,7 @@ func calcAdvertiseRoutesForSet(advertiseExitNodeSet, advertiseRoutesSet bool, cu
|
||||
if alreadyAdvertisesExitNode == setArgs.advertiseDefaultRoute {
|
||||
return curPrefs.AdvertiseRoutes, nil
|
||||
}
|
||||
routes = tsaddr.FilterPrefixesCopy(curPrefs.AdvertiseRoutes, func(p netip.Prefix) bool {
|
||||
routes = tsaddr.FilterPrefixesCopy(views.SliceOf(curPrefs.AdvertiseRoutes), func(p netip.Prefix) bool {
|
||||
return p.Bits() != 0
|
||||
})
|
||||
if setArgs.advertiseDefaultRoute {
|
||||
|
@ -309,8 +309,8 @@ func (v StructWithSlicesView) StructPointers() views.SliceView[*StructWithPtrs,
|
||||
func (v StructWithSlicesView) Structs() StructWithPtrs { panic("unsupported") }
|
||||
func (v StructWithSlicesView) Ints() *int { panic("unsupported") }
|
||||
func (v StructWithSlicesView) Slice() views.Slice[string] { return views.SliceOf(v.ж.Slice) }
|
||||
func (v StructWithSlicesView) Prefixes() views.IPPrefixSlice {
|
||||
return views.IPPrefixSliceOf(v.ж.Prefixes)
|
||||
func (v StructWithSlicesView) Prefixes() views.Slice[netip.Prefix] {
|
||||
return views.SliceOf(v.ж.Prefixes)
|
||||
}
|
||||
func (v StructWithSlicesView) Data() mem.RO { return mem.B(v.ж.Data) }
|
||||
|
||||
|
@ -69,8 +69,6 @@ func (v *{{.ViewName}}) UnmarshalJSON(b []byte) error {
|
||||
{{end}}
|
||||
{{define "byteSliceField"}}func (v {{.ViewName}}) {{.FieldName}}() mem.RO { return mem.B(v.ж.{{.FieldName}}) }
|
||||
{{end}}
|
||||
{{define "ipPrefixSliceField"}}func (v {{.ViewName}}) {{.FieldName}}() views.IPPrefixSlice { return views.IPPrefixSliceOf(v.ж.{{.FieldName}}) }
|
||||
{{end}}
|
||||
{{define "sliceField"}}func (v {{.ViewName}}) {{.FieldName}}() views.Slice[{{.FieldType}}] { return views.SliceOf(v.ж.{{.FieldName}}) }
|
||||
{{end}}
|
||||
{{define "viewSliceField"}}func (v {{.ViewName}}) {{.FieldName}}() views.SliceView[{{.FieldType}},{{.FieldViewName}}] { return views.SliceOfViews[{{.FieldType}},{{.FieldViewName}}](v.ж.{{.FieldName}}) }
|
||||
@ -176,9 +174,6 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi
|
||||
case "byte":
|
||||
it.Import("go4.org/mem")
|
||||
writeTemplate("byteSliceField")
|
||||
case "inet.af/netip.Prefix", "net/netip.Prefix":
|
||||
it.Import("tailscale.com/types/views")
|
||||
writeTemplate("ipPrefixSliceField")
|
||||
default:
|
||||
it.Import("tailscale.com/types/views")
|
||||
shallow, deep, base := requiresCloning(elem)
|
||||
|
@ -79,8 +79,8 @@ func (v PrefsView) Hostname() string { return v.ж.Hostname }
|
||||
func (v PrefsView) NotepadURLs() bool { return v.ж.NotepadURLs }
|
||||
func (v PrefsView) ForceDaemon() bool { return v.ж.ForceDaemon }
|
||||
func (v PrefsView) Egg() bool { return v.ж.Egg }
|
||||
func (v PrefsView) AdvertiseRoutes() views.IPPrefixSlice {
|
||||
return views.IPPrefixSliceOf(v.ж.AdvertiseRoutes)
|
||||
func (v PrefsView) AdvertiseRoutes() views.Slice[netip.Prefix] {
|
||||
return views.SliceOf(v.ж.AdvertiseRoutes)
|
||||
}
|
||||
func (v PrefsView) NoSNAT() bool { return v.ж.NoSNAT }
|
||||
func (v PrefsView) NetfilterMode() preftype.NetfilterMode { return v.ж.NetfilterMode }
|
||||
|
@ -776,13 +776,13 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) {
|
||||
func peerStatusFromNode(ps *ipnstate.PeerStatus, n *tailcfg.Node) {
|
||||
ps.ID = n.StableID
|
||||
ps.Created = n.Created
|
||||
ps.ExitNodeOption = tsaddr.ContainsExitRoutes(n.AllowedIPs)
|
||||
ps.ExitNodeOption = tsaddr.ContainsExitRoutes(views.SliceOf(n.AllowedIPs))
|
||||
if n.Tags != nil {
|
||||
v := views.SliceOf(n.Tags)
|
||||
ps.Tags = &v
|
||||
}
|
||||
if n.PrimaryRoutes != nil {
|
||||
v := views.IPPrefixSliceOf(n.PrimaryRoutes)
|
||||
v := views.SliceOf(n.PrimaryRoutes)
|
||||
ps.PrimaryRoutes = &v
|
||||
}
|
||||
|
||||
@ -2301,7 +2301,8 @@ func (b *LocalBackend) setAtomicValuesFromPrefsLocked(p ipn.PrefsView) {
|
||||
b.lastServeConfJSON = mem.B(nil)
|
||||
b.serveConfig = ipn.ServeConfigView{}
|
||||
} else {
|
||||
b.containsViaIPFuncAtomic.Store(tsaddr.NewContainsIPFunc(p.AdvertiseRoutes().Filter(tsaddr.IsViaPrefix)))
|
||||
filtered := tsaddr.FilterPrefixesCopy(p.AdvertiseRoutes(), tsaddr.IsViaPrefix)
|
||||
b.containsViaIPFuncAtomic.Store(tsaddr.NewContainsIPFunc(filtered))
|
||||
b.setTCPPortsInterceptedFromNetmapAndPrefsLocked(p)
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ type PeerStatus struct {
|
||||
// PrimaryRoutes are the routes this node is currently the primary
|
||||
// subnet router for, as determined by the control plane. It does
|
||||
// not include the IPs in TailscaleIPs.
|
||||
PrimaryRoutes *views.IPPrefixSlice `json:",omitempty"`
|
||||
PrimaryRoutes *views.Slice[netip.Prefix] `json:",omitempty"`
|
||||
|
||||
// Endpoints:
|
||||
Addrs []string
|
||||
|
@ -23,6 +23,7 @@
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/persist"
|
||||
"tailscale.com/types/preftype"
|
||||
"tailscale.com/types/views"
|
||||
"tailscale.com/util/dnsname"
|
||||
)
|
||||
|
||||
@ -506,7 +507,7 @@ func (p *Prefs) AdvertisesExitNode() bool {
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
return tsaddr.ContainsExitRoutes(p.AdvertiseRoutes)
|
||||
return tsaddr.ContainsExitRoutes(views.SliceOf(p.AdvertiseRoutes))
|
||||
}
|
||||
|
||||
// SetAdvertiseExitNode mutates p (if non-nil) to add or remove the two
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
"go4.org/netipx"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/views"
|
||||
)
|
||||
|
||||
// ChromeOSVMRange returns the subset of the CGNAT IPv4 range used by
|
||||
@ -225,9 +226,10 @@ func PrefixIs6(p netip.Prefix) bool { return p.Addr().Is6() }
|
||||
|
||||
// ContainsExitRoutes reports whether rr contains both the IPv4 and
|
||||
// IPv6 /0 route.
|
||||
func ContainsExitRoutes(rr []netip.Prefix) bool {
|
||||
func ContainsExitRoutes(rr views.Slice[netip.Prefix]) bool {
|
||||
var v4, v6 bool
|
||||
for _, r := range rr {
|
||||
for i := range rr.LenIter() {
|
||||
r := rr.At(i)
|
||||
if r == allIPv4 {
|
||||
v4 = true
|
||||
} else if r == allIPv6 {
|
||||
@ -237,6 +239,17 @@ func ContainsExitRoutes(rr []netip.Prefix) bool {
|
||||
return v4 && v6
|
||||
}
|
||||
|
||||
// ContainsNonExitSubnetRoutes reports whether v contains Subnet
|
||||
// Routes other than ExitNode Routes.
|
||||
func ContainsNonExitSubnetRoutes(rr views.Slice[netip.Prefix]) bool {
|
||||
for i := range rr.LenIter() {
|
||||
if rr.At(i).Bits() != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
allIPv4 = netip.MustParsePrefix("0.0.0.0/0")
|
||||
allIPv6 = netip.MustParsePrefix("::/0")
|
||||
@ -258,10 +271,10 @@ func SortPrefixes(p []netip.Prefix) {
|
||||
|
||||
// FilterPrefixes returns a new slice, not aliasing in, containing elements of
|
||||
// in that match f.
|
||||
func FilterPrefixesCopy(in []netip.Prefix, f func(netip.Prefix) bool) []netip.Prefix {
|
||||
func FilterPrefixesCopy(in views.Slice[netip.Prefix], f func(netip.Prefix) bool) []netip.Prefix {
|
||||
var out []netip.Prefix
|
||||
for _, v := range in {
|
||||
if f(v) {
|
||||
for i := range in.LenIter() {
|
||||
if v := in.At(i); f(v) {
|
||||
out = append(out, v)
|
||||
}
|
||||
}
|
||||
|
@ -131,27 +131,25 @@ func (v *NodeView) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v NodeView) ID() NodeID { return v.ж.ID }
|
||||
func (v NodeView) StableID() StableNodeID { return v.ж.StableID }
|
||||
func (v NodeView) Name() string { return v.ж.Name }
|
||||
func (v NodeView) User() UserID { return v.ж.User }
|
||||
func (v NodeView) Sharer() UserID { return v.ж.Sharer }
|
||||
func (v NodeView) Key() key.NodePublic { return v.ж.Key }
|
||||
func (v NodeView) KeyExpiry() time.Time { return v.ж.KeyExpiry }
|
||||
func (v NodeView) KeySignature() mem.RO { return mem.B(v.ж.KeySignature) }
|
||||
func (v NodeView) Machine() key.MachinePublic { return v.ж.Machine }
|
||||
func (v NodeView) DiscoKey() key.DiscoPublic { return v.ж.DiscoKey }
|
||||
func (v NodeView) Addresses() views.IPPrefixSlice { return views.IPPrefixSliceOf(v.ж.Addresses) }
|
||||
func (v NodeView) AllowedIPs() views.IPPrefixSlice { return views.IPPrefixSliceOf(v.ж.AllowedIPs) }
|
||||
func (v NodeView) Endpoints() views.Slice[string] { return views.SliceOf(v.ж.Endpoints) }
|
||||
func (v NodeView) DERP() string { return v.ж.DERP }
|
||||
func (v NodeView) Hostinfo() HostinfoView { return v.ж.Hostinfo }
|
||||
func (v NodeView) Created() time.Time { return v.ж.Created }
|
||||
func (v NodeView) Cap() CapabilityVersion { return v.ж.Cap }
|
||||
func (v NodeView) Tags() views.Slice[string] { return views.SliceOf(v.ж.Tags) }
|
||||
func (v NodeView) PrimaryRoutes() views.IPPrefixSlice {
|
||||
return views.IPPrefixSliceOf(v.ж.PrimaryRoutes)
|
||||
}
|
||||
func (v NodeView) ID() NodeID { return v.ж.ID }
|
||||
func (v NodeView) StableID() StableNodeID { return v.ж.StableID }
|
||||
func (v NodeView) Name() string { return v.ж.Name }
|
||||
func (v NodeView) User() UserID { return v.ж.User }
|
||||
func (v NodeView) Sharer() UserID { return v.ж.Sharer }
|
||||
func (v NodeView) Key() key.NodePublic { return v.ж.Key }
|
||||
func (v NodeView) KeyExpiry() time.Time { return v.ж.KeyExpiry }
|
||||
func (v NodeView) KeySignature() mem.RO { return mem.B(v.ж.KeySignature) }
|
||||
func (v NodeView) Machine() key.MachinePublic { return v.ж.Machine }
|
||||
func (v NodeView) DiscoKey() key.DiscoPublic { return v.ж.DiscoKey }
|
||||
func (v NodeView) Addresses() views.Slice[netip.Prefix] { return views.SliceOf(v.ж.Addresses) }
|
||||
func (v NodeView) AllowedIPs() views.Slice[netip.Prefix] { return views.SliceOf(v.ж.AllowedIPs) }
|
||||
func (v NodeView) Endpoints() views.Slice[string] { return views.SliceOf(v.ж.Endpoints) }
|
||||
func (v NodeView) DERP() string { return v.ж.DERP }
|
||||
func (v NodeView) Hostinfo() HostinfoView { return v.ж.Hostinfo }
|
||||
func (v NodeView) Created() time.Time { return v.ж.Created }
|
||||
func (v NodeView) Cap() CapabilityVersion { return v.ж.Cap }
|
||||
func (v NodeView) Tags() views.Slice[string] { return views.SliceOf(v.ж.Tags) }
|
||||
func (v NodeView) PrimaryRoutes() views.Slice[netip.Prefix] { return views.SliceOf(v.ж.PrimaryRoutes) }
|
||||
func (v NodeView) LastSeen() *time.Time {
|
||||
if v.ж.LastSeen == nil {
|
||||
return nil
|
||||
@ -266,41 +264,39 @@ func (v *HostinfoView) UnmarshalJSON(b []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v HostinfoView) IPNVersion() string { return v.ж.IPNVersion }
|
||||
func (v HostinfoView) FrontendLogID() string { return v.ж.FrontendLogID }
|
||||
func (v HostinfoView) BackendLogID() string { return v.ж.BackendLogID }
|
||||
func (v HostinfoView) OS() string { return v.ж.OS }
|
||||
func (v HostinfoView) OSVersion() string { return v.ж.OSVersion }
|
||||
func (v HostinfoView) Container() opt.Bool { return v.ж.Container }
|
||||
func (v HostinfoView) Env() string { return v.ж.Env }
|
||||
func (v HostinfoView) Distro() string { return v.ж.Distro }
|
||||
func (v HostinfoView) DistroVersion() string { return v.ж.DistroVersion }
|
||||
func (v HostinfoView) DistroCodeName() string { return v.ж.DistroCodeName }
|
||||
func (v HostinfoView) App() string { return v.ж.App }
|
||||
func (v HostinfoView) Desktop() opt.Bool { return v.ж.Desktop }
|
||||
func (v HostinfoView) Package() string { return v.ж.Package }
|
||||
func (v HostinfoView) DeviceModel() string { return v.ж.DeviceModel }
|
||||
func (v HostinfoView) PushDeviceToken() string { return v.ж.PushDeviceToken }
|
||||
func (v HostinfoView) Hostname() string { return v.ж.Hostname }
|
||||
func (v HostinfoView) ShieldsUp() bool { return v.ж.ShieldsUp }
|
||||
func (v HostinfoView) ShareeNode() bool { return v.ж.ShareeNode }
|
||||
func (v HostinfoView) NoLogsNoSupport() bool { return v.ж.NoLogsNoSupport }
|
||||
func (v HostinfoView) WireIngress() bool { return v.ж.WireIngress }
|
||||
func (v HostinfoView) AllowsUpdate() bool { return v.ж.AllowsUpdate }
|
||||
func (v HostinfoView) Machine() string { return v.ж.Machine }
|
||||
func (v HostinfoView) GoArch() string { return v.ж.GoArch }
|
||||
func (v HostinfoView) GoArchVar() string { return v.ж.GoArchVar }
|
||||
func (v HostinfoView) GoVersion() string { return v.ж.GoVersion }
|
||||
func (v HostinfoView) RoutableIPs() views.IPPrefixSlice {
|
||||
return views.IPPrefixSliceOf(v.ж.RoutableIPs)
|
||||
}
|
||||
func (v HostinfoView) RequestTags() views.Slice[string] { return views.SliceOf(v.ж.RequestTags) }
|
||||
func (v HostinfoView) Services() views.Slice[Service] { return views.SliceOf(v.ж.Services) }
|
||||
func (v HostinfoView) NetInfo() NetInfoView { return v.ж.NetInfo.View() }
|
||||
func (v HostinfoView) SSH_HostKeys() views.Slice[string] { return views.SliceOf(v.ж.SSH_HostKeys) }
|
||||
func (v HostinfoView) Cloud() string { return v.ж.Cloud }
|
||||
func (v HostinfoView) Userspace() opt.Bool { return v.ж.Userspace }
|
||||
func (v HostinfoView) UserspaceRouter() opt.Bool { return v.ж.UserspaceRouter }
|
||||
func (v HostinfoView) IPNVersion() string { return v.ж.IPNVersion }
|
||||
func (v HostinfoView) FrontendLogID() string { return v.ж.FrontendLogID }
|
||||
func (v HostinfoView) BackendLogID() string { return v.ж.BackendLogID }
|
||||
func (v HostinfoView) OS() string { return v.ж.OS }
|
||||
func (v HostinfoView) OSVersion() string { return v.ж.OSVersion }
|
||||
func (v HostinfoView) Container() opt.Bool { return v.ж.Container }
|
||||
func (v HostinfoView) Env() string { return v.ж.Env }
|
||||
func (v HostinfoView) Distro() string { return v.ж.Distro }
|
||||
func (v HostinfoView) DistroVersion() string { return v.ж.DistroVersion }
|
||||
func (v HostinfoView) DistroCodeName() string { return v.ж.DistroCodeName }
|
||||
func (v HostinfoView) App() string { return v.ж.App }
|
||||
func (v HostinfoView) Desktop() opt.Bool { return v.ж.Desktop }
|
||||
func (v HostinfoView) Package() string { return v.ж.Package }
|
||||
func (v HostinfoView) DeviceModel() string { return v.ж.DeviceModel }
|
||||
func (v HostinfoView) PushDeviceToken() string { return v.ж.PushDeviceToken }
|
||||
func (v HostinfoView) Hostname() string { return v.ж.Hostname }
|
||||
func (v HostinfoView) ShieldsUp() bool { return v.ж.ShieldsUp }
|
||||
func (v HostinfoView) ShareeNode() bool { return v.ж.ShareeNode }
|
||||
func (v HostinfoView) NoLogsNoSupport() bool { return v.ж.NoLogsNoSupport }
|
||||
func (v HostinfoView) WireIngress() bool { return v.ж.WireIngress }
|
||||
func (v HostinfoView) AllowsUpdate() bool { return v.ж.AllowsUpdate }
|
||||
func (v HostinfoView) Machine() string { return v.ж.Machine }
|
||||
func (v HostinfoView) GoArch() string { return v.ж.GoArch }
|
||||
func (v HostinfoView) GoArchVar() string { return v.ж.GoArchVar }
|
||||
func (v HostinfoView) GoVersion() string { return v.ж.GoVersion }
|
||||
func (v HostinfoView) RoutableIPs() views.Slice[netip.Prefix] { return views.SliceOf(v.ж.RoutableIPs) }
|
||||
func (v HostinfoView) RequestTags() views.Slice[string] { return views.SliceOf(v.ж.RequestTags) }
|
||||
func (v HostinfoView) Services() views.Slice[Service] { return views.SliceOf(v.ж.Services) }
|
||||
func (v HostinfoView) NetInfo() NetInfoView { return v.ж.NetInfo.View() }
|
||||
func (v HostinfoView) SSH_HostKeys() views.Slice[string] { return views.SliceOf(v.ж.SSH_HostKeys) }
|
||||
func (v HostinfoView) Cloud() string { return v.ж.Cloud }
|
||||
func (v HostinfoView) Userspace() opt.Bool { return v.ж.Userspace }
|
||||
func (v HostinfoView) UserspaceRouter() opt.Bool { return v.ж.UserspaceRouter }
|
||||
func (v HostinfoView) Location() *Location {
|
||||
if v.ж.Location == nil {
|
||||
return nil
|
||||
|
@ -9,10 +9,6 @@
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"maps"
|
||||
"net/netip"
|
||||
"slices"
|
||||
|
||||
"tailscale.com/net/tsaddr"
|
||||
)
|
||||
|
||||
func unmarshalSliceFromJSON[T any](b []byte, x *[]T) error {
|
||||
@ -229,84 +225,6 @@ func SliceEqualAnyOrder[T comparable](a, b Slice[T]) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IPPrefixSlice is a read-only accessor for a slice of netip.Prefix.
|
||||
type IPPrefixSlice struct {
|
||||
ж Slice[netip.Prefix]
|
||||
}
|
||||
|
||||
// IPPrefixSliceOf returns a IPPrefixSlice for the provided slice.
|
||||
func IPPrefixSliceOf(x []netip.Prefix) IPPrefixSlice { return IPPrefixSlice{SliceOf(x)} }
|
||||
|
||||
// IsNil reports whether the underlying slice is nil.
|
||||
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) }
|
||||
|
||||
// AppendTo appends the underlying slice values to dst.
|
||||
func (v IPPrefixSlice) AppendTo(dst []netip.Prefix) []netip.Prefix {
|
||||
return v.ж.AppendTo(dst)
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying Slice[netip.Prefix].
|
||||
func (v IPPrefixSlice) Unwrap() Slice[netip.Prefix] {
|
||||
return v.ж
|
||||
}
|
||||
|
||||
// AsSlice returns a copy of underlying slice.
|
||||
func (v IPPrefixSlice) AsSlice() []netip.Prefix {
|
||||
return v.ж.AsSlice()
|
||||
}
|
||||
|
||||
// Filter returns a new slice, containing elements of v that match f.
|
||||
func (v IPPrefixSlice) Filter(f func(netip.Prefix) bool) []netip.Prefix {
|
||||
return tsaddr.FilterPrefixesCopy(v.ж.ж, f)
|
||||
}
|
||||
|
||||
// PrefixesContainsIP reports whether any IPPrefix contains IP.
|
||||
func (v IPPrefixSlice) ContainsIP(ip netip.Addr) bool {
|
||||
return tsaddr.PrefixesContainsIP(v.ж.ж, ip)
|
||||
}
|
||||
|
||||
// PrefixesContainsFunc reports whether f is true for any IPPrefix in the slice.
|
||||
func (v IPPrefixSlice) ContainsFunc(f func(netip.Prefix) bool) bool {
|
||||
return slices.ContainsFunc(v.ж.ж, f)
|
||||
}
|
||||
|
||||
// ContainsExitRoutes reports whether v contains ExitNode Routes.
|
||||
func (v IPPrefixSlice) ContainsExitRoutes() bool {
|
||||
return tsaddr.ContainsExitRoutes(v.ж.ж)
|
||||
}
|
||||
|
||||
// ContainsNonExitSubnetRoutes reports whether v contains Subnet
|
||||
// Routes other than ExitNode Routes.
|
||||
func (v IPPrefixSlice) ContainsNonExitSubnetRoutes() bool {
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
if v.At(i).Bits() != 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler.
|
||||
func (v IPPrefixSlice) MarshalJSON() ([]byte, error) {
|
||||
return v.ж.MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (v *IPPrefixSlice) UnmarshalJSON(b []byte) error {
|
||||
return v.ж.UnmarshalJSON(b)
|
||||
}
|
||||
|
||||
// MapOf returns a view over m. It is the caller's responsibility to make sure K
|
||||
// and V is immutable, if this is being used to provide a read-only view over m.
|
||||
func MapOf[K comparable, V comparable](m map[K]V) Map[K, V] {
|
||||
|
@ -16,10 +16,10 @@
|
||||
|
||||
type viewStruct struct {
|
||||
Int int
|
||||
Addrs IPPrefixSlice
|
||||
Addrs Slice[netip.Prefix]
|
||||
Strings Slice[string]
|
||||
AddrsPtr *IPPrefixSlice `json:",omitempty"`
|
||||
StringsPtr *Slice[string] `json:",omitempty"`
|
||||
AddrsPtr *Slice[netip.Prefix] `json:",omitempty"`
|
||||
StringsPtr *Slice[string] `json:",omitempty"`
|
||||
}
|
||||
|
||||
func BenchmarkSliceIteration(b *testing.B) {
|
||||
@ -66,7 +66,7 @@ func TestViewsJSON(t *testing.T) {
|
||||
}
|
||||
return
|
||||
}
|
||||
ipp := IPPrefixSliceOf(mustCIDR("192.168.0.0/24"))
|
||||
ipp := SliceOf(mustCIDR("192.168.0.0/24"))
|
||||
ss := SliceOf([]string{"bar"})
|
||||
tests := []struct {
|
||||
name string
|
||||
|
Loading…
Reference in New Issue
Block a user