diff --git a/internal/encoding/wire/wire.go b/internal/encoding/wire/wire.go index 32622b11..d7baa7f1 100644 --- a/internal/encoding/wire/wire.go +++ b/internal/encoding/wire/wire.go @@ -176,7 +176,6 @@ func SizeTag(num Number) int { // AppendVarint appends v to b as a varint-encoded uint64. func AppendVarint(b []byte, v uint64) []byte { - // TODO: Specialize for sizes 1 and 2 with mid-stack inlining. switch { case v < 1<<7: b = append(b, byte(v)) @@ -259,7 +258,6 @@ func AppendVarint(b []byte, v uint64) []byte { // ConsumeVarint parses b as a varint-encoded uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeVarint(b []byte) (v uint64, n int) { - // TODO: Specialize for sizes 1 and 2 with mid-stack inlining. var y uint64 if len(b) <= 0 { return 0, errCodeTruncated diff --git a/internal/impl/decode.go b/internal/impl/decode.go index fc93525a..4a1d6312 100644 --- a/internal/impl/decode.go +++ b/internal/impl/decode.go @@ -97,15 +97,27 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Numbe start := len(b) for len(b) > 0 { // Parse the tag (field number and wire type). - // TODO: inline 1 and 2 byte variants? - num, wtyp, n := wire.ConsumeTag(b) - if n < 0 { - return out, wire.ParseError(n) + var tag uint64 + if b[0] < 0x80 { + tag = uint64(b[0]) + b = b[1:] + } else if len(b) >= 2 && b[1] < 128 { + tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 + b = b[2:] + } else { + var n int + tag, n = wire.ConsumeVarint(b) + if n < 0 { + return out, wire.ParseError(n) + } + b = b[n:] } - if num > wire.MaxValidNumber { + num := wire.Number(tag >> 3) + wtyp := wire.Type(tag & 7) + + if num < wire.MinValidNumber || num > wire.MaxValidNumber { return out, errors.New("invalid field number") } - b = b[n:] if wtyp == wire.EndGroupType { if num != groupTag { @@ -121,6 +133,7 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Numbe } else { f = mi.coderFields[num] } + var n int err := errUnknown switch { case f != nil: