1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved. 2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style 3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file. 4*1c12ee1eSDan Willemsen 5*1c12ee1eSDan Willemsen// Package protowire parses and formats the raw wire encoding. 6*1c12ee1eSDan Willemsen// See https://protobuf.dev/programming-guides/encoding. 7*1c12ee1eSDan Willemsen// 8*1c12ee1eSDan Willemsen// For marshaling and unmarshaling entire protobuf messages, 9*1c12ee1eSDan Willemsen// use the "google.golang.org/protobuf/proto" package instead. 10*1c12ee1eSDan Willemsenpackage protowire 11*1c12ee1eSDan Willemsen 12*1c12ee1eSDan Willemsenimport ( 13*1c12ee1eSDan Willemsen "io" 14*1c12ee1eSDan Willemsen "math" 15*1c12ee1eSDan Willemsen "math/bits" 16*1c12ee1eSDan Willemsen 17*1c12ee1eSDan Willemsen "google.golang.org/protobuf/internal/errors" 18*1c12ee1eSDan Willemsen) 19*1c12ee1eSDan Willemsen 20*1c12ee1eSDan Willemsen// Number represents the field number. 21*1c12ee1eSDan Willemsentype Number int32 22*1c12ee1eSDan Willemsen 23*1c12ee1eSDan Willemsenconst ( 24*1c12ee1eSDan Willemsen MinValidNumber Number = 1 25*1c12ee1eSDan Willemsen FirstReservedNumber Number = 19000 26*1c12ee1eSDan Willemsen LastReservedNumber Number = 19999 27*1c12ee1eSDan Willemsen MaxValidNumber Number = 1<<29 - 1 28*1c12ee1eSDan Willemsen DefaultRecursionLimit = 10000 29*1c12ee1eSDan Willemsen) 30*1c12ee1eSDan Willemsen 31*1c12ee1eSDan Willemsen// IsValid reports whether the field number is semantically valid. 32*1c12ee1eSDan Willemsenfunc (n Number) IsValid() bool { 33*1c12ee1eSDan Willemsen return MinValidNumber <= n && n <= MaxValidNumber 34*1c12ee1eSDan Willemsen} 35*1c12ee1eSDan Willemsen 36*1c12ee1eSDan Willemsen// Type represents the wire type. 37*1c12ee1eSDan Willemsentype Type int8 38*1c12ee1eSDan Willemsen 39*1c12ee1eSDan Willemsenconst ( 40*1c12ee1eSDan Willemsen VarintType Type = 0 41*1c12ee1eSDan Willemsen Fixed32Type Type = 5 42*1c12ee1eSDan Willemsen Fixed64Type Type = 1 43*1c12ee1eSDan Willemsen BytesType Type = 2 44*1c12ee1eSDan Willemsen StartGroupType Type = 3 45*1c12ee1eSDan Willemsen EndGroupType Type = 4 46*1c12ee1eSDan Willemsen) 47*1c12ee1eSDan Willemsen 48*1c12ee1eSDan Willemsenconst ( 49*1c12ee1eSDan Willemsen _ = -iota 50*1c12ee1eSDan Willemsen errCodeTruncated 51*1c12ee1eSDan Willemsen errCodeFieldNumber 52*1c12ee1eSDan Willemsen errCodeOverflow 53*1c12ee1eSDan Willemsen errCodeReserved 54*1c12ee1eSDan Willemsen errCodeEndGroup 55*1c12ee1eSDan Willemsen errCodeRecursionDepth 56*1c12ee1eSDan Willemsen) 57*1c12ee1eSDan Willemsen 58*1c12ee1eSDan Willemsenvar ( 59*1c12ee1eSDan Willemsen errFieldNumber = errors.New("invalid field number") 60*1c12ee1eSDan Willemsen errOverflow = errors.New("variable length integer overflow") 61*1c12ee1eSDan Willemsen errReserved = errors.New("cannot parse reserved wire type") 62*1c12ee1eSDan Willemsen errEndGroup = errors.New("mismatching end group marker") 63*1c12ee1eSDan Willemsen errParse = errors.New("parse error") 64*1c12ee1eSDan Willemsen) 65*1c12ee1eSDan Willemsen 66*1c12ee1eSDan Willemsen// ParseError converts an error code into an error value. 67*1c12ee1eSDan Willemsen// This returns nil if n is a non-negative number. 68*1c12ee1eSDan Willemsenfunc ParseError(n int) error { 69*1c12ee1eSDan Willemsen if n >= 0 { 70*1c12ee1eSDan Willemsen return nil 71*1c12ee1eSDan Willemsen } 72*1c12ee1eSDan Willemsen switch n { 73*1c12ee1eSDan Willemsen case errCodeTruncated: 74*1c12ee1eSDan Willemsen return io.ErrUnexpectedEOF 75*1c12ee1eSDan Willemsen case errCodeFieldNumber: 76*1c12ee1eSDan Willemsen return errFieldNumber 77*1c12ee1eSDan Willemsen case errCodeOverflow: 78*1c12ee1eSDan Willemsen return errOverflow 79*1c12ee1eSDan Willemsen case errCodeReserved: 80*1c12ee1eSDan Willemsen return errReserved 81*1c12ee1eSDan Willemsen case errCodeEndGroup: 82*1c12ee1eSDan Willemsen return errEndGroup 83*1c12ee1eSDan Willemsen default: 84*1c12ee1eSDan Willemsen return errParse 85*1c12ee1eSDan Willemsen } 86*1c12ee1eSDan Willemsen} 87*1c12ee1eSDan Willemsen 88*1c12ee1eSDan Willemsen// ConsumeField parses an entire field record (both tag and value) and returns 89*1c12ee1eSDan Willemsen// the field number, the wire type, and the total length. 90*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 91*1c12ee1eSDan Willemsen// 92*1c12ee1eSDan Willemsen// The total length includes the tag header and the end group marker (if the 93*1c12ee1eSDan Willemsen// field is a group). 94*1c12ee1eSDan Willemsenfunc ConsumeField(b []byte) (Number, Type, int) { 95*1c12ee1eSDan Willemsen num, typ, n := ConsumeTag(b) 96*1c12ee1eSDan Willemsen if n < 0 { 97*1c12ee1eSDan Willemsen return 0, 0, n // forward error code 98*1c12ee1eSDan Willemsen } 99*1c12ee1eSDan Willemsen m := ConsumeFieldValue(num, typ, b[n:]) 100*1c12ee1eSDan Willemsen if m < 0 { 101*1c12ee1eSDan Willemsen return 0, 0, m // forward error code 102*1c12ee1eSDan Willemsen } 103*1c12ee1eSDan Willemsen return num, typ, n + m 104*1c12ee1eSDan Willemsen} 105*1c12ee1eSDan Willemsen 106*1c12ee1eSDan Willemsen// ConsumeFieldValue parses a field value and returns its length. 107*1c12ee1eSDan Willemsen// This assumes that the field Number and wire Type have already been parsed. 108*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 109*1c12ee1eSDan Willemsen// 110*1c12ee1eSDan Willemsen// When parsing a group, the length includes the end group marker and 111*1c12ee1eSDan Willemsen// the end group is verified to match the starting field number. 112*1c12ee1eSDan Willemsenfunc ConsumeFieldValue(num Number, typ Type, b []byte) (n int) { 113*1c12ee1eSDan Willemsen return consumeFieldValueD(num, typ, b, DefaultRecursionLimit) 114*1c12ee1eSDan Willemsen} 115*1c12ee1eSDan Willemsen 116*1c12ee1eSDan Willemsenfunc consumeFieldValueD(num Number, typ Type, b []byte, depth int) (n int) { 117*1c12ee1eSDan Willemsen switch typ { 118*1c12ee1eSDan Willemsen case VarintType: 119*1c12ee1eSDan Willemsen _, n = ConsumeVarint(b) 120*1c12ee1eSDan Willemsen return n 121*1c12ee1eSDan Willemsen case Fixed32Type: 122*1c12ee1eSDan Willemsen _, n = ConsumeFixed32(b) 123*1c12ee1eSDan Willemsen return n 124*1c12ee1eSDan Willemsen case Fixed64Type: 125*1c12ee1eSDan Willemsen _, n = ConsumeFixed64(b) 126*1c12ee1eSDan Willemsen return n 127*1c12ee1eSDan Willemsen case BytesType: 128*1c12ee1eSDan Willemsen _, n = ConsumeBytes(b) 129*1c12ee1eSDan Willemsen return n 130*1c12ee1eSDan Willemsen case StartGroupType: 131*1c12ee1eSDan Willemsen if depth < 0 { 132*1c12ee1eSDan Willemsen return errCodeRecursionDepth 133*1c12ee1eSDan Willemsen } 134*1c12ee1eSDan Willemsen n0 := len(b) 135*1c12ee1eSDan Willemsen for { 136*1c12ee1eSDan Willemsen num2, typ2, n := ConsumeTag(b) 137*1c12ee1eSDan Willemsen if n < 0 { 138*1c12ee1eSDan Willemsen return n // forward error code 139*1c12ee1eSDan Willemsen } 140*1c12ee1eSDan Willemsen b = b[n:] 141*1c12ee1eSDan Willemsen if typ2 == EndGroupType { 142*1c12ee1eSDan Willemsen if num != num2 { 143*1c12ee1eSDan Willemsen return errCodeEndGroup 144*1c12ee1eSDan Willemsen } 145*1c12ee1eSDan Willemsen return n0 - len(b) 146*1c12ee1eSDan Willemsen } 147*1c12ee1eSDan Willemsen 148*1c12ee1eSDan Willemsen n = consumeFieldValueD(num2, typ2, b, depth-1) 149*1c12ee1eSDan Willemsen if n < 0 { 150*1c12ee1eSDan Willemsen return n // forward error code 151*1c12ee1eSDan Willemsen } 152*1c12ee1eSDan Willemsen b = b[n:] 153*1c12ee1eSDan Willemsen } 154*1c12ee1eSDan Willemsen case EndGroupType: 155*1c12ee1eSDan Willemsen return errCodeEndGroup 156*1c12ee1eSDan Willemsen default: 157*1c12ee1eSDan Willemsen return errCodeReserved 158*1c12ee1eSDan Willemsen } 159*1c12ee1eSDan Willemsen} 160*1c12ee1eSDan Willemsen 161*1c12ee1eSDan Willemsen// AppendTag encodes num and typ as a varint-encoded tag and appends it to b. 162*1c12ee1eSDan Willemsenfunc AppendTag(b []byte, num Number, typ Type) []byte { 163*1c12ee1eSDan Willemsen return AppendVarint(b, EncodeTag(num, typ)) 164*1c12ee1eSDan Willemsen} 165*1c12ee1eSDan Willemsen 166*1c12ee1eSDan Willemsen// ConsumeTag parses b as a varint-encoded tag, reporting its length. 167*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 168*1c12ee1eSDan Willemsenfunc ConsumeTag(b []byte) (Number, Type, int) { 169*1c12ee1eSDan Willemsen v, n := ConsumeVarint(b) 170*1c12ee1eSDan Willemsen if n < 0 { 171*1c12ee1eSDan Willemsen return 0, 0, n // forward error code 172*1c12ee1eSDan Willemsen } 173*1c12ee1eSDan Willemsen num, typ := DecodeTag(v) 174*1c12ee1eSDan Willemsen if num < MinValidNumber { 175*1c12ee1eSDan Willemsen return 0, 0, errCodeFieldNumber 176*1c12ee1eSDan Willemsen } 177*1c12ee1eSDan Willemsen return num, typ, n 178*1c12ee1eSDan Willemsen} 179*1c12ee1eSDan Willemsen 180*1c12ee1eSDan Willemsenfunc SizeTag(num Number) int { 181*1c12ee1eSDan Willemsen return SizeVarint(EncodeTag(num, 0)) // wire type has no effect on size 182*1c12ee1eSDan Willemsen} 183*1c12ee1eSDan Willemsen 184*1c12ee1eSDan Willemsen// AppendVarint appends v to b as a varint-encoded uint64. 185*1c12ee1eSDan Willemsenfunc AppendVarint(b []byte, v uint64) []byte { 186*1c12ee1eSDan Willemsen switch { 187*1c12ee1eSDan Willemsen case v < 1<<7: 188*1c12ee1eSDan Willemsen b = append(b, byte(v)) 189*1c12ee1eSDan Willemsen case v < 1<<14: 190*1c12ee1eSDan Willemsen b = append(b, 191*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 192*1c12ee1eSDan Willemsen byte(v>>7)) 193*1c12ee1eSDan Willemsen case v < 1<<21: 194*1c12ee1eSDan Willemsen b = append(b, 195*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 196*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 197*1c12ee1eSDan Willemsen byte(v>>14)) 198*1c12ee1eSDan Willemsen case v < 1<<28: 199*1c12ee1eSDan Willemsen b = append(b, 200*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 201*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 202*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 203*1c12ee1eSDan Willemsen byte(v>>21)) 204*1c12ee1eSDan Willemsen case v < 1<<35: 205*1c12ee1eSDan Willemsen b = append(b, 206*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 207*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 208*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 209*1c12ee1eSDan Willemsen byte((v>>21)&0x7f|0x80), 210*1c12ee1eSDan Willemsen byte(v>>28)) 211*1c12ee1eSDan Willemsen case v < 1<<42: 212*1c12ee1eSDan Willemsen b = append(b, 213*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 214*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 215*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 216*1c12ee1eSDan Willemsen byte((v>>21)&0x7f|0x80), 217*1c12ee1eSDan Willemsen byte((v>>28)&0x7f|0x80), 218*1c12ee1eSDan Willemsen byte(v>>35)) 219*1c12ee1eSDan Willemsen case v < 1<<49: 220*1c12ee1eSDan Willemsen b = append(b, 221*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 222*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 223*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 224*1c12ee1eSDan Willemsen byte((v>>21)&0x7f|0x80), 225*1c12ee1eSDan Willemsen byte((v>>28)&0x7f|0x80), 226*1c12ee1eSDan Willemsen byte((v>>35)&0x7f|0x80), 227*1c12ee1eSDan Willemsen byte(v>>42)) 228*1c12ee1eSDan Willemsen case v < 1<<56: 229*1c12ee1eSDan Willemsen b = append(b, 230*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 231*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 232*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 233*1c12ee1eSDan Willemsen byte((v>>21)&0x7f|0x80), 234*1c12ee1eSDan Willemsen byte((v>>28)&0x7f|0x80), 235*1c12ee1eSDan Willemsen byte((v>>35)&0x7f|0x80), 236*1c12ee1eSDan Willemsen byte((v>>42)&0x7f|0x80), 237*1c12ee1eSDan Willemsen byte(v>>49)) 238*1c12ee1eSDan Willemsen case v < 1<<63: 239*1c12ee1eSDan Willemsen b = append(b, 240*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 241*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 242*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 243*1c12ee1eSDan Willemsen byte((v>>21)&0x7f|0x80), 244*1c12ee1eSDan Willemsen byte((v>>28)&0x7f|0x80), 245*1c12ee1eSDan Willemsen byte((v>>35)&0x7f|0x80), 246*1c12ee1eSDan Willemsen byte((v>>42)&0x7f|0x80), 247*1c12ee1eSDan Willemsen byte((v>>49)&0x7f|0x80), 248*1c12ee1eSDan Willemsen byte(v>>56)) 249*1c12ee1eSDan Willemsen default: 250*1c12ee1eSDan Willemsen b = append(b, 251*1c12ee1eSDan Willemsen byte((v>>0)&0x7f|0x80), 252*1c12ee1eSDan Willemsen byte((v>>7)&0x7f|0x80), 253*1c12ee1eSDan Willemsen byte((v>>14)&0x7f|0x80), 254*1c12ee1eSDan Willemsen byte((v>>21)&0x7f|0x80), 255*1c12ee1eSDan Willemsen byte((v>>28)&0x7f|0x80), 256*1c12ee1eSDan Willemsen byte((v>>35)&0x7f|0x80), 257*1c12ee1eSDan Willemsen byte((v>>42)&0x7f|0x80), 258*1c12ee1eSDan Willemsen byte((v>>49)&0x7f|0x80), 259*1c12ee1eSDan Willemsen byte((v>>56)&0x7f|0x80), 260*1c12ee1eSDan Willemsen 1) 261*1c12ee1eSDan Willemsen } 262*1c12ee1eSDan Willemsen return b 263*1c12ee1eSDan Willemsen} 264*1c12ee1eSDan Willemsen 265*1c12ee1eSDan Willemsen// ConsumeVarint parses b as a varint-encoded uint64, reporting its length. 266*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 267*1c12ee1eSDan Willemsenfunc ConsumeVarint(b []byte) (v uint64, n int) { 268*1c12ee1eSDan Willemsen var y uint64 269*1c12ee1eSDan Willemsen if len(b) <= 0 { 270*1c12ee1eSDan Willemsen return 0, errCodeTruncated 271*1c12ee1eSDan Willemsen } 272*1c12ee1eSDan Willemsen v = uint64(b[0]) 273*1c12ee1eSDan Willemsen if v < 0x80 { 274*1c12ee1eSDan Willemsen return v, 1 275*1c12ee1eSDan Willemsen } 276*1c12ee1eSDan Willemsen v -= 0x80 277*1c12ee1eSDan Willemsen 278*1c12ee1eSDan Willemsen if len(b) <= 1 { 279*1c12ee1eSDan Willemsen return 0, errCodeTruncated 280*1c12ee1eSDan Willemsen } 281*1c12ee1eSDan Willemsen y = uint64(b[1]) 282*1c12ee1eSDan Willemsen v += y << 7 283*1c12ee1eSDan Willemsen if y < 0x80 { 284*1c12ee1eSDan Willemsen return v, 2 285*1c12ee1eSDan Willemsen } 286*1c12ee1eSDan Willemsen v -= 0x80 << 7 287*1c12ee1eSDan Willemsen 288*1c12ee1eSDan Willemsen if len(b) <= 2 { 289*1c12ee1eSDan Willemsen return 0, errCodeTruncated 290*1c12ee1eSDan Willemsen } 291*1c12ee1eSDan Willemsen y = uint64(b[2]) 292*1c12ee1eSDan Willemsen v += y << 14 293*1c12ee1eSDan Willemsen if y < 0x80 { 294*1c12ee1eSDan Willemsen return v, 3 295*1c12ee1eSDan Willemsen } 296*1c12ee1eSDan Willemsen v -= 0x80 << 14 297*1c12ee1eSDan Willemsen 298*1c12ee1eSDan Willemsen if len(b) <= 3 { 299*1c12ee1eSDan Willemsen return 0, errCodeTruncated 300*1c12ee1eSDan Willemsen } 301*1c12ee1eSDan Willemsen y = uint64(b[3]) 302*1c12ee1eSDan Willemsen v += y << 21 303*1c12ee1eSDan Willemsen if y < 0x80 { 304*1c12ee1eSDan Willemsen return v, 4 305*1c12ee1eSDan Willemsen } 306*1c12ee1eSDan Willemsen v -= 0x80 << 21 307*1c12ee1eSDan Willemsen 308*1c12ee1eSDan Willemsen if len(b) <= 4 { 309*1c12ee1eSDan Willemsen return 0, errCodeTruncated 310*1c12ee1eSDan Willemsen } 311*1c12ee1eSDan Willemsen y = uint64(b[4]) 312*1c12ee1eSDan Willemsen v += y << 28 313*1c12ee1eSDan Willemsen if y < 0x80 { 314*1c12ee1eSDan Willemsen return v, 5 315*1c12ee1eSDan Willemsen } 316*1c12ee1eSDan Willemsen v -= 0x80 << 28 317*1c12ee1eSDan Willemsen 318*1c12ee1eSDan Willemsen if len(b) <= 5 { 319*1c12ee1eSDan Willemsen return 0, errCodeTruncated 320*1c12ee1eSDan Willemsen } 321*1c12ee1eSDan Willemsen y = uint64(b[5]) 322*1c12ee1eSDan Willemsen v += y << 35 323*1c12ee1eSDan Willemsen if y < 0x80 { 324*1c12ee1eSDan Willemsen return v, 6 325*1c12ee1eSDan Willemsen } 326*1c12ee1eSDan Willemsen v -= 0x80 << 35 327*1c12ee1eSDan Willemsen 328*1c12ee1eSDan Willemsen if len(b) <= 6 { 329*1c12ee1eSDan Willemsen return 0, errCodeTruncated 330*1c12ee1eSDan Willemsen } 331*1c12ee1eSDan Willemsen y = uint64(b[6]) 332*1c12ee1eSDan Willemsen v += y << 42 333*1c12ee1eSDan Willemsen if y < 0x80 { 334*1c12ee1eSDan Willemsen return v, 7 335*1c12ee1eSDan Willemsen } 336*1c12ee1eSDan Willemsen v -= 0x80 << 42 337*1c12ee1eSDan Willemsen 338*1c12ee1eSDan Willemsen if len(b) <= 7 { 339*1c12ee1eSDan Willemsen return 0, errCodeTruncated 340*1c12ee1eSDan Willemsen } 341*1c12ee1eSDan Willemsen y = uint64(b[7]) 342*1c12ee1eSDan Willemsen v += y << 49 343*1c12ee1eSDan Willemsen if y < 0x80 { 344*1c12ee1eSDan Willemsen return v, 8 345*1c12ee1eSDan Willemsen } 346*1c12ee1eSDan Willemsen v -= 0x80 << 49 347*1c12ee1eSDan Willemsen 348*1c12ee1eSDan Willemsen if len(b) <= 8 { 349*1c12ee1eSDan Willemsen return 0, errCodeTruncated 350*1c12ee1eSDan Willemsen } 351*1c12ee1eSDan Willemsen y = uint64(b[8]) 352*1c12ee1eSDan Willemsen v += y << 56 353*1c12ee1eSDan Willemsen if y < 0x80 { 354*1c12ee1eSDan Willemsen return v, 9 355*1c12ee1eSDan Willemsen } 356*1c12ee1eSDan Willemsen v -= 0x80 << 56 357*1c12ee1eSDan Willemsen 358*1c12ee1eSDan Willemsen if len(b) <= 9 { 359*1c12ee1eSDan Willemsen return 0, errCodeTruncated 360*1c12ee1eSDan Willemsen } 361*1c12ee1eSDan Willemsen y = uint64(b[9]) 362*1c12ee1eSDan Willemsen v += y << 63 363*1c12ee1eSDan Willemsen if y < 2 { 364*1c12ee1eSDan Willemsen return v, 10 365*1c12ee1eSDan Willemsen } 366*1c12ee1eSDan Willemsen return 0, errCodeOverflow 367*1c12ee1eSDan Willemsen} 368*1c12ee1eSDan Willemsen 369*1c12ee1eSDan Willemsen// SizeVarint returns the encoded size of a varint. 370*1c12ee1eSDan Willemsen// The size is guaranteed to be within 1 and 10, inclusive. 371*1c12ee1eSDan Willemsenfunc SizeVarint(v uint64) int { 372*1c12ee1eSDan Willemsen // This computes 1 + (bits.Len64(v)-1)/7. 373*1c12ee1eSDan Willemsen // 9/64 is a good enough approximation of 1/7 374*1c12ee1eSDan Willemsen return int(9*uint32(bits.Len64(v))+64) / 64 375*1c12ee1eSDan Willemsen} 376*1c12ee1eSDan Willemsen 377*1c12ee1eSDan Willemsen// AppendFixed32 appends v to b as a little-endian uint32. 378*1c12ee1eSDan Willemsenfunc AppendFixed32(b []byte, v uint32) []byte { 379*1c12ee1eSDan Willemsen return append(b, 380*1c12ee1eSDan Willemsen byte(v>>0), 381*1c12ee1eSDan Willemsen byte(v>>8), 382*1c12ee1eSDan Willemsen byte(v>>16), 383*1c12ee1eSDan Willemsen byte(v>>24)) 384*1c12ee1eSDan Willemsen} 385*1c12ee1eSDan Willemsen 386*1c12ee1eSDan Willemsen// ConsumeFixed32 parses b as a little-endian uint32, reporting its length. 387*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 388*1c12ee1eSDan Willemsenfunc ConsumeFixed32(b []byte) (v uint32, n int) { 389*1c12ee1eSDan Willemsen if len(b) < 4 { 390*1c12ee1eSDan Willemsen return 0, errCodeTruncated 391*1c12ee1eSDan Willemsen } 392*1c12ee1eSDan Willemsen v = uint32(b[0])<<0 | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 393*1c12ee1eSDan Willemsen return v, 4 394*1c12ee1eSDan Willemsen} 395*1c12ee1eSDan Willemsen 396*1c12ee1eSDan Willemsen// SizeFixed32 returns the encoded size of a fixed32; which is always 4. 397*1c12ee1eSDan Willemsenfunc SizeFixed32() int { 398*1c12ee1eSDan Willemsen return 4 399*1c12ee1eSDan Willemsen} 400*1c12ee1eSDan Willemsen 401*1c12ee1eSDan Willemsen// AppendFixed64 appends v to b as a little-endian uint64. 402*1c12ee1eSDan Willemsenfunc AppendFixed64(b []byte, v uint64) []byte { 403*1c12ee1eSDan Willemsen return append(b, 404*1c12ee1eSDan Willemsen byte(v>>0), 405*1c12ee1eSDan Willemsen byte(v>>8), 406*1c12ee1eSDan Willemsen byte(v>>16), 407*1c12ee1eSDan Willemsen byte(v>>24), 408*1c12ee1eSDan Willemsen byte(v>>32), 409*1c12ee1eSDan Willemsen byte(v>>40), 410*1c12ee1eSDan Willemsen byte(v>>48), 411*1c12ee1eSDan Willemsen byte(v>>56)) 412*1c12ee1eSDan Willemsen} 413*1c12ee1eSDan Willemsen 414*1c12ee1eSDan Willemsen// ConsumeFixed64 parses b as a little-endian uint64, reporting its length. 415*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 416*1c12ee1eSDan Willemsenfunc ConsumeFixed64(b []byte) (v uint64, n int) { 417*1c12ee1eSDan Willemsen if len(b) < 8 { 418*1c12ee1eSDan Willemsen return 0, errCodeTruncated 419*1c12ee1eSDan Willemsen } 420*1c12ee1eSDan Willemsen v = uint64(b[0])<<0 | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 421*1c12ee1eSDan Willemsen return v, 8 422*1c12ee1eSDan Willemsen} 423*1c12ee1eSDan Willemsen 424*1c12ee1eSDan Willemsen// SizeFixed64 returns the encoded size of a fixed64; which is always 8. 425*1c12ee1eSDan Willemsenfunc SizeFixed64() int { 426*1c12ee1eSDan Willemsen return 8 427*1c12ee1eSDan Willemsen} 428*1c12ee1eSDan Willemsen 429*1c12ee1eSDan Willemsen// AppendBytes appends v to b as a length-prefixed bytes value. 430*1c12ee1eSDan Willemsenfunc AppendBytes(b []byte, v []byte) []byte { 431*1c12ee1eSDan Willemsen return append(AppendVarint(b, uint64(len(v))), v...) 432*1c12ee1eSDan Willemsen} 433*1c12ee1eSDan Willemsen 434*1c12ee1eSDan Willemsen// ConsumeBytes parses b as a length-prefixed bytes value, reporting its length. 435*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 436*1c12ee1eSDan Willemsenfunc ConsumeBytes(b []byte) (v []byte, n int) { 437*1c12ee1eSDan Willemsen m, n := ConsumeVarint(b) 438*1c12ee1eSDan Willemsen if n < 0 { 439*1c12ee1eSDan Willemsen return nil, n // forward error code 440*1c12ee1eSDan Willemsen } 441*1c12ee1eSDan Willemsen if m > uint64(len(b[n:])) { 442*1c12ee1eSDan Willemsen return nil, errCodeTruncated 443*1c12ee1eSDan Willemsen } 444*1c12ee1eSDan Willemsen return b[n:][:m], n + int(m) 445*1c12ee1eSDan Willemsen} 446*1c12ee1eSDan Willemsen 447*1c12ee1eSDan Willemsen// SizeBytes returns the encoded size of a length-prefixed bytes value, 448*1c12ee1eSDan Willemsen// given only the length. 449*1c12ee1eSDan Willemsenfunc SizeBytes(n int) int { 450*1c12ee1eSDan Willemsen return SizeVarint(uint64(n)) + n 451*1c12ee1eSDan Willemsen} 452*1c12ee1eSDan Willemsen 453*1c12ee1eSDan Willemsen// AppendString appends v to b as a length-prefixed bytes value. 454*1c12ee1eSDan Willemsenfunc AppendString(b []byte, v string) []byte { 455*1c12ee1eSDan Willemsen return append(AppendVarint(b, uint64(len(v))), v...) 456*1c12ee1eSDan Willemsen} 457*1c12ee1eSDan Willemsen 458*1c12ee1eSDan Willemsen// ConsumeString parses b as a length-prefixed bytes value, reporting its length. 459*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 460*1c12ee1eSDan Willemsenfunc ConsumeString(b []byte) (v string, n int) { 461*1c12ee1eSDan Willemsen bb, n := ConsumeBytes(b) 462*1c12ee1eSDan Willemsen return string(bb), n 463*1c12ee1eSDan Willemsen} 464*1c12ee1eSDan Willemsen 465*1c12ee1eSDan Willemsen// AppendGroup appends v to b as group value, with a trailing end group marker. 466*1c12ee1eSDan Willemsen// The value v must not contain the end marker. 467*1c12ee1eSDan Willemsenfunc AppendGroup(b []byte, num Number, v []byte) []byte { 468*1c12ee1eSDan Willemsen return AppendVarint(append(b, v...), EncodeTag(num, EndGroupType)) 469*1c12ee1eSDan Willemsen} 470*1c12ee1eSDan Willemsen 471*1c12ee1eSDan Willemsen// ConsumeGroup parses b as a group value until the trailing end group marker, 472*1c12ee1eSDan Willemsen// and verifies that the end marker matches the provided num. The value v 473*1c12ee1eSDan Willemsen// does not contain the end marker, while the length does contain the end marker. 474*1c12ee1eSDan Willemsen// This returns a negative length upon an error (see ParseError). 475*1c12ee1eSDan Willemsenfunc ConsumeGroup(num Number, b []byte) (v []byte, n int) { 476*1c12ee1eSDan Willemsen n = ConsumeFieldValue(num, StartGroupType, b) 477*1c12ee1eSDan Willemsen if n < 0 { 478*1c12ee1eSDan Willemsen return nil, n // forward error code 479*1c12ee1eSDan Willemsen } 480*1c12ee1eSDan Willemsen b = b[:n] 481*1c12ee1eSDan Willemsen 482*1c12ee1eSDan Willemsen // Truncate off end group marker, but need to handle denormalized varints. 483*1c12ee1eSDan Willemsen // Assuming end marker is never 0 (which is always the case since 484*1c12ee1eSDan Willemsen // EndGroupType is non-zero), we can truncate all trailing bytes where the 485*1c12ee1eSDan Willemsen // lower 7 bits are all zero (implying that the varint is denormalized). 486*1c12ee1eSDan Willemsen for len(b) > 0 && b[len(b)-1]&0x7f == 0 { 487*1c12ee1eSDan Willemsen b = b[:len(b)-1] 488*1c12ee1eSDan Willemsen } 489*1c12ee1eSDan Willemsen b = b[:len(b)-SizeTag(num)] 490*1c12ee1eSDan Willemsen return b, n 491*1c12ee1eSDan Willemsen} 492*1c12ee1eSDan Willemsen 493*1c12ee1eSDan Willemsen// SizeGroup returns the encoded size of a group, given only the length. 494*1c12ee1eSDan Willemsenfunc SizeGroup(num Number, n int) int { 495*1c12ee1eSDan Willemsen return n + SizeTag(num) 496*1c12ee1eSDan Willemsen} 497*1c12ee1eSDan Willemsen 498*1c12ee1eSDan Willemsen// DecodeTag decodes the field Number and wire Type from its unified form. 499*1c12ee1eSDan Willemsen// The Number is -1 if the decoded field number overflows int32. 500*1c12ee1eSDan Willemsen// Other than overflow, this does not check for field number validity. 501*1c12ee1eSDan Willemsenfunc DecodeTag(x uint64) (Number, Type) { 502*1c12ee1eSDan Willemsen // NOTE: MessageSet allows for larger field numbers than normal. 503*1c12ee1eSDan Willemsen if x>>3 > uint64(math.MaxInt32) { 504*1c12ee1eSDan Willemsen return -1, 0 505*1c12ee1eSDan Willemsen } 506*1c12ee1eSDan Willemsen return Number(x >> 3), Type(x & 7) 507*1c12ee1eSDan Willemsen} 508*1c12ee1eSDan Willemsen 509*1c12ee1eSDan Willemsen// EncodeTag encodes the field Number and wire Type into its unified form. 510*1c12ee1eSDan Willemsenfunc EncodeTag(num Number, typ Type) uint64 { 511*1c12ee1eSDan Willemsen return uint64(num)<<3 | uint64(typ&7) 512*1c12ee1eSDan Willemsen} 513*1c12ee1eSDan Willemsen 514*1c12ee1eSDan Willemsen// DecodeZigZag decodes a zig-zag-encoded uint64 as an int64. 515*1c12ee1eSDan Willemsen// 516*1c12ee1eSDan Willemsen// Input: {…, 5, 3, 1, 0, 2, 4, 6, …} 517*1c12ee1eSDan Willemsen// Output: {…, -3, -2, -1, 0, +1, +2, +3, …} 518*1c12ee1eSDan Willemsenfunc DecodeZigZag(x uint64) int64 { 519*1c12ee1eSDan Willemsen return int64(x>>1) ^ int64(x)<<63>>63 520*1c12ee1eSDan Willemsen} 521*1c12ee1eSDan Willemsen 522*1c12ee1eSDan Willemsen// EncodeZigZag encodes an int64 as a zig-zag-encoded uint64. 523*1c12ee1eSDan Willemsen// 524*1c12ee1eSDan Willemsen// Input: {…, -3, -2, -1, 0, +1, +2, +3, …} 525*1c12ee1eSDan Willemsen// Output: {…, 5, 3, 1, 0, 2, 4, 6, …} 526*1c12ee1eSDan Willemsenfunc EncodeZigZag(x int64) uint64 { 527*1c12ee1eSDan Willemsen return uint64(x<<1) ^ uint64(x>>63) 528*1c12ee1eSDan Willemsen} 529*1c12ee1eSDan Willemsen 530*1c12ee1eSDan Willemsen// DecodeBool decodes a uint64 as a bool. 531*1c12ee1eSDan Willemsen// 532*1c12ee1eSDan Willemsen// Input: { 0, 1, 2, …} 533*1c12ee1eSDan Willemsen// Output: {false, true, true, …} 534*1c12ee1eSDan Willemsenfunc DecodeBool(x uint64) bool { 535*1c12ee1eSDan Willemsen return x != 0 536*1c12ee1eSDan Willemsen} 537*1c12ee1eSDan Willemsen 538*1c12ee1eSDan Willemsen// EncodeBool encodes a bool as a uint64. 539*1c12ee1eSDan Willemsen// 540*1c12ee1eSDan Willemsen// Input: {false, true} 541*1c12ee1eSDan Willemsen// Output: { 0, 1} 542*1c12ee1eSDan Willemsenfunc EncodeBool(x bool) uint64 { 543*1c12ee1eSDan Willemsen if x { 544*1c12ee1eSDan Willemsen return 1 545*1c12ee1eSDan Willemsen } 546*1c12ee1eSDan Willemsen return 0 547*1c12ee1eSDan Willemsen} 548