mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 19:15:34 +00:00
types/wgkey: use value receiver with MarshalJSON
Pointer receivers used with MarshalJSON are code rakes. https://github.com/golang/go/issues/22967 https://github.com/dominikh/go-tools/issues/911 I just stepped on one, and it hurt. Turn it over. While we're here, optimize the code a bit. name old time/op new time/op delta MarshalJSON-8 184ns ± 0% 44ns ± 0% -76.03% (p=0.000 n=20+19) name old alloc/op new alloc/op delta MarshalJSON-8 184B ± 0% 80B ± 0% -56.52% (p=0.000 n=20+20) name old allocs/op new allocs/op delta MarshalJSON-8 4.00 ± 0% 1.00 ± 0% -75.00% (p=0.000 n=20+20) Signed-off-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
7ee891f5fd
commit
4037fc25c5
@ -90,14 +90,12 @@ func (k *Key) IsZero() bool {
|
|||||||
return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
|
return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Key) MarshalJSON() ([]byte, error) {
|
func (k Key) MarshalJSON() ([]byte, error) {
|
||||||
if k == nil {
|
buf := make([]byte, 2+len(k)*2)
|
||||||
return []byte("null"), nil
|
buf[0] = '"'
|
||||||
}
|
hex.Encode(buf[1:], k[:])
|
||||||
// TODO(josharian): use encoding/hex instead?
|
buf[len(buf)-1] = '"'
|
||||||
buf := new(bytes.Buffer)
|
return buf, nil
|
||||||
fmt.Fprintf(buf, `"%x"`, k[:])
|
|
||||||
return buf.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Key) UnmarshalJSON(b []byte) error {
|
func (k *Key) UnmarshalJSON(b []byte) error {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ func TestKeyBasics(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("JSON round-trip", func(t *testing.T) {
|
t.Run("JSON round-trip (pointer)", func(t *testing.T) {
|
||||||
// should preserve the keys
|
// should preserve the keys
|
||||||
k2 := new(Key)
|
k2 := new(Key)
|
||||||
if err := k2.UnmarshalJSON(b); err != nil {
|
if err := k2.UnmarshalJSON(b); err != nil {
|
||||||
@ -55,6 +56,27 @@ func TestKeyBasics(t *testing.T) {
|
|||||||
t.Fatalf("base64-encoded keys match: %s, %s", b1, b2)
|
t.Fatalf("base64-encoded keys match: %s, %s", b1, b2)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("JSON round-trip (value)", func(t *testing.T) {
|
||||||
|
type T struct {
|
||||||
|
K Key
|
||||||
|
}
|
||||||
|
v := T{K: *k1}
|
||||||
|
b, err := json.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var u T
|
||||||
|
if err := json.Unmarshal(b, &u); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(v.K[:], u.K[:]) {
|
||||||
|
t.Fatalf("v.K %v != u.K %v", v.K[:], u.K[:])
|
||||||
|
}
|
||||||
|
if b1, b2 := v.K.String(), u.K.String(); b1 != b2 {
|
||||||
|
t.Fatalf("base64-encoded keys do not match: %s, %s", b1, b2)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
func TestPrivateKeyBasics(t *testing.T) {
|
func TestPrivateKeyBasics(t *testing.T) {
|
||||||
pri, err := NewPrivate()
|
pri, err := NewPrivate()
|
||||||
@ -109,3 +131,28 @@ func TestPrivateKeyBasics(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshalJSONAllocs(t *testing.T) {
|
||||||
|
var k Key
|
||||||
|
f := testing.AllocsPerRun(100, func() {
|
||||||
|
k.MarshalJSON()
|
||||||
|
})
|
||||||
|
n := int(f)
|
||||||
|
if n != 1 {
|
||||||
|
t.Fatalf("max one alloc per Key.MarshalJSON, got %d", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sink []byte
|
||||||
|
|
||||||
|
func BenchmarkMarshalJSON(b *testing.B) {
|
||||||
|
b.ReportAllocs()
|
||||||
|
var k Key
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
var err error
|
||||||
|
sink, err = k.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user