diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 83fab9c97..30672bc6f 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -5,7 +5,7 @@ // the node and the coordination server. package tailcfg -//go:generate go run tailscale.com/cmd/viewer --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile --clonefunc +//go:generate go run tailscale.com/cmd/viewer --type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile,VIPService --clonefunc import ( "bytes" diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index da1f4f374..3952f5f47 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -626,9 +626,28 @@ var _UserProfileCloneNeedsRegeneration = UserProfile(struct { ProfilePicURL string }{}) +// Clone makes a deep copy of VIPService. +// The result aliases no memory with the original. +func (src *VIPService) Clone() *VIPService { + if src == nil { + return nil + } + dst := new(VIPService) + *dst = *src + dst.Ports = append(src.Ports[:0:0], src.Ports...) + return dst +} + +// A compilation failure here means this code must be regenerated, with the command at the top of this file. +var _VIPServiceCloneNeedsRegeneration = VIPService(struct { + Name ServiceName + Ports []ProtoPortRange + Active bool +}{}) + // Clone duplicates src into dst and reports whether it succeeded. // To succeed, must be of types <*T, *T> or <*T, **T>, -// where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile. +// where T is one of User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile,VIPService. func Clone(dst, src any) bool { switch src := src.(type) { case *User: @@ -802,6 +821,15 @@ func Clone(dst, src any) bool { *dst = src.Clone() return true } + case *VIPService: + switch dst := dst.(type) { + case *VIPService: + *dst = *src.Clone() + return true + case **VIPService: + *dst = src.Clone() + return true + } } return false } diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index b1aacab23..f8f9f865c 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -19,7 +19,7 @@ import ( "tailscale.com/types/views" ) -//go:generate go run tailscale.com/cmd/cloner -clonefunc=true -type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile +//go:generate go run tailscale.com/cmd/cloner -clonefunc=true -type=User,Node,Hostinfo,NetInfo,Login,DNSConfig,RegisterResponse,RegisterResponseAuth,RegisterRequest,DERPHomeParams,DERPRegion,DERPMap,DERPNode,SSHRule,SSHAction,SSHPrincipal,ControlDialPlan,Location,UserProfile,VIPService // View returns a read-only view of User. func (p *User) View() UserView { @@ -1414,3 +1414,59 @@ var _UserProfileViewNeedsRegeneration = UserProfile(struct { DisplayName string ProfilePicURL string }{}) + +// View returns a read-only view of VIPService. +func (p *VIPService) View() VIPServiceView { + return VIPServiceView{ж: p} +} + +// VIPServiceView provides a read-only view over VIPService. +// +// Its methods should only be called if `Valid()` returns true. +type VIPServiceView struct { + // ж is the underlying mutable value, named with a hard-to-type + // character that looks pointy like a pointer. + // 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. + ж *VIPService +} + +// Valid reports whether v's underlying value is non-nil. +func (v VIPServiceView) Valid() bool { return v.ж != nil } + +// AsStruct returns a clone of the underlying value which aliases no memory with +// the original. +func (v VIPServiceView) AsStruct() *VIPService { + if v.ж == nil { + return nil + } + return v.ж.Clone() +} + +func (v VIPServiceView) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) } + +func (v *VIPServiceView) UnmarshalJSON(b []byte) error { + if v.ж != nil { + return errors.New("already initialized") + } + if len(b) == 0 { + return nil + } + var x VIPService + if err := json.Unmarshal(b, &x); err != nil { + return err + } + v.ж = &x + return nil +} + +func (v VIPServiceView) Name() ServiceName { return v.ж.Name } +func (v VIPServiceView) Ports() views.Slice[ProtoPortRange] { return views.SliceOf(v.ж.Ports) } +func (v VIPServiceView) Active() bool { return v.ж.Active } + +// A compilation failure here means this code must be regenerated, with the command at the top of this file. +var _VIPServiceViewNeedsRegeneration = VIPService(struct { + Name ServiceName + Ports []ProtoPortRange + Active bool +}{})