summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2023-08-31 13:02:58 -0700
committerJoe Tsai <joetsai@digital-static.net>2023-09-06 13:03:51 -0700
commit8841fd58c95cd335c5cf531ad08e978ca9c87c76 (patch)
tree621414b273badfcf682c85dc55b0b169bf5ada0f
parentac7b4d62fdc6ff589d894cc2fbac3e47c9c674c6 (diff)
downloadtailscale-dsnet/viewer-jsonv2.tar.xz
tailscale-dsnet/viewer-jsonv2.zip
cmd/viewer: support v2 JSON methodsdsnet/viewer-jsonv2
This links in github.com/go-json-experiment/json into tailscaled. After this change, the tailscaled binary on GOOS=linux and GOARCH=amd64 increases by ~85KiB. The v2 marshal/unmarshal methods avoids a O(n^2) behavior with deeply nested v1 MarshalJSON and UnmarshalJSON calls, since each call requires the encoding/json package to rescan the entire JSON value. Our data structures are not so deep that the O(n^2) behavior becomes notable, but this does provide about a ~20% performance benefit. Updates tailscale/corp#14379 Signed-off-by: Joe Tsai <joetsai@digital-static.net>
-rw-r--r--cmd/derper/depaware.txt10
-rw-r--r--cmd/netlogfmt/main.go9
-rw-r--r--cmd/tailscale/depaware.txt8
-rw-r--r--cmd/tailscaled/depaware.txt8
-rw-r--r--cmd/viewer/viewer.go36
-rw-r--r--go.mod2
-rw-r--r--go.sum4
-rw-r--r--tailcfg/tailcfg.go2
-rw-r--r--tailcfg/tailcfg_view.go420
-rw-r--r--util/codegen/codegen.go22
10 files changed, 502 insertions, 19 deletions
diff --git a/cmd/derper/depaware.txt b/cmd/derper/depaware.txt
index 238e0cf76..a618bf068 100644
--- a/cmd/derper/depaware.txt
+++ b/cmd/derper/depaware.txt
@@ -15,6 +15,12 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
L github.com/coreos/go-iptables/iptables from tailscale.com/util/linuxfw
W 💣 github.com/dblohm7/wingoes from tailscale.com/util/winutil
github.com/fxamacker/cbor/v2 from tailscale.com/tka
+ github.com/go-json-experiment/json from tailscale.com/tailcfg
+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonwire from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/jsontext from github.com/go-json-experiment/json+
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
github.com/golang/protobuf/proto from github.com/matttproud/golang_protobuf_extensions/pbutil+
L github.com/google/nftables from tailscale.com/util/linuxfw
@@ -191,7 +197,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
golang.org/x/time/rate from tailscale.com/cmd/derper+
bufio from compress/flate+
bytes from bufio+
- cmp from slices
+ cmp from slices+
compress/flate from compress/gzip+
compress/gzip from internal/profile+
container/list from crypto/tls+
@@ -220,7 +226,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
embed from crypto/internal/nistec+
encoding from encoding/json+
encoding/asn1 from crypto/x509+
- encoding/base32 from tailscale.com/tka
+ encoding/base32 from tailscale.com/tka+
encoding/base64 from encoding/json+
encoding/binary from compress/gzip+
encoding/hex from crypto/x509+
diff --git a/cmd/netlogfmt/main.go b/cmd/netlogfmt/main.go
index 98c958305..e1a5c2cb2 100644
--- a/cmd/netlogfmt/main.go
+++ b/cmd/netlogfmt/main.go
@@ -42,6 +42,7 @@ import (
"github.com/dsnet/try"
jsonv2 "github.com/go-json-experiment/json"
+ "github.com/go-json-experiment/json/jsontext"
"tailscale.com/types/logid"
"tailscale.com/types/netlogtype"
"tailscale.com/util/cmpx"
@@ -75,13 +76,13 @@ func main() {
func processStream(r io.Reader) (err error) {
defer try.Handle(&err)
- dec := jsonv2.NewDecoder(os.Stdin)
+ dec := jsontext.NewDecoder(os.Stdin)
for {
processValue(dec)
}
}
-func processValue(dec *jsonv2.Decoder) {
+func processValue(dec *jsontext.Decoder) {
switch dec.PeekKind() {
case '[':
processArray(dec)
@@ -92,7 +93,7 @@ func processValue(dec *jsonv2.Decoder) {
}
}
-func processArray(dec *jsonv2.Decoder) {
+func processArray(dec *jsontext.Decoder) {
try.E1(dec.ReadToken()) // parse '['
for dec.PeekKind() != ']' {
processValue(dec)
@@ -100,7 +101,7 @@ func processArray(dec *jsonv2.Decoder) {
try.E1(dec.ReadToken()) // parse ']'
}
-func processObject(dec *jsonv2.Decoder) {
+func processObject(dec *jsontext.Decoder) {
var hasTraffic bool
var rawMsg []byte
try.E1(dec.ReadToken()) // parse '{'
diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt
index 16e3121ce..4c12ceecd 100644
--- a/cmd/tailscale/depaware.txt
+++ b/cmd/tailscale/depaware.txt
@@ -15,6 +15,12 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
W 💣 github.com/dblohm7/wingoes from tailscale.com/util/winutil/authenticode+
W 💣 github.com/dblohm7/wingoes/pe from tailscale.com/util/winutil/authenticode
github.com/fxamacker/cbor/v2 from tailscale.com/tka
+ github.com/go-json-experiment/json from tailscale.com/tailcfg
+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonwire from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/jsontext from github.com/go-json-experiment/json+
L 💣 github.com/godbus/dbus/v5 from github.com/coreos/go-systemd/v22/dbus
github.com/golang/groupcache/lru from tailscale.com/net/dnscache
L github.com/google/nftables from tailscale.com/util/linuxfw
@@ -205,7 +211,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
archive/tar from tailscale.com/clientupdate
bufio from compress/flate+
bytes from bufio+
- cmp from slices
+ cmp from slices+
compress/flate from compress/gzip+
compress/gzip from net/http+
compress/zlib from image/png+
diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt
index 4e49741a5..0eab53aaa 100644
--- a/cmd/tailscaled/depaware.txt
+++ b/cmd/tailscaled/depaware.txt
@@ -84,6 +84,12 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
W github.com/dblohm7/wingoes/internal from github.com/dblohm7/wingoes/com
W 💣 github.com/dblohm7/wingoes/pe from tailscale.com/util/osdiag+
github.com/fxamacker/cbor/v2 from tailscale.com/tka
+ github.com/go-json-experiment/json from tailscale.com/tailcfg
+ github.com/go-json-experiment/json/internal from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonflags from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonopts from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/internal/jsonwire from github.com/go-json-experiment/json+
+ github.com/go-json-experiment/json/jsontext from github.com/go-json-experiment/json+
W 💣 github.com/go-ole/go-ole from github.com/go-ole/go-ole/oleutil+
W 💣 github.com/go-ole/go-ole/oleutil from tailscale.com/wgengine/winnet
L 💣 github.com/godbus/dbus/v5 from tailscale.com/net/dns+
@@ -418,7 +424,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
archive/tar from tailscale.com/clientupdate
bufio from compress/flate+
bytes from bufio+
- cmp from slices
+ cmp from slices+
compress/flate from compress/gzip+
compress/gzip from golang.org/x/net/http2+
W compress/zlib from debug/pe
diff --git a/cmd/viewer/viewer.go b/cmd/viewer/viewer.go
index b9c01a9b8..5ce55dabb 100644
--- a/cmd/viewer/viewer.go
+++ b/cmd/viewer/viewer.go
@@ -64,6 +64,30 @@ func (v *{{.ViewName}}) UnmarshalJSON(b []byte) error {
return nil
}
+{{if .SupportJSONV2}}
+// Verify that {{.ViewName}} implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*{{.ViewName}})(nil)
+ _ (jsonv2.UnmarshalerV2) = (*{{.ViewName}})(nil)
+)
+
+func (v {{.ViewName}}) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *{{.ViewName}}) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x {{.StructName}}
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+{{end}}
+
{{end}}
{{define "valueField"}}func (v {{.ViewName}}) {{.FieldName}}() {{.FieldType}} { return v.ж.{{.FieldName}} }
{{end}}
@@ -126,6 +150,10 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi
}
it.Import("encoding/json")
it.Import("errors")
+ if *jsonv2Methods {
+ it.ImportNamed("github.com/go-json-experiment/json", "jsonv2")
+ it.Import("github.com/go-json-experiment/json/jsontext")
+ }
args := struct {
StructName string
@@ -138,9 +166,12 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi
MapValueType string
MapValueView string
MapFn string
+
+ SupportJSONV2 bool
}{
- StructName: typ.Obj().Name(),
- ViewName: typ.Obj().Name() + "View",
+ StructName: typ.Obj().Name(),
+ ViewName: typ.Obj().Name() + "View",
+ SupportJSONV2: *jsonv2Methods,
}
writeTemplate := func(name string) {
@@ -321,6 +352,7 @@ var (
flagTypes = flag.String("type", "", "comma-separated list of types; required")
flagBuildTags = flag.String("tags", "", "compiler build tags to apply")
flagCloneFunc = flag.Bool("clonefunc", false, "add a top-level Clone func")
+ jsonv2Methods = flag.Bool("jsonv2method", false, "add marshal/unmarshal methods for JSONv2")
flagCloneOnlyTypes = flag.String("clone-only-type", "", "comma-separated list of types (a subset of --type) that should only generate a go:generate clone line and not actual views")
)
diff --git a/go.mod b/go.mod
index 86e202ec8..31024f61d 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
github.com/evanw/esbuild v0.14.53
github.com/frankban/quicktest v1.14.5
github.com/fxamacker/cbor/v2 v2.4.0
- github.com/go-json-experiment/json v0.0.0-20230321051131-ccbac49a6929
+ github.com/go-json-experiment/json v0.0.0-20230831193458-5df0a50228ea
github.com/go-logr/zapr v1.2.4
github.com/go-ole/go-ole v1.2.6
github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466
diff --git a/go.sum b/go.sum
index 3d6a4720b..8d42fec30 100644
--- a/go.sum
+++ b/go.sum
@@ -299,8 +299,8 @@ github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhc
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-json-experiment/json v0.0.0-20230321051131-ccbac49a6929 h1:GdbUZo0+623j+pKRhwwdf1q28IUgRc7asx3TjF9b7VQ=
-github.com/go-json-experiment/json v0.0.0-20230321051131-ccbac49a6929/go.mod h1:AHV+bpNGVGD0DCHMBhhTYtT7yeBYD9Yk92XAjB7vOgo=
+github.com/go-json-experiment/json v0.0.0-20230831193458-5df0a50228ea h1:EFOg7Pq/YiznRzn/7udE/cuT1swauYdQ5ljDK93jBNc=
+github.com/go-json-experiment/json v0.0.0-20230831193458-5df0a50228ea/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go
index 501a6bf62..4ea43c650 100644
--- a/tailcfg/tailcfg.go
+++ b/tailcfg/tailcfg.go
@@ -3,7 +3,7 @@
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 --clonefunc --jsonv2method
import (
"bytes"
diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go
index 0b9250412..de82e13db 100644
--- a/tailcfg/tailcfg_view.go
+++ b/tailcfg/tailcfg_view.go
@@ -11,6 +11,8 @@ import (
"net/netip"
"time"
+ jsonv2 "github.com/go-json-experiment/json"
+ "github.com/go-json-experiment/json/jsontext"
"tailscale.com/types/dnstype"
"tailscale.com/types/key"
"tailscale.com/types/opt"
@@ -66,6 +68,28 @@ func (v *UserView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that UserView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*UserView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*UserView)(nil)
+)
+
+func (v UserView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *UserView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x User
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v UserView) ID() UserID { return v.ж.ID }
func (v UserView) LoginName() string { return v.ж.LoginName }
func (v UserView) DisplayName() string { return v.ж.DisplayName }
@@ -128,6 +152,28 @@ func (v *NodeView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that NodeView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*NodeView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*NodeView)(nil)
+)
+
+func (v NodeView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *NodeView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x Node
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ 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 }
@@ -263,6 +309,28 @@ func (v *HostinfoView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that HostinfoView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*HostinfoView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*HostinfoView)(nil)
+)
+
+func (v HostinfoView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *HostinfoView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x Hostinfo
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ 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 }
@@ -389,6 +457,28 @@ func (v *NetInfoView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that NetInfoView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*NetInfoView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*NetInfoView)(nil)
+)
+
+func (v NetInfoView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *NetInfoView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x NetInfo
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v NetInfoView) MappingVariesByDestIP() opt.Bool { return v.ж.MappingVariesByDestIP }
func (v NetInfoView) HairPinning() opt.Bool { return v.ж.HairPinning }
func (v NetInfoView) WorkingIPv6() opt.Bool { return v.ж.WorkingIPv6 }
@@ -469,6 +559,28 @@ func (v *LoginView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that LoginView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*LoginView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*LoginView)(nil)
+)
+
+func (v LoginView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *LoginView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x Login
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v LoginView) ID() LoginID { return v.ж.ID }
func (v LoginView) Provider() string { return v.ж.Provider }
func (v LoginView) LoginName() string { return v.ж.LoginName }
@@ -530,6 +642,28 @@ func (v *DNSConfigView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that DNSConfigView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*DNSConfigView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*DNSConfigView)(nil)
+)
+
+func (v DNSConfigView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *DNSConfigView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x DNSConfig
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v DNSConfigView) Resolvers() views.SliceView[*dnstype.Resolver, dnstype.ResolverView] {
return views.SliceOfViews[*dnstype.Resolver, dnstype.ResolverView](v.ж.Resolvers)
}
@@ -611,6 +745,28 @@ func (v *RegisterResponseView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that RegisterResponseView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*RegisterResponseView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*RegisterResponseView)(nil)
+)
+
+func (v RegisterResponseView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *RegisterResponseView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x RegisterResponse
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v RegisterResponseView) User() UserView { return v.ж.User.View() }
func (v RegisterResponseView) Login() Login { return v.ж.Login }
func (v RegisterResponseView) NodeKeyExpired() bool { return v.ж.NodeKeyExpired }
@@ -677,6 +833,28 @@ func (v *RegisterResponseAuthView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that RegisterResponseAuthView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*RegisterResponseAuthView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*RegisterResponseAuthView)(nil)
+)
+
+func (v RegisterResponseAuthView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *RegisterResponseAuthView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x RegisterResponseAuth
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v RegisterResponseAuthView) Provider() string { return v.ж.Provider }
func (v RegisterResponseAuthView) LoginName() string { return v.ж.LoginName }
func (v RegisterResponseAuthView) Oauth2Token() *Oauth2Token {
@@ -743,6 +921,28 @@ func (v *RegisterRequestView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that RegisterRequestView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*RegisterRequestView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*RegisterRequestView)(nil)
+)
+
+func (v RegisterRequestView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *RegisterRequestView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x RegisterRequest
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v RegisterRequestView) Version() CapabilityVersion { return v.ж.Version }
func (v RegisterRequestView) NodeKey() key.NodePublic { return v.ж.NodeKey }
func (v RegisterRequestView) OldNodeKey() key.NodePublic { return v.ж.OldNodeKey }
@@ -835,6 +1035,28 @@ func (v *DERPHomeParamsView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that DERPHomeParamsView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*DERPHomeParamsView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*DERPHomeParamsView)(nil)
+)
+
+func (v DERPHomeParamsView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *DERPHomeParamsView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x DERPHomeParams
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v DERPHomeParamsView) RegionScore() views.Map[int, float64] {
return views.MapOf(v.ж.RegionScore)
}
@@ -889,6 +1111,28 @@ func (v *DERPRegionView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that DERPRegionView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*DERPRegionView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*DERPRegionView)(nil)
+)
+
+func (v DERPRegionView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *DERPRegionView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x DERPRegion
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v DERPRegionView) RegionID() int { return v.ж.RegionID }
func (v DERPRegionView) RegionCode() string { return v.ж.RegionCode }
func (v DERPRegionView) RegionName() string { return v.ж.RegionName }
@@ -951,6 +1195,28 @@ func (v *DERPMapView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that DERPMapView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*DERPMapView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*DERPMapView)(nil)
+)
+
+func (v DERPMapView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *DERPMapView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x DERPMap
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v DERPMapView) HomeParams() DERPHomeParamsView { return v.ж.HomeParams.View() }
func (v DERPMapView) Regions() views.MapFn[int, *DERPRegion, DERPRegionView] {
@@ -1012,6 +1278,28 @@ func (v *DERPNodeView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that DERPNodeView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*DERPNodeView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*DERPNodeView)(nil)
+)
+
+func (v DERPNodeView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *DERPNodeView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x DERPNode
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v DERPNodeView) Name() string { return v.ж.Name }
func (v DERPNodeView) RegionID() int { return v.ж.RegionID }
func (v DERPNodeView) HostName() string { return v.ж.HostName }
@@ -1086,6 +1374,28 @@ func (v *SSHRuleView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that SSHRuleView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*SSHRuleView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*SSHRuleView)(nil)
+)
+
+func (v SSHRuleView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *SSHRuleView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x SSHRule
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v SSHRuleView) RuleExpires() *time.Time {
if v.ж.RuleExpires == nil {
return nil
@@ -1154,6 +1464,28 @@ func (v *SSHActionView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that SSHActionView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*SSHActionView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*SSHActionView)(nil)
+)
+
+func (v SSHActionView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *SSHActionView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x SSHAction
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v SSHActionView) Message() string { return v.ж.Message }
func (v SSHActionView) Reject() bool { return v.ж.Reject }
func (v SSHActionView) Accept() bool { return v.ж.Accept }
@@ -1230,6 +1562,28 @@ func (v *SSHPrincipalView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that SSHPrincipalView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*SSHPrincipalView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*SSHPrincipalView)(nil)
+)
+
+func (v SSHPrincipalView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *SSHPrincipalView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x SSHPrincipal
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v SSHPrincipalView) Node() StableNodeID { return v.ж.Node }
func (v SSHPrincipalView) NodeIP() string { return v.ж.NodeIP }
func (v SSHPrincipalView) UserLogin() string { return v.ж.UserLogin }
@@ -1290,6 +1644,28 @@ func (v *ControlDialPlanView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that ControlDialPlanView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*ControlDialPlanView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*ControlDialPlanView)(nil)
+)
+
+func (v ControlDialPlanView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *ControlDialPlanView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x ControlDialPlan
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v ControlDialPlanView) Candidates() views.Slice[ControlIPCandidate] {
return views.SliceOf(v.ж.Candidates)
}
@@ -1344,6 +1720,28 @@ func (v *LocationView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that LocationView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*LocationView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*LocationView)(nil)
+)
+
+func (v LocationView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *LocationView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x Location
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v LocationView) Country() string { return v.ж.Country }
func (v LocationView) CountryCode() string { return v.ж.CountryCode }
func (v LocationView) City() string { return v.ж.City }
@@ -1404,6 +1802,28 @@ func (v *UserProfileView) UnmarshalJSON(b []byte) error {
return nil
}
+// Verify that UserProfileView implements jsonv2 interfaces.
+var (
+ _ (jsonv2.MarshalerV2) = (*UserProfileView)(nil)
+ _ (jsonv2.UnmarshalerV2) = (*UserProfileView)(nil)
+)
+
+func (v UserProfileView) MarshalJSONV2(enc *jsontext.Encoder, opts jsonv2.Options) error {
+ return jsonv2.MarshalEncode(enc, v.ж, opts)
+}
+
+func (v *UserProfileView) UnmarshalJSONV2(dec *jsontext.Decoder, opts jsonv2.Options) error {
+ if v.ж != nil {
+ return errors.New("already initialized")
+ }
+ var x UserProfile
+ if err := jsonv2.UnmarshalDecode(dec, &x, opts); err != nil {
+ return err
+ }
+ v.ж = &x
+ return nil
+}
+
func (v UserProfileView) ID() UserID { return v.ж.ID }
func (v UserProfileView) LoginName() string { return v.ж.LoginName }
func (v UserProfileView) DisplayName() string { return v.ж.DisplayName }
diff --git a/util/codegen/codegen.go b/util/codegen/codegen.go
index cf848b1d2..e560bfb00 100644
--- a/util/codegen/codegen.go
+++ b/util/codegen/codegen.go
@@ -74,12 +74,20 @@ func NewImportTracker(thisPkg *types.Package) *ImportTracker {
// ImportTracker provides a mechanism to track and build import paths.
type ImportTracker struct {
thisPkg *types.Package
- packages map[string]bool
+ packages map[string]string // package paths to package names; empty name to use default
}
func (it *ImportTracker) Import(pkg string) {
- if pkg != "" && !it.packages[pkg] {
- mak.Set(&it.packages, pkg, true)
+ _, ok := it.packages[pkg]
+ if pkg != "" && !ok {
+ mak.Set(&it.packages, pkg, "")
+ }
+}
+
+func (it *ImportTracker) ImportNamed(pkg, name string) {
+ _, ok := it.packages[pkg]
+ if pkg != "" && !ok {
+ mak.Set(&it.packages, pkg, name)
}
}
@@ -100,8 +108,12 @@ func (it *ImportTracker) QualifiedName(t types.Type) string {
// Write prints all the tracked imports in a single import block to w.
func (it *ImportTracker) Write(w io.Writer) {
fmt.Fprintf(w, "import (\n")
- for s := range it.packages {
- fmt.Fprintf(w, "\t%q\n", s)
+ for pkgPath, pkgName := range it.packages {
+ if pkgName == "" {
+ fmt.Fprintf(w, "\t%q\n", pkgPath)
+ } else {
+ fmt.Fprintf(w, "\t%s %q\n", pkgName, pkgPath)
+ }
}
fmt.Fprintf(w, ")\n\n")
}