mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 13:05:46 +00:00
types/views: add generic Slice[T] and remove StringSlice
Also make IPPrefixSliceOf use Slice[netaddr.IPPrefix] as it also provides additional functions besides the standard ones provided by Slice[T]. Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
parent
d8953bf2ba
commit
6b9d938c1a
@ -444,10 +444,10 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) {
|
|||||||
exitNodeOption := tsaddr.PrefixesContainsFunc(p.AllowedIPs, func(r netaddr.IPPrefix) bool {
|
exitNodeOption := tsaddr.PrefixesContainsFunc(p.AllowedIPs, func(r netaddr.IPPrefix) bool {
|
||||||
return r.Bits() == 0
|
return r.Bits() == 0
|
||||||
})
|
})
|
||||||
var tags *views.StringSlice
|
var tags *views.Slice[string]
|
||||||
var primaryRoutes *views.IPPrefixSlice
|
var primaryRoutes *views.IPPrefixSlice
|
||||||
if p.Tags != nil {
|
if p.Tags != nil {
|
||||||
v := views.StringSliceOf(p.Tags)
|
v := views.SliceOf(p.Tags)
|
||||||
tags = &v
|
tags = &v
|
||||||
}
|
}
|
||||||
if p.PrimaryRoutes != nil {
|
if p.PrimaryRoutes != nil {
|
||||||
|
@ -112,7 +112,7 @@ type PeerStatus struct {
|
|||||||
|
|
||||||
// Tags are the list of ACL tags applied to this node.
|
// Tags are the list of ACL tags applied to this node.
|
||||||
// See tailscale.com/tailcfg#Node.Tags for more information.
|
// See tailscale.com/tailcfg#Node.Tags for more information.
|
||||||
Tags *views.StringSlice `json:",omitempty"`
|
Tags *views.Slice[string] `json:",omitempty"`
|
||||||
|
|
||||||
// PrimaryRoutes are the routes this node is currently the primary
|
// PrimaryRoutes are the routes this node is currently the primary
|
||||||
// subnet router for, as determined by the control plane. It does
|
// subnet router for, as determined by the control plane. It does
|
||||||
|
@ -527,12 +527,12 @@ func (v HostinfoView) RoutableIPs() views.IPPrefixSlice {
|
|||||||
return views.IPPrefixSliceOf(v.ж.RoutableIPs)
|
return views.IPPrefixSliceOf(v.ж.RoutableIPs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v HostinfoView) RequestTags() views.StringSlice {
|
func (v HostinfoView) RequestTags() views.Slice[string] {
|
||||||
return views.StringSliceOf(v.ж.RequestTags)
|
return views.SliceOf(v.ж.RequestTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v HostinfoView) SSH_HostKeys() views.StringSlice {
|
func (v HostinfoView) SSH_HostKeys() views.Slice[string] {
|
||||||
return views.StringSliceOf(v.ж.SSH_HostKeys)
|
return views.SliceOf(v.ж.SSH_HostKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v HostinfoView) Services() ServiceSlice {
|
func (v HostinfoView) Services() ServiceSlice {
|
||||||
|
@ -14,25 +14,25 @@
|
|||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StringSlice is a read-only accessor for a slice of strings.
|
// Slice is a read-only accessor for a slice.
|
||||||
type StringSlice struct {
|
type Slice[T any] struct {
|
||||||
// It is named distinctively to make you think of how dangerous it is to escape
|
// It is named distinctively to make you think of how dangerous it is to escape
|
||||||
// to callers. You must not let callers be able to mutate it.
|
// to callers. You must not let callers be able to mutate it.
|
||||||
ж []string
|
ж []T
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringSliceOf returns a StringSlice for the provided slice.
|
// SliceOf returns a Slice for the provided slice.
|
||||||
func StringSliceOf(x []string) StringSlice { return StringSlice{x} }
|
func SliceOf[T any](x []T) Slice[T] { return Slice[T]{x} }
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalJSON implements json.Marshaler.
|
||||||
func (v StringSlice) MarshalJSON() ([]byte, error) {
|
func (v Slice[T]) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(v.ж)
|
return json.Marshal(v.ж)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
func (v *StringSlice) UnmarshalJSON(b []byte) error {
|
func (v *Slice[T]) UnmarshalJSON(b []byte) error {
|
||||||
if v.ж != nil {
|
if v.ж != nil {
|
||||||
return errors.New("StringSlice is already initialized")
|
return errors.New("Slice is already initialized")
|
||||||
}
|
}
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -44,83 +44,77 @@ func (v *StringSlice) UnmarshalJSON(b []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsNil reports whether the underlying slice is nil.
|
// IsNil reports whether the underlying slice is nil.
|
||||||
func (v StringSlice) IsNil() bool { return v.ж == nil }
|
func (v Slice[T]) IsNil() bool { return v.ж == nil }
|
||||||
|
|
||||||
// Len returns the length of the slice.
|
// Len returns the length of the slice.
|
||||||
func (v StringSlice) Len() int { return len(v.ж) }
|
func (v Slice[T]) Len() int { return len(v.ж) }
|
||||||
|
|
||||||
// At returns the string at index `i` of the slice.
|
// At returns the element at index `i` of the slice.
|
||||||
func (v StringSlice) At(i int) string { return v.ж[i] }
|
func (v Slice[T]) At(i int) T { return v.ж[i] }
|
||||||
|
|
||||||
// AppendTo appends the underlying slice values to dst.
|
// AppendTo appends the underlying slice values to dst.
|
||||||
func (v StringSlice) AppendTo(dst []string) []string {
|
func (v Slice[T]) AppendTo(dst []T) []T {
|
||||||
return append(dst, v.ж...)
|
return append(dst, v.ж...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsSlice returns a copy of underlying slice.
|
// AsSlice returns a copy of underlying slice.
|
||||||
func (v StringSlice) AsSlice() []string {
|
func (v Slice[T]) AsSlice() []T {
|
||||||
return v.AppendTo(v.ж[:0:0])
|
return v.AppendTo(v.ж[:0:0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPPrefixSlice is a read-only accessor for a slice of netaddr.IPPrefix.
|
// IPPrefixSlice is a read-only accessor for a slice of netaddr.IPPrefix.
|
||||||
type IPPrefixSlice struct {
|
type IPPrefixSlice struct {
|
||||||
// It is named distinctively to make you think of how dangerous it is to escape
|
ж Slice[netaddr.IPPrefix]
|
||||||
// to callers. You must not let callers be able to mutate it.jd
|
|
||||||
ж []netaddr.IPPrefix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPPrefixSliceOf returns a IPPrefixSlice for the provided slice.
|
// IPPrefixSliceOf returns a IPPrefixSlice for the provided slice.
|
||||||
func IPPrefixSliceOf(x []netaddr.IPPrefix) IPPrefixSlice { return IPPrefixSlice{x} }
|
func IPPrefixSliceOf(x []netaddr.IPPrefix) IPPrefixSlice { return IPPrefixSlice{SliceOf(x)} }
|
||||||
|
|
||||||
// IsNil reports whether the underlying slice is nil.
|
// IsNil reports whether the underlying slice is nil.
|
||||||
func (v IPPrefixSlice) IsNil() bool { return v.ж == nil }
|
func (v IPPrefixSlice) IsNil() bool { return v.ж.IsNil() }
|
||||||
|
|
||||||
// Len returns the length of the slice.
|
// Len returns the length of the slice.
|
||||||
func (v IPPrefixSlice) Len() int { return len(v.ж) }
|
func (v IPPrefixSlice) Len() int { return v.ж.Len() }
|
||||||
|
|
||||||
// At returns the IPPrefix at index `i` of the slice.
|
// At returns the IPPrefix at index `i` of the slice.
|
||||||
func (v IPPrefixSlice) At(i int) netaddr.IPPrefix { return v.ж[i] }
|
func (v IPPrefixSlice) At(i int) netaddr.IPPrefix { return v.ж.At(i) }
|
||||||
|
|
||||||
// Append appends the underlying slice values to dst.
|
// AppendTo appends the underlying slice values to dst.
|
||||||
func (v IPPrefixSlice) AppendTo(dst []netaddr.IPPrefix) []netaddr.IPPrefix {
|
func (v IPPrefixSlice) AppendTo(dst []netaddr.IPPrefix) []netaddr.IPPrefix {
|
||||||
return append(dst, v.ж...)
|
return v.ж.AppendTo(dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic returns the underlying Slice[netaddr.IPPrefix].
|
||||||
|
func (v IPPrefixSlice) Generic() Slice[netaddr.IPPrefix] {
|
||||||
|
return v.ж
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsSlice returns a copy of underlying slice.
|
// AsSlice returns a copy of underlying slice.
|
||||||
func (v IPPrefixSlice) AsSlice() []netaddr.IPPrefix {
|
func (v IPPrefixSlice) AsSlice() []netaddr.IPPrefix {
|
||||||
return v.AppendTo(v.ж[:0:0])
|
return v.ж.AsSlice()
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrefixesContainsIP reports whether any IPPrefix contains IP.
|
// PrefixesContainsIP reports whether any IPPrefix contains IP.
|
||||||
func (v IPPrefixSlice) ContainsIP(ip netaddr.IP) bool {
|
func (v IPPrefixSlice) ContainsIP(ip netaddr.IP) bool {
|
||||||
return tsaddr.PrefixesContainsIP(v.ж, ip)
|
return tsaddr.PrefixesContainsIP(v.ж.ж, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrefixesContainsFunc reports whether f is true for any IPPrefix in the slice.
|
// PrefixesContainsFunc reports whether f is true for any IPPrefix in the slice.
|
||||||
func (v IPPrefixSlice) ContainsFunc(f func(netaddr.IPPrefix) bool) bool {
|
func (v IPPrefixSlice) ContainsFunc(f func(netaddr.IPPrefix) bool) bool {
|
||||||
return tsaddr.PrefixesContainsFunc(v.ж, f)
|
return tsaddr.PrefixesContainsFunc(v.ж.ж, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainsExitRoutes reports whether v contains ExitNode Routes.
|
// ContainsExitRoutes reports whether v contains ExitNode Routes.
|
||||||
func (v IPPrefixSlice) ContainsExitRoutes() bool {
|
func (v IPPrefixSlice) ContainsExitRoutes() bool {
|
||||||
return tsaddr.ContainsExitRoutes(v.ж)
|
return tsaddr.ContainsExitRoutes(v.ж.ж)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalJSON implements json.Marshaler.
|
||||||
func (v IPPrefixSlice) MarshalJSON() ([]byte, error) {
|
func (v IPPrefixSlice) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(v.ж)
|
return v.ж.MarshalJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
func (v *IPPrefixSlice) UnmarshalJSON(b []byte) error {
|
func (v *IPPrefixSlice) UnmarshalJSON(b []byte) error {
|
||||||
if v.ж != nil {
|
return v.ж.UnmarshalJSON(b)
|
||||||
return errors.New("IPPrefixSlice is already initialized")
|
|
||||||
}
|
|
||||||
if len(b) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(b, &v.ж); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,12 @@ func TestViewsJSON(t *testing.T) {
|
|||||||
}
|
}
|
||||||
type viewStruct struct {
|
type viewStruct struct {
|
||||||
Addrs IPPrefixSlice
|
Addrs IPPrefixSlice
|
||||||
Strings StringSlice
|
Strings Slice[string]
|
||||||
AddrsPtr *IPPrefixSlice `json:",omitempty"`
|
AddrsPtr *IPPrefixSlice `json:",omitempty"`
|
||||||
StringsPtr *StringSlice `json:",omitempty"`
|
StringsPtr *Slice[string] `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
ipp := IPPrefixSliceOf(mustCIDR("192.168.0.0/24"))
|
||||||
|
ss := SliceOf([]string{"bar"})
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
in viewStruct
|
in viewStruct
|
||||||
@ -40,12 +42,12 @@ type viewStruct struct {
|
|||||||
{
|
{
|
||||||
name: "everything",
|
name: "everything",
|
||||||
in: viewStruct{
|
in: viewStruct{
|
||||||
Addrs: IPPrefixSliceOf(mustCIDR("192.168.0.0/24")),
|
Addrs: ipp,
|
||||||
AddrsPtr: &IPPrefixSlice{mustCIDR("192.168.0.0/24")},
|
AddrsPtr: &ipp,
|
||||||
StringsPtr: &StringSlice{[]string{"foo"}},
|
StringsPtr: &ss,
|
||||||
Strings: StringSlice{[]string{"bar"}},
|
Strings: ss,
|
||||||
},
|
},
|
||||||
wantJSON: `{"Addrs":["192.168.0.0/24"],"Strings":["bar"],"AddrsPtr":["192.168.0.0/24"],"StringsPtr":["foo"]}`,
|
wantJSON: `{"Addrs":["192.168.0.0/24"],"Strings":["bar"],"AddrsPtr":["192.168.0.0/24"],"StringsPtr":["bar"]}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user