mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-07 08:07:42 +00:00
all: implement AppendText alongside MarshalText (#9207)
This eventually allows encoding packages that may respect the proposed encoding.TextAppender interface. The performance gains from this is between 10-30%. Updates tailscale/corp#14379 Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
parent
9a3bc9049c
commit
c6fadd6d71
@ -37,6 +37,10 @@
|
|||||||
StateSynchronized // connected and received map update
|
StateSynchronized // connected and received map update
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (s State) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return append(b, s.String()...), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s State) MarshalText() ([]byte, error) {
|
func (s State) MarshalText() ([]byte, error) {
|
||||||
return []byte(s.String()), nil
|
return []byte(s.String()), nil
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -445,6 +444,10 @@ func (n *Node) InitDisplayNames(networkMagicDNSSuffix string) {
|
|||||||
MachineInvalid // server has explicitly rejected this machine key
|
MachineInvalid // server has explicitly rejected this machine key
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (m MachineStatus) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return append(b, m.String()...), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m MachineStatus) MarshalText() ([]byte, error) {
|
func (m MachineStatus) MarshalText() ([]byte, error) {
|
||||||
return []byte(m.String()), nil
|
return []byte(m.String()), nil
|
||||||
}
|
}
|
||||||
@ -921,6 +924,10 @@ func appendStructPtrDiff(base []string, pfx string, p1, p2 reflect.Value) (ret [
|
|||||||
SignatureV2
|
SignatureV2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (st SignatureType) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return append(b, st.String()...), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (st SignatureType) MarshalText() ([]byte, error) {
|
func (st SignatureType) MarshalText() ([]byte, error) {
|
||||||
return []byte(st.String()), nil
|
return []byte(st.String()), nil
|
||||||
}
|
}
|
||||||
@ -1765,18 +1772,6 @@ type Debug struct {
|
|||||||
Exit *int `json:",omitempty"`
|
Exit *int `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func appendKey(base []byte, prefix string, k [32]byte) []byte {
|
|
||||||
ret := append(base, make([]byte, len(prefix)+64)...)
|
|
||||||
buf := ret[len(base):]
|
|
||||||
copy(buf, prefix)
|
|
||||||
hex.Encode(buf[len(prefix):], k[:])
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func keyMarshalText(prefix string, k [32]byte) []byte {
|
|
||||||
return appendKey(nil, prefix, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (id ID) String() string { return fmt.Sprintf("id:%x", int64(id)) }
|
func (id ID) String() string { return fmt.Sprintf("id:%x", int64(id)) }
|
||||||
func (id UserID) String() string { return fmt.Sprintf("userid:%x", int64(id)) }
|
func (id UserID) String() string { return fmt.Sprintf("userid:%x", int64(id)) }
|
||||||
func (id LoginID) String() string { return fmt.Sprintf("loginid:%x", int64(id)) }
|
func (id LoginID) String() string { return fmt.Sprintf("loginid:%x", int64(id)) }
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
package tailcfg
|
|
||||||
|
|
||||||
var ExportKeyMarshalText = keyMarshalText
|
|
@ -16,11 +16,9 @@
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
. "tailscale.com/tailcfg"
|
. "tailscale.com/tailcfg"
|
||||||
"tailscale.com/tstest"
|
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/ptr"
|
"tailscale.com/types/ptr"
|
||||||
"tailscale.com/util/must"
|
"tailscale.com/util/must"
|
||||||
"tailscale.com/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func fieldsOf(t reflect.Type) (fields []string) {
|
func fieldsOf(t reflect.Type) (fields []string) {
|
||||||
@ -683,29 +681,6 @@ func TestEndpointTypeMarshal(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var sinkBytes []byte
|
|
||||||
|
|
||||||
func BenchmarkKeyMarshalText(b *testing.B) {
|
|
||||||
b.ReportAllocs()
|
|
||||||
var k [32]byte
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
sinkBytes = ExportKeyMarshalText("prefix", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppendKeyAllocs(t *testing.T) {
|
|
||||||
if version.IsRace() {
|
|
||||||
t.Skip("skipping in race detector") // append(b, make([]byte, N)...) not optimized in compiler with race
|
|
||||||
}
|
|
||||||
var k [32]byte
|
|
||||||
err := tstest.MinAllocsPerRun(t, 1, func() {
|
|
||||||
sinkBytes = ExportKeyMarshalText("prefix", k)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegisterRequestNilClone(t *testing.T) {
|
func TestRegisterRequestNilClone(t *testing.T) {
|
||||||
var nilReq *RegisterRequest
|
var nilReq *RegisterRequest
|
||||||
got := nilReq.Clone()
|
got := nilReq.Clone()
|
||||||
|
18
tka/aum.go
18
tka/aum.go
@ -9,6 +9,7 @@
|
|||||||
"encoding/base32"
|
"encoding/base32"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/fxamacker/cbor/v2"
|
"github.com/fxamacker/cbor/v2"
|
||||||
"golang.org/x/crypto/blake2s"
|
"golang.org/x/crypto/blake2s"
|
||||||
@ -37,11 +38,22 @@ func (h *AUMHash) UnmarshalText(text []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(https://go.dev/issue/53693): Use base32.Encoding.AppendEncode instead.
|
||||||
|
func base32AppendEncode(enc *base32.Encoding, dst, src []byte) []byte {
|
||||||
|
n := enc.EncodedLen(len(src))
|
||||||
|
dst = slices.Grow(dst, n)
|
||||||
|
enc.Encode(dst[len(dst):][:n], src)
|
||||||
|
return dst[:len(dst)+n]
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (h AUMHash) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return base32AppendEncode(base32StdNoPad, b, h[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (h AUMHash) MarshalText() ([]byte, error) {
|
func (h AUMHash) MarshalText() ([]byte, error) {
|
||||||
b := make([]byte, base32StdNoPad.EncodedLen(len(h)))
|
return h.AppendText(nil)
|
||||||
base32StdNoPad.Encode(b, h[:])
|
|
||||||
return b, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsZero returns true if the hash is the empty value.
|
// IsZero returns true if the hash is the empty value.
|
||||||
|
@ -72,9 +72,14 @@ func (k ChallengePublic) String() string {
|
|||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k ChallengePublic) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, chalPublicHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k ChallengePublic) MarshalText() ([]byte, error) {
|
func (k ChallengePublic) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], chalPublicHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
@ -127,9 +127,14 @@ func (k DiscoPublic) String() string {
|
|||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k DiscoPublic) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, discoPublicHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k DiscoPublic) MarshalText() ([]byte, error) {
|
func (k DiscoPublic) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], discoPublicHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextUnmarshaler.
|
// MarshalText implements encoding.TextUnmarshaler.
|
||||||
|
@ -67,9 +67,14 @@ func (k MachinePrivate) Public() MachinePublic {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k MachinePrivate) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, machinePrivateHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k MachinePrivate) MarshalText() ([]byte, error) {
|
func (k MachinePrivate) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], machinePrivateHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextUnmarshaler.
|
// MarshalText implements encoding.TextUnmarshaler.
|
||||||
@ -243,9 +248,14 @@ func (k MachinePublic) String() string {
|
|||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k MachinePublic) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, machinePublicHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k MachinePublic) MarshalText() ([]byte, error) {
|
func (k MachinePublic) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], machinePublicHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextUnmarshaler.
|
// MarshalText implements encoding.TextUnmarshaler.
|
||||||
|
@ -61,9 +61,14 @@ func (k *NLPrivate) UnmarshalText(b []byte) error {
|
|||||||
return parseHex(k.k[:], mem.B(b), mem.S(nlPrivateHexPrefix))
|
return parseHex(k.k[:], mem.B(b), mem.S(nlPrivateHexPrefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k NLPrivate) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, nlPrivateHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k NLPrivate) MarshalText() ([]byte, error) {
|
func (k NLPrivate) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], nlPrivateHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal reports whether k and other are the same key.
|
// Equal reports whether k and other are the same key.
|
||||||
@ -132,10 +137,15 @@ func (k *NLPublic) UnmarshalText(b []byte) error {
|
|||||||
return parseHex(k.k[:], mem.B(b), mem.S(nlPublicHexPrefix))
|
return parseHex(k.k[:], mem.B(b), mem.S(nlPublicHexPrefix))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k NLPublic) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, nlPublicHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler, emitting a
|
// MarshalText implements encoding.TextMarshaler, emitting a
|
||||||
// representation of the form nlpub:<hex>.
|
// representation of the form nlpub:<hex>.
|
||||||
func (k NLPublic) MarshalText() ([]byte, error) {
|
func (k NLPublic) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], nlPublicHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLIString returns a marshalled representation suitable for use
|
// CLIString returns a marshalled representation suitable for use
|
||||||
@ -143,7 +153,7 @@ func (k NLPublic) MarshalText() ([]byte, error) {
|
|||||||
// the nlpub:<hex> form emitted by MarshalText. Both forms can
|
// the nlpub:<hex> form emitted by MarshalText. Both forms can
|
||||||
// be decoded by UnmarshalText.
|
// be decoded by UnmarshalText.
|
||||||
func (k NLPublic) CLIString() string {
|
func (k NLPublic) CLIString() string {
|
||||||
return string(toHex(k.k[:], nlPublicHexPrefixCLI))
|
return string(appendHexKey(nil, nlPublicHexPrefixCLI, k.k[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifier returns a ed25519.PublicKey that can be used to
|
// Verifier returns a ed25519.PublicKey that can be used to
|
||||||
|
@ -103,9 +103,14 @@ func (k NodePrivate) Public() NodePublic {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k NodePrivate) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, nodePrivateHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k NodePrivate) MarshalText() ([]byte, error) {
|
func (k NodePrivate) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], nodePrivateHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextUnmarshaler.
|
// MarshalText implements encoding.TextUnmarshaler.
|
||||||
@ -308,9 +313,14 @@ func (k NodePublic) String() string {
|
|||||||
return string(bs)
|
return string(bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendText implements encoding.TextAppender.
|
||||||
|
func (k NodePublic) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return appendHexKey(b, nodePublicHexPrefix, k.k[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextMarshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (k NodePublic) MarshalText() ([]byte, error) {
|
func (k NodePublic) MarshalText() ([]byte, error) {
|
||||||
return toHex(k.k[:], nodePublicHexPrefix), nil
|
return k.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText implements encoding.TextUnmarshaler.
|
// MarshalText implements encoding.TextUnmarshaler.
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"go4.org/mem"
|
"go4.org/mem"
|
||||||
)
|
)
|
||||||
@ -49,11 +50,19 @@ func clamp25519Private(b []byte) {
|
|||||||
b[31] = (b[31] & 127) | 64
|
b[31] = (b[31] & 127) | 64
|
||||||
}
|
}
|
||||||
|
|
||||||
func toHex(k []byte, prefix string) []byte {
|
func appendHexKey(dst []byte, prefix string, key []byte) []byte {
|
||||||
ret := make([]byte, len(prefix)+len(k)*2)
|
dst = slices.Grow(dst, len(prefix)+hex.EncodedLen(len(key)))
|
||||||
copy(ret, prefix)
|
dst = append(dst, prefix...)
|
||||||
hex.Encode(ret[len(prefix):], k)
|
dst = hexAppendEncode(dst, key)
|
||||||
return ret
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(https://go.dev/issue/53693): Use hex.AppendEncode instead.
|
||||||
|
func hexAppendEncode(dst, src []byte) []byte {
|
||||||
|
n := hex.EncodedLen(len(src))
|
||||||
|
dst = slices.Grow(dst, n)
|
||||||
|
hex.Encode(dst[len(dst):][:n], src)
|
||||||
|
return dst[:len(dst)+n]
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseHex decodes a key string of the form "<prefix><hex string>"
|
// parseHex decodes a key string of the form "<prefix><hex string>"
|
||||||
|
@ -38,8 +38,12 @@ func ParsePrivateID(in string) (out PrivateID, err error) {
|
|||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (id PrivateID) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return hexAppendEncode(b, id[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (id PrivateID) MarshalText() ([]byte, error) {
|
func (id PrivateID) MarshalText() ([]byte, error) {
|
||||||
return formatID(id), nil
|
return id.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id *PrivateID) UnmarshalText(in []byte) error {
|
func (id *PrivateID) UnmarshalText(in []byte) error {
|
||||||
@ -47,7 +51,7 @@ func (id *PrivateID) UnmarshalText(in []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (id PrivateID) String() string {
|
func (id PrivateID) String() string {
|
||||||
return string(formatID(id))
|
return string(hexAppendEncode(nil, id[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id PrivateID) IsZero() bool {
|
func (id PrivateID) IsZero() bool {
|
||||||
@ -70,8 +74,12 @@ func ParsePublicID(in string) (out PublicID, err error) {
|
|||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (id PublicID) AppendText(b []byte) ([]byte, error) {
|
||||||
|
return hexAppendEncode(b, id[:]), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (id PublicID) MarshalText() ([]byte, error) {
|
func (id PublicID) MarshalText() ([]byte, error) {
|
||||||
return formatID(id), nil
|
return id.AppendText(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id *PublicID) UnmarshalText(in []byte) error {
|
func (id *PublicID) UnmarshalText(in []byte) error {
|
||||||
@ -79,7 +87,7 @@ func (id *PublicID) UnmarshalText(in []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (id PublicID) String() string {
|
func (id PublicID) String() string {
|
||||||
return string(formatID(id))
|
return string(hexAppendEncode(nil, id[:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id1 PublicID) Less(id2 PublicID) bool {
|
func (id1 PublicID) Less(id2 PublicID) bool {
|
||||||
@ -98,10 +106,12 @@ func (id PublicID) Prefix64() uint64 {
|
|||||||
return binary.BigEndian.Uint64(id[:8])
|
return binary.BigEndian.Uint64(id[:8])
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatID(in [32]byte) []byte {
|
// TODO(https://go.dev/issue/53693): Use hex.AppendEncode instead.
|
||||||
var hexArr [2 * len(in)]byte
|
func hexAppendEncode(dst, src []byte) []byte {
|
||||||
hex.Encode(hexArr[:], in[:])
|
n := hex.EncodedLen(len(src))
|
||||||
return hexArr[:]
|
dst = slices.Grow(dst, n)
|
||||||
|
hex.Encode(dst[len(dst):][:n], src)
|
||||||
|
return dst[:len(dst)+n]
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseID[Bytes []byte | string](funcName string, out *[32]byte, in Bytes) (err error) {
|
func parseID[Bytes []byte | string](funcName string, out *[32]byte, in Bytes) (err error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user