internal/impl: inline small tag decoding in the validator

name                            old time/op    new time/op    delta
EmptyMessage/Wire/Validate-12     4.59ns ± 0%    4.51ns ± 1%   -1.74%  (p=0.001 n=8+8)
RepeatedInt32/Wire/Validate-12    1.28µs ± 0%    0.91µs ± 0%  -28.71%  (p=0.000 n=7+8)
Required/Wire/Validate-12         48.3ns ± 2%    34.5ns ± 0%  -28.69%  (p=0.001 n=7+7)

Change-Id: If7c431ee23d930d44af0fc26b7bd2149d3aded64
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/216624
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/internal/impl/validate.go b/internal/impl/validate.go
index 093f078..40c6a7a 100644
--- a/internal/impl/validate.go
+++ b/internal/impl/validate.go
@@ -251,14 +251,30 @@
 		}
 	Field:
 		for len(b) > 0 {
-			num, wtyp, n := wire.ConsumeTag(b)
-			if n < 0 {
-				return ValidationInvalid
+			// Parse the tag (field number and wire type).
+			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 ValidationInvalid
+				}
+				b = b[n:]
 			}
-			b = b[n:]
-			if num > wire.MaxValidNumber {
+			var num wire.Number
+			if n := tag >> 3; n < uint64(wire.MinValidNumber) || n > uint64(wire.MaxValidNumber) {
 				return ValidationInvalid
+			} else {
+				num = wire.Number(n)
 			}
+			wtyp := wire.Type(tag & 7)
+
 			if wtyp == wire.EndGroupType {
 				if st.endGroup == num {
 					goto PopState
@@ -431,7 +447,7 @@
 				b = b[n:]
 				continue Field
 			}
-			n = wire.ConsumeFieldValue(num, wtyp, b)
+			n := wire.ConsumeFieldValue(num, wtyp, b)
 			if n < 0 {
 				return ValidationInvalid
 			}